@@ -138,8 +138,23 @@ namespace ts.codefix {
138
138
139
139
const currentTokenMeaning = getMeaningFromLocation ( token ) ;
140
140
if ( context . errorCode === Diagnostics . _0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead . code ) {
141
- const symbol = checker . getAliasedSymbol ( checker . getSymbolAtLocation ( token ) ) ;
142
- return getCodeActionForImport ( symbol , /*isDefault*/ false , /*isNamespaceImport*/ true ) ;
141
+ const umdSymbol = checker . getSymbolAtLocation ( token ) ;
142
+ let symbol : ts . Symbol ;
143
+ let symbolName : string ;
144
+ if ( umdSymbol . flags & ts . SymbolFlags . Alias ) {
145
+ symbol = checker . getAliasedSymbol ( umdSymbol ) ;
146
+ symbolName = name ;
147
+ }
148
+ else if ( isJsxOpeningLikeElement ( token . parent ) && token . parent . tagName === token ) {
149
+ // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`.
150
+ symbol = checker . getAliasedSymbol ( checker . resolveNameAtLocation ( token , checker . getJsxNamespace ( ) , SymbolFlags . Value ) ) ;
151
+ symbolName = symbol . name ;
152
+ }
153
+ else {
154
+ Debug . fail ( "Either the symbol or the JSX namespace should be a UMD global if we got here" ) ;
155
+ }
156
+
157
+ return getCodeActionForImport ( symbol , symbolName , /*isDefault*/ false , /*isNamespaceImport*/ true ) ;
143
158
}
144
159
145
160
const candidateModules = checker . getAmbientModules ( ) ;
@@ -159,15 +174,15 @@ namespace ts.codefix {
159
174
if ( localSymbol && localSymbol . name === name && checkSymbolHasMeaning ( localSymbol , currentTokenMeaning ) ) {
160
175
// check if this symbol is already used
161
176
const symbolId = getUniqueSymbolId ( localSymbol ) ;
162
- symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , /*isDefault*/ true ) ) ;
177
+ symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , name , /*isDefault*/ true ) ) ;
163
178
}
164
179
}
165
180
166
181
// check exports with the same name
167
182
const exportSymbolWithIdenticalName = checker . tryGetMemberInModuleExports ( name , moduleSymbol ) ;
168
183
if ( exportSymbolWithIdenticalName && checkSymbolHasMeaning ( exportSymbolWithIdenticalName , currentTokenMeaning ) ) {
169
184
const symbolId = getUniqueSymbolId ( exportSymbolWithIdenticalName ) ;
170
- symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol ) ) ;
185
+ symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , name ) ) ;
171
186
}
172
187
}
173
188
@@ -218,7 +233,7 @@ namespace ts.codefix {
218
233
return declarations ? some ( symbol . declarations , decl => ! ! ( getMeaningFromDeclaration ( decl ) & meaning ) ) : false ;
219
234
}
220
235
221
- function getCodeActionForImport ( moduleSymbol : Symbol , isDefault ?: boolean , isNamespaceImport ?: boolean ) : ImportCodeAction [ ] {
236
+ function getCodeActionForImport ( moduleSymbol : Symbol , symbolName : string , isDefault ?: boolean , isNamespaceImport ?: boolean ) : ImportCodeAction [ ] {
222
237
const existingDeclarations = getImportDeclarations ( moduleSymbol ) ;
223
238
if ( existingDeclarations . length > 0 ) {
224
239
// With an existing import statement, there are more than one actions the user can do.
@@ -375,10 +390,10 @@ namespace ts.codefix {
375
390
const moduleSpecifierWithoutQuotes = stripQuotes ( moduleSpecifier || getModuleSpecifierForNewImport ( ) ) ;
376
391
const changeTracker = createChangeTracker ( ) ;
377
392
const importClause = isDefault
378
- ? createImportClause ( createIdentifier ( name ) , /*namedBindings*/ undefined )
393
+ ? createImportClause ( createIdentifier ( symbolName ) , /*namedBindings*/ undefined )
379
394
: isNamespaceImport
380
- ? createImportClause ( /*name*/ undefined , createNamespaceImport ( createIdentifier ( name ) ) )
381
- : createImportClause ( /*name*/ undefined , createNamedImports ( [ createImportSpecifier ( /*propertyName*/ undefined , createIdentifier ( name ) ) ] ) ) ;
395
+ ? createImportClause ( /*name*/ undefined , createNamespaceImport ( createIdentifier ( symbolName ) ) )
396
+ : createImportClause ( /*name*/ undefined , createNamedImports ( [ createImportSpecifier ( /*propertyName*/ undefined , createIdentifier ( symbolName ) ) ] ) ) ;
382
397
const importDecl = createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , importClause , createLiteral ( moduleSpecifierWithoutQuotes ) ) ;
383
398
if ( ! lastImportDeclaration ) {
384
399
changeTracker . insertNodeAt ( sourceFile , sourceFile . getStart ( ) , importDecl , { suffix : `${ context . newLineCharacter } ${ context . newLineCharacter } ` } ) ;
@@ -392,7 +407,7 @@ namespace ts.codefix {
392
407
// are there are already a new line seperating code and import statements.
393
408
return createCodeAction (
394
409
Diagnostics . Import_0_from_1 ,
395
- [ name , `"${ moduleSpecifierWithoutQuotes } "` ] ,
410
+ [ symbolName , `"${ moduleSpecifierWithoutQuotes } "` ] ,
396
411
changeTracker . getChanges ( ) ,
397
412
"NewImport" ,
398
413
moduleSpecifierWithoutQuotes
@@ -412,8 +427,9 @@ namespace ts.codefix {
412
427
removeFileExtension ( getRelativePath ( moduleFileName , sourceDirectory ) ) ;
413
428
414
429
function tryGetModuleNameFromAmbientModule ( ) : string {
415
- if ( moduleSymbol . valueDeclaration . kind !== SyntaxKind . SourceFile ) {
416
- return moduleSymbol . name ;
430
+ const decl = moduleSymbol . valueDeclaration ;
431
+ if ( isModuleDeclaration ( decl ) && isStringLiteral ( decl . name ) ) {
432
+ return decl . name . text ;
417
433
}
418
434
}
419
435
0 commit comments