Add refactoring to use default import (#19659)

* Add refactoring to use default import

* Add localizable description
This commit is contained in:
Andy
2017-11-03 08:31:13 -07:00
committed by GitHub
parent cc2a2a79b5
commit d54ad4b01a
5 changed files with 134 additions and 0 deletions

View File

@@ -2,3 +2,4 @@
/// <reference path="convertFunctionToEs6Class.ts" />
/// <reference path="extractSymbol.ts" />
/// <reference path="installTypesForPackage.ts" />
/// <reference path="useDefaultImport.ts" />

View File

@@ -0,0 +1,96 @@
/* @internal */
namespace ts.refactor.installTypesForPackage {
const actionName = "Convert to default import";
const useDefaultImport: Refactor = {
name: actionName,
description: getLocaleSpecificMessage(Diagnostics.Convert_to_default_import),
getEditsForAction,
getAvailableActions,
};
registerRefactor(useDefaultImport);
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
const { file, startPosition, program } = context;
if (!program.getCompilerOptions().allowSyntheticDefaultImports) {
return undefined;
}
const importInfo = getConvertibleImportAtPosition(file, startPosition);
if (!importInfo) {
return undefined;
}
const module = ts.getResolvedModule(file, importInfo.moduleSpecifier.text);
const resolvedFile = program.getSourceFile(module.resolvedFileName);
if (!(resolvedFile.externalModuleIndicator && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals)) {
return undefined;
}
return [
{
name: useDefaultImport.name,
description: useDefaultImport.description,
actions: [
{
description: useDefaultImport.description,
name: actionName,
},
],
},
];
}
function getEditsForAction(context: RefactorContext, _actionName: string): RefactorEditInfo | undefined {
const { file, startPosition } = context;
Debug.assertEqual(actionName, _actionName);
const importInfo = getConvertibleImportAtPosition(file, startPosition);
if (!importInfo) {
return undefined;
}
const { importStatement, name, moduleSpecifier } = importInfo;
const newImportClause = createImportClause(name, /*namedBindings*/ undefined);
const newImportStatement = ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newImportClause, moduleSpecifier);
return {
edits: textChanges.ChangeTracker.with(context, t => t.replaceNode(file, importStatement, newImportStatement)),
renameFilename: undefined,
renameLocation: undefined,
};
}
function getConvertibleImportAtPosition(
file: SourceFile,
startPosition: number,
): { importStatement: AnyImportSyntax, name: Identifier, moduleSpecifier: StringLiteral } | undefined {
let node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
while (true) {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
const eq = node as ImportEqualsDeclaration;
const { moduleReference } = eq;
return moduleReference.kind === SyntaxKind.ExternalModuleReference && isStringLiteral(moduleReference.expression)
? { importStatement: eq, name: eq.name, moduleSpecifier: moduleReference.expression }
: undefined;
case SyntaxKind.ImportDeclaration:
const d = node as ImportDeclaration;
const { importClause } = d;
return !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(d.moduleSpecifier)
? { importStatement: d, name: importClause.namedBindings.name, moduleSpecifier: d.moduleSpecifier }
: undefined;
// For known child node kinds of convertible imports, try again with parent node.
case SyntaxKind.NamespaceImport:
case SyntaxKind.ExternalModuleReference:
case SyntaxKind.ImportKeyword:
case SyntaxKind.Identifier:
case SyntaxKind.StringLiteral:
case SyntaxKind.AsteriskToken:
break;
default:
return undefined;
}
node = node.parent;
}
}
}