1/* @internal */ 2namespace ts.codefix { 3 const fixName = "invalidImportSyntax"; 4 5 function getCodeFixesForImportDeclaration(context: CodeFixContext, node: ImportDeclaration): CodeFixAction[] { 6 const sourceFile = getSourceFileOfNode(node); 7 const namespace = getNamespaceDeclarationNode(node) as NamespaceImport; 8 const opts = context.program.getCompilerOptions(); 9 const variations: CodeFixAction[] = []; 10 11 // import Bluebird from "bluebird"; 12 variations.push(createAction(context, sourceFile, node, makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, getQuotePreference(sourceFile, context.preferences)))); 13 14 if (getEmitModuleKind(opts) === ModuleKind.CommonJS) { 15 // import Bluebird = require("bluebird"); 16 variations.push(createAction(context, sourceFile, node, factory.createImportEqualsDeclaration( 17 /*decorators*/ undefined, 18 /*modifiers*/ undefined, 19 /*isTypeOnly*/ false, 20 namespace.name, 21 factory.createExternalModuleReference(node.moduleSpecifier) 22 ))); 23 } 24 25 return variations; 26 } 27 28 function createAction(context: CodeFixContext, sourceFile: SourceFile, node: Node, replacement: Node): CodeFixAction { 29 const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, node, replacement)); 30 return createCodeFixActionWithoutFixAll(fixName, changes, [Diagnostics.Replace_import_with_0, changes[0].textChanges[0].newText]); 31 } 32 33 registerCodeFix({ 34 errorCodes: [ 35 Diagnostics.This_expression_is_not_callable.code, 36 Diagnostics.This_expression_is_not_constructable.code, 37 ], 38 getCodeActions: getActionsForUsageOfInvalidImport 39 }); 40 41 function getActionsForUsageOfInvalidImport(context: CodeFixContext): CodeFixAction[] | undefined { 42 const sourceFile = context.sourceFile; 43 const targetKind = Diagnostics.This_expression_is_not_callable.code === context.errorCode ? SyntaxKind.CallExpression : SyntaxKind.NewExpression; 44 const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start), a => a.kind === targetKind) as CallExpression | NewExpression; 45 if (!node) { 46 return []; 47 } 48 const expr = node.expression; 49 return getImportCodeFixesForExpression(context, expr); 50 } 51 52 registerCodeFix({ 53 errorCodes: [ 54 // The following error codes cover pretty much all assignability errors that could involve an expression 55 Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code, 56 Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code, 57 Diagnostics.Type_0_is_not_assignable_to_type_1.code, 58 Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated.code, 59 Diagnostics.Type_predicate_0_is_not_assignable_to_1.code, 60 Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2.code, 61 Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2.code, 62 Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1.code, 63 Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2.code, 64 Diagnostics.Property_0_in_type_1_is_not_assignable_to_type_2.code, 65 Diagnostics.Property_0_of_JSX_spread_attribute_is_not_assignable_to_target_property.code, 66 Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1.code, 67 ], 68 getCodeActions: getActionsForInvalidImportLocation 69 }); 70 71 function getActionsForInvalidImportLocation(context: CodeFixContext): CodeFixAction[] | undefined { 72 const sourceFile = context.sourceFile; 73 const node = findAncestor(getTokenAtPosition(sourceFile, context.span.start), a => a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length)); 74 if (!node) { 75 return []; 76 } 77 return getImportCodeFixesForExpression(context, node); 78 } 79 80 function getImportCodeFixesForExpression(context: CodeFixContext, expr: Node): CodeFixAction[] | undefined { 81 const type = context.program.getTypeChecker().getTypeAtLocation(expr); 82 if (!(type.symbol && (type.symbol as TransientSymbol).originatingImport)) { 83 return []; 84 } 85 const fixes: CodeFixAction[] = []; 86 const relatedImport = (type.symbol as TransientSymbol).originatingImport!; // TODO: GH#18217 87 if (!isImportCall(relatedImport)) { 88 addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport)); 89 } 90 if (isExpression(expr) && !(isNamedDeclaration(expr.parent) && expr.parent.name === expr)) { 91 const sourceFile = context.sourceFile; 92 const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, factory.createPropertyAccessExpression(expr, "default"), {})); 93 fixes.push(createCodeFixActionWithoutFixAll(fixName, changes, Diagnostics.Use_synthetic_default_member)); 94 } 95 return fixes; 96 } 97} 98