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