@@ -138,8 +138,23 @@ namespace ts.codefix {
138138
139139 const currentTokenMeaning = getMeaningFromLocation ( token ) ;
140140 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 ) ;
143158 }
144159
145160 const candidateModules = checker . getAmbientModules ( ) ;
@@ -159,15 +174,15 @@ namespace ts.codefix {
159174 if ( localSymbol && localSymbol . name === name && checkSymbolHasMeaning ( localSymbol , currentTokenMeaning ) ) {
160175 // check if this symbol is already used
161176 const symbolId = getUniqueSymbolId ( localSymbol ) ;
162- symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , /*isDefault*/ true ) ) ;
177+ symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , name , /*isDefault*/ true ) ) ;
163178 }
164179 }
165180
166181 // check exports with the same name
167182 const exportSymbolWithIdenticalName = checker . tryGetMemberInModuleExports ( name , moduleSymbol ) ;
168183 if ( exportSymbolWithIdenticalName && checkSymbolHasMeaning ( exportSymbolWithIdenticalName , currentTokenMeaning ) ) {
169184 const symbolId = getUniqueSymbolId ( exportSymbolWithIdenticalName ) ;
170- symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol ) ) ;
185+ symbolIdActionMap . addActions ( symbolId , getCodeActionForImport ( moduleSymbol , name ) ) ;
171186 }
172187 }
173188
@@ -218,7 +233,7 @@ namespace ts.codefix {
218233 return declarations ? some ( symbol . declarations , decl => ! ! ( getMeaningFromDeclaration ( decl ) & meaning ) ) : false ;
219234 }
220235
221- function getCodeActionForImport ( moduleSymbol : Symbol , isDefault ?: boolean , isNamespaceImport ?: boolean ) : ImportCodeAction [ ] {
236+ function getCodeActionForImport ( moduleSymbol : Symbol , symbolName : string , isDefault ?: boolean , isNamespaceImport ?: boolean ) : ImportCodeAction [ ] {
222237 const existingDeclarations = getImportDeclarations ( moduleSymbol ) ;
223238 if ( existingDeclarations . length > 0 ) {
224239 // With an existing import statement, there are more than one actions the user can do.
@@ -375,10 +390,10 @@ namespace ts.codefix {
375390 const moduleSpecifierWithoutQuotes = stripQuotes ( moduleSpecifier || getModuleSpecifierForNewImport ( ) ) ;
376391 const changeTracker = createChangeTracker ( ) ;
377392 const importClause = isDefault
378- ? createImportClause ( createIdentifier ( name ) , /*namedBindings*/ undefined )
393+ ? createImportClause ( createIdentifier ( symbolName ) , /*namedBindings*/ undefined )
379394 : 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 ) ) ] ) ) ;
382397 const importDecl = createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , importClause , createLiteral ( moduleSpecifierWithoutQuotes ) ) ;
383398 if ( ! lastImportDeclaration ) {
384399 changeTracker . insertNodeAt ( sourceFile , sourceFile . getStart ( ) , importDecl , { suffix : `${ context . newLineCharacter } ${ context . newLineCharacter } ` } ) ;
@@ -392,7 +407,7 @@ namespace ts.codefix {
392407 // are there are already a new line seperating code and import statements.
393408 return createCodeAction (
394409 Diagnostics . Import_0_from_1 ,
395- [ name , `"${ moduleSpecifierWithoutQuotes } "` ] ,
410+ [ symbolName , `"${ moduleSpecifierWithoutQuotes } "` ] ,
396411 changeTracker . getChanges ( ) ,
397412 "NewImport" ,
398413 moduleSpecifierWithoutQuotes
@@ -412,8 +427,9 @@ namespace ts.codefix {
412427 removeFileExtension ( getRelativePath ( moduleFileName , sourceDirectory ) ) ;
413428
414429 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 ;
417433 }
418434 }
419435
0 commit comments