@@ -80,12 +80,15 @@ import {
8080 ImportSpecifier ,
8181 insertImports ,
8282 InternalSymbolName ,
83+ isDefaultImport ,
8384 isExternalModuleReference ,
8485 isFullSourceFile ,
8586 isIdentifier ,
8687 isImportable ,
88+ isImportClause ,
8789 isImportDeclaration ,
8890 isImportEqualsDeclaration ,
91+ isImportSpecifier ,
8992 isIntrinsicJsxName ,
9093 isJSDocImportTag ,
9194 isJsxClosingElement ,
@@ -228,6 +231,7 @@ export interface ImportAdder {
228231 addImportFromDiagnostic : ( diagnostic : DiagnosticWithLocation , context : CodeFixContextBase ) => void ;
229232 addImportFromExportedSymbol : ( exportedSymbol : Symbol , isValidTypeOnlyUseSite ?: boolean , referenceImport ?: ImportOrRequireAliasDeclaration ) => void ;
230233 addImportForNonExistentExport : ( exportName : string , exportingFileName : string , exportKind : ExportKind , exportedMeanings : SymbolFlags , isImportUsageValidAsTypeOnly : boolean ) => void ;
234+ addImportForModuleSymbol : ( symbolAlias : Symbol , isValidTypeOnlyUseSite : boolean , referenceImport : ImportOrRequireAliasDeclaration ) => void ;
231235 addImportForUnresolvedIdentifier : ( context : CodeFixContextBase , symbolToken : Identifier , useAutoImportProvider : boolean ) => void ;
232236 addVerbatimImport : ( declaration : AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration ) => void ;
233237 removeExistingImport : ( declaration : ImportOrRequireAliasDeclaration ) => void ;
@@ -257,7 +261,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
257261 type NewImportsKey = `${0 | 1 } |${string } `;
258262 /** Use `getNewImportEntry` for access */
259263 const newImports = new Map < NewImportsKey , Mutable < ImportsCollection & { useRequire : boolean ; } > > ( ) ;
260- return { addImportFromDiagnostic, addImportFromExportedSymbol, writeFixes, hasFixes, addImportForUnresolvedIdentifier, addImportForNonExistentExport, removeExistingImport, addVerbatimImport } ;
264+ return { addImportFromDiagnostic, addImportFromExportedSymbol, addImportForModuleSymbol , writeFixes, hasFixes, addImportForUnresolvedIdentifier, addImportForNonExistentExport, removeExistingImport, addVerbatimImport } ;
261265
262266 function addVerbatimImport ( declaration : AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration ) {
263267 verbatimImports . add ( declaration ) ;
@@ -276,7 +280,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
276280 }
277281
278282 function addImportFromExportedSymbol ( exportedSymbol : Symbol , isValidTypeOnlyUseSite ?: boolean , referenceImport ?: ImportOrRequireAliasDeclaration ) {
279- const moduleSymbol = Debug . checkDefined ( exportedSymbol . parent ) ;
283+ const moduleSymbol = Debug . checkDefined ( exportedSymbol . parent , "Expected exported symbol to have module symbol as parent" ) ;
280284 const symbolName = getNameForExportedSymbol ( exportedSymbol , getEmitScriptTarget ( compilerOptions ) ) ;
281285 const checker = program . getTypeChecker ( ) ;
282286 const symbol = checker . getMergedSymbol ( skipAlias ( exportedSymbol , checker ) ) ;
@@ -317,6 +321,74 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
317321 }
318322 }
319323
324+ function addImportForModuleSymbol ( symbolAlias : Symbol , isValidTypeOnlyUseSite : boolean , referenceImport : ImportOrRequireAliasDeclaration ) {
325+ // Adds import for module, import alias will be symbolAlias.name
326+ const checker = program . getTypeChecker ( ) ;
327+ const moduleSymbol = checker . getAliasedSymbol ( symbolAlias ) ;
328+ Debug . assert ( moduleSymbol . flags & SymbolFlags . Module , "Expected symbol to be a module" ) ;
329+ const moduleSpecifierResolutionHost = createModuleSpecifierResolutionHost ( program , host ) ;
330+ const moduleSpecifierResult = moduleSpecifiers . getModuleSpecifiersWithCacheInfo ( moduleSymbol , checker , compilerOptions , sourceFile , moduleSpecifierResolutionHost , preferences , /*options*/ undefined , /*forAutoImport*/ true ) ;
331+
332+ const useRequire = shouldUseRequire ( sourceFile , program ) ;
333+
334+ // Copy the type-only status from the reference import
335+ let addAsTypeOnly = getAddAsTypeOnly (
336+ isValidTypeOnlyUseSite ,
337+ /*isForNewImportDeclaration*/ true ,
338+ /*symbol*/ undefined ,
339+ symbolAlias . flags ,
340+ program . getTypeChecker ( ) ,
341+ compilerOptions ,
342+ ) ;
343+ addAsTypeOnly = addAsTypeOnly === AddAsTypeOnly . Allowed && isTypeOnlyImportDeclaration ( referenceImport ) ? AddAsTypeOnly . Required : AddAsTypeOnly . Allowed ;
344+
345+ // Copy the kind of import
346+ const importKind = isImportDeclaration ( referenceImport ) ?
347+ isDefaultImport ( referenceImport ) ? ImportKind . Default : ImportKind . Namespace :
348+ isImportSpecifier ( referenceImport ) ? ImportKind . Named :
349+ isImportClause ( referenceImport ) && ! ! referenceImport . name ? ImportKind . Default : ImportKind . Namespace ;
350+
351+ const exportInfo = [ {
352+ symbol : symbolAlias ,
353+ moduleSymbol,
354+ moduleFileName : moduleSymbol . declarations ?. [ 0 ] ?. getSourceFile ( ) ?. fileName ,
355+ exportKind : ExportKind . Module ,
356+ targetFlags : symbolAlias . flags ,
357+ isFromPackageJson : false ,
358+ } ] ;
359+
360+ const existingFix = getImportFixForSymbol (
361+ sourceFile ,
362+ exportInfo ,
363+ program ,
364+ /*position*/ undefined ,
365+ ! ! isValidTypeOnlyUseSite ,
366+ useRequire ,
367+ host ,
368+ preferences ,
369+ ) ;
370+
371+ let fix : FixAddNewImport | ImportFixWithModuleSpecifier ;
372+ if ( existingFix && importKind !== ImportKind . Namespace ) {
373+ fix = {
374+ ...existingFix ,
375+ addAsTypeOnly,
376+ importKind,
377+ } ;
378+ }
379+ else {
380+ fix = {
381+ kind : ImportFixKind . AddNew ,
382+ moduleSpecifierKind : existingFix !== undefined ? existingFix . moduleSpecifierKind : moduleSpecifierResult . kind ,
383+ moduleSpecifier : existingFix !== undefined ? existingFix . moduleSpecifier : first ( moduleSpecifierResult . moduleSpecifiers ) ,
384+ importKind,
385+ addAsTypeOnly,
386+ useRequire,
387+ } ;
388+ }
389+ addImport ( { fix, symbolName : symbolAlias . name , errorIdentifierText : undefined } ) ;
390+ }
391+
320392 function addImportForNonExistentExport ( exportName : string , exportingFileName : string , exportKind : ExportKind , exportedMeanings : SymbolFlags , isImportUsageValidAsTypeOnly : boolean ) {
321393 const exportingSourceFile = program . getSourceFile ( exportingFileName ) ;
322394 const useRequire = shouldUseRequire ( sourceFile , program ) ;
@@ -1452,6 +1524,8 @@ export function getImportKind(importingFile: SourceFile | FutureSourceFile, expo
14521524 return getExportEqualsImportKind ( importingFile , program . getCompilerOptions ( ) , ! ! forceImportKeyword ) ;
14531525 case ExportKind . UMD :
14541526 return getUmdImportKind ( importingFile , program , ! ! forceImportKeyword ) ;
1527+ case ExportKind . Module :
1528+ return ImportKind . Namespace ;
14551529 default :
14561530 return Debug . assertNever ( exportKind ) ;
14571531 }
0 commit comments