@@ -4,12 +4,13 @@ namespace ts.codefix {
4
4
const errorCodes = [
5
5
Diagnostics . Property_0_does_not_exist_on_type_1_Did_you_mean_2 . code ,
6
6
Diagnostics . Cannot_find_name_0_Did_you_mean_1 . code ,
7
+ Diagnostics . Module_0_has_no_exported_member_1_Did_you_mean_2 . code ,
7
8
] ;
8
9
registerCodeFix ( {
9
10
errorCodes,
10
11
getCodeActions ( context ) {
11
12
const { sourceFile } = context ;
12
- const info = getInfo ( sourceFile , context . span . start , context . program . getTypeChecker ( ) ) ;
13
+ const info = getInfo ( sourceFile , context . span . start , context ) ;
13
14
if ( ! info ) return undefined ;
14
15
const { node, suggestion } = info ;
15
16
const changes = textChanges . ChangeTracker . with ( context , t => doChange ( t , sourceFile , node , suggestion ) ) ;
@@ -18,23 +19,32 @@ namespace ts.codefix {
18
19
} ,
19
20
fixIds : [ fixId ] ,
20
21
getAllCodeActions : context => codeFixAll ( context , errorCodes , ( changes , diag ) => {
21
- const info = getInfo ( diag . file ! , diag . start ! , context . program . getTypeChecker ( ) ) ;
22
+ const info = getInfo ( diag . file ! , diag . start ! , context ) ;
22
23
if ( info ) doChange ( changes , context . sourceFile , info . node , info . suggestion ) ;
23
24
} ) ,
24
25
} ) ;
25
26
26
- function getInfo ( sourceFile : SourceFile , pos : number , checker : TypeChecker ) : { node : Node , suggestion : string } | undefined {
27
+ function getInfo ( sourceFile : SourceFile , pos : number , context : CodeFixContextBase ) : { node : Node , suggestion : string } | undefined {
27
28
// This is the identifier of the misspelled word. eg:
28
29
// this.speling = 1;
29
30
// ^^^^^^^
30
31
const node = getTokenAtPosition ( sourceFile , pos , /*includeJsDocComment*/ false ) ; // TODO: GH#15852
32
+ const checker = context . program . getTypeChecker ( ) ;
31
33
32
34
let suggestion : string ;
33
35
if ( isPropertyAccessExpression ( node . parent ) && node . parent . name === node ) {
34
36
Debug . assert ( node . kind === SyntaxKind . Identifier ) ;
35
37
const containingType = checker . getTypeAtLocation ( node . parent . expression ) ;
36
38
suggestion = checker . getSuggestionForNonexistentProperty ( node as Identifier , containingType ) ;
37
39
}
40
+ else if ( isImportSpecifier ( node . parent ) && node . parent . name === node ) {
41
+ Debug . assert ( node . kind === SyntaxKind . Identifier ) ;
42
+ const importDeclaration = findAncestor ( node , isImportDeclaration ) ;
43
+ const resolvedSourceFile = getResolvedSourceFileFromImportDeclaration ( sourceFile , context , importDeclaration ) ;
44
+ if ( resolvedSourceFile && resolvedSourceFile . symbol ) {
45
+ suggestion = checker . getSuggestionForNonexistentModule ( node as Identifier , resolvedSourceFile . symbol ) ;
46
+ }
47
+ }
38
48
else {
39
49
const meaning = getMeaningFromLocation ( node ) ;
40
50
const name = getTextOfNode ( node ) ;
@@ -62,4 +72,13 @@ namespace ts.codefix {
62
72
}
63
73
return flags ;
64
74
}
75
+
76
+ function getResolvedSourceFileFromImportDeclaration ( sourceFile : SourceFile , context : CodeFixContextBase , importDeclaration : ImportDeclaration ) : SourceFile | undefined {
77
+ if ( ! importDeclaration || ! isStringLiteralLike ( importDeclaration . moduleSpecifier ) ) return undefined ;
78
+
79
+ const resolvedModule = getResolvedModule ( sourceFile , importDeclaration . moduleSpecifier . text ) ;
80
+ if ( ! resolvedModule ) return undefined ;
81
+
82
+ return context . program . getSourceFile ( resolvedModule . resolvedFileName ) ;
83
+ }
65
84
}
0 commit comments