@@ -80,12 +80,15 @@ import {
80
80
ImportSpecifier ,
81
81
insertImports ,
82
82
InternalSymbolName ,
83
+ isDefaultImport ,
83
84
isExternalModuleReference ,
84
85
isFullSourceFile ,
85
86
isIdentifier ,
86
87
isImportable ,
88
+ isImportClause ,
87
89
isImportDeclaration ,
88
90
isImportEqualsDeclaration ,
91
+ isImportSpecifier ,
89
92
isIntrinsicJsxName ,
90
93
isJSDocImportTag ,
91
94
isJsxClosingElement ,
@@ -228,6 +231,7 @@ export interface ImportAdder {
228
231
addImportFromDiagnostic : ( diagnostic : DiagnosticWithLocation , context : CodeFixContextBase ) => void ;
229
232
addImportFromExportedSymbol : ( exportedSymbol : Symbol , isValidTypeOnlyUseSite ?: boolean , referenceImport ?: ImportOrRequireAliasDeclaration ) => void ;
230
233
addImportForNonExistentExport : ( exportName : string , exportingFileName : string , exportKind : ExportKind , exportedMeanings : SymbolFlags , isImportUsageValidAsTypeOnly : boolean ) => void ;
234
+ addImportForModuleSymbol : ( symbolAlias : Symbol , isValidTypeOnlyUseSite : boolean , referenceImport : ImportOrRequireAliasDeclaration ) => void ;
231
235
addImportForUnresolvedIdentifier : ( context : CodeFixContextBase , symbolToken : Identifier , useAutoImportProvider : boolean ) => void ;
232
236
addVerbatimImport : ( declaration : AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration ) => void ;
233
237
removeExistingImport : ( declaration : ImportOrRequireAliasDeclaration ) => void ;
@@ -257,7 +261,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
257
261
type NewImportsKey = `${0 | 1 } |${string } `;
258
262
/** Use `getNewImportEntry` for access */
259
263
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 } ;
261
265
262
266
function addVerbatimImport ( declaration : AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration ) {
263
267
verbatimImports . add ( declaration ) ;
@@ -276,7 +280,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
276
280
}
277
281
278
282
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" ) ;
280
284
const symbolName = getNameForExportedSymbol ( exportedSymbol , getEmitScriptTarget ( compilerOptions ) ) ;
281
285
const checker = program . getTypeChecker ( ) ;
282
286
const symbol = checker . getMergedSymbol ( skipAlias ( exportedSymbol , checker ) ) ;
@@ -317,6 +321,74 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog
317
321
}
318
322
}
319
323
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
+
320
392
function addImportForNonExistentExport ( exportName : string , exportingFileName : string , exportKind : ExportKind , exportedMeanings : SymbolFlags , isImportUsageValidAsTypeOnly : boolean ) {
321
393
const exportingSourceFile = program . getSourceFile ( exportingFileName ) ;
322
394
const useRequire = shouldUseRequire ( sourceFile , program ) ;
@@ -1452,6 +1524,8 @@ export function getImportKind(importingFile: SourceFile | FutureSourceFile, expo
1452
1524
return getExportEqualsImportKind ( importingFile , program . getCompilerOptions ( ) , ! ! forceImportKeyword ) ;
1453
1525
case ExportKind . UMD :
1454
1526
return getUmdImportKind ( importingFile , program , ! ! forceImportKeyword ) ;
1527
+ case ExportKind . Module :
1528
+ return ImportKind . Namespace ;
1455
1529
default :
1456
1530
return Debug . assertNever ( exportKind ) ;
1457
1531
}
0 commit comments