@@ -283,25 +283,13 @@ namespace ts.codefix {
283
283
preferences : UserPreferences ,
284
284
) : ReadonlyArray < FixAddNewImport | FixUseImportType > {
285
285
const isJs = isSourceFileJS ( sourceFile ) ;
286
- const { allowsImporting } = createLazyPackageJsonDependencyReader ( sourceFile , host ) ;
287
286
const choicesForEachExportingModule = flatMap ( moduleSymbols , ( { moduleSymbol, importKind, exportedSymbolIsTypeOnly } ) =>
288
287
moduleSpecifiers . getModuleSpecifiers ( moduleSymbol , program . getCompilerOptions ( ) , sourceFile , host , program . getSourceFiles ( ) , preferences , program . redirectTargetsMap )
289
288
. map ( ( moduleSpecifier ) : FixAddNewImport | FixUseImportType =>
290
289
// `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types.
291
290
exportedSymbolIsTypeOnly && isJs ? { kind : ImportFixKind . ImportType , moduleSpecifier, position : Debug . assertDefined ( position ) } : { kind : ImportFixKind . AddNew , moduleSpecifier, importKind } ) ) ;
292
-
293
- // Sort by presence in package.json, then shortest paths first
294
- return sort ( choicesForEachExportingModule , ( a , b ) => {
295
- const allowsImportingA = allowsImporting ( a . moduleSpecifier ) ;
296
- const allowsImportingB = allowsImporting ( b . moduleSpecifier ) ;
297
- if ( allowsImportingA && ! allowsImportingB ) {
298
- return - 1 ;
299
- }
300
- if ( allowsImportingB && ! allowsImportingA ) {
301
- return 1 ;
302
- }
303
- return a . moduleSpecifier . length - b . moduleSpecifier . length ;
304
- } ) ;
291
+ // Sort to keep the shortest paths first
292
+ return sort ( choicesForEachExportingModule , ( a , b ) => a . moduleSpecifier . length - b . moduleSpecifier . length ) ;
305
293
}
306
294
307
295
function getFixesForAddImport (
@@ -392,8 +380,7 @@ namespace ts.codefix {
392
380
// "default" is a keyword and not a legal identifier for the import, so we don't expect it here
393
381
Debug . assert ( symbolName !== InternalSymbolName . Default ) ;
394
382
395
- const exportInfos = getExportInfos ( symbolName , getMeaningFromLocation ( symbolToken ) , cancellationToken , sourceFile , checker , program , preferences , host ) ;
396
- const fixes = arrayFrom ( flatMapIterator ( exportInfos . entries ( ) , ( [ _ , exportInfos ] ) =>
383
+ const fixes = arrayFrom ( flatMapIterator ( getExportInfos ( symbolName , getMeaningFromLocation ( symbolToken ) , cancellationToken , sourceFile , checker , program ) . entries ( ) , ( [ _ , exportInfos ] ) =>
397
384
getFixForImport ( exportInfos , symbolName , symbolToken . getStart ( sourceFile ) , program , sourceFile , host , preferences ) ) ) ;
398
385
return { fixes, symbolName } ;
399
386
}
@@ -406,16 +393,14 @@ namespace ts.codefix {
406
393
sourceFile : SourceFile ,
407
394
checker : TypeChecker ,
408
395
program : Program ,
409
- preferences : UserPreferences ,
410
- host : LanguageServiceHost
411
396
) : ReadonlyMap < ReadonlyArray < SymbolExportInfo > > {
412
397
// For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once.
413
398
// Maps symbol id to info for modules providing that symbol (original export + re-exports).
414
399
const originalSymbolToExportInfos = createMultiMap < SymbolExportInfo > ( ) ;
415
400
function addSymbol ( moduleSymbol : Symbol , exportedSymbol : Symbol , importKind : ImportKind ) : void {
416
401
originalSymbolToExportInfos . add ( getUniqueSymbolId ( exportedSymbol , checker ) . toString ( ) , { moduleSymbol, importKind, exportedSymbolIsTypeOnly : isTypeOnlySymbol ( exportedSymbol , checker ) } ) ;
417
402
}
418
- forEachExternalModuleToImportFrom ( checker , host , preferences , program . redirectTargetsMap , sourceFile , program . getSourceFiles ( ) , moduleSymbol => {
403
+ forEachExternalModuleToImportFrom ( checker , sourceFile , program . getSourceFiles ( ) , moduleSymbol => {
419
404
cancellationToken . throwIfCancellationRequested ( ) ;
420
405
421
406
const defaultInfo = getDefaultLikeExportInfo ( moduleSymbol , checker , program . getCompilerOptions ( ) ) ;
@@ -576,44 +561,12 @@ namespace ts.codefix {
576
561
return some ( declarations , decl => ! ! ( getMeaningFromDeclaration ( decl ) & meaning ) ) ;
577
562
}
578
563
579
- export function forEachExternalModuleToImportFrom ( checker : TypeChecker , host : LanguageServiceHost , preferences : UserPreferences , redirectTargetsMap : RedirectTargetsMap , from : SourceFile , allSourceFiles : ReadonlyArray < SourceFile > , cb : ( module : Symbol ) => void ) {
580
- const { allowsImporting } = createLazyPackageJsonDependencyReader ( from , host ) ;
581
- const compilerOptions = host . getCompilationSettings ( ) ;
582
- const getCanonicalFileName = hostGetCanonicalFileName ( host ) ;
564
+ export function forEachExternalModuleToImportFrom ( checker : TypeChecker , from : SourceFile , allSourceFiles : ReadonlyArray < SourceFile > , cb : ( module : Symbol ) => void ) {
583
565
forEachExternalModule ( checker , allSourceFiles , ( module , sourceFile ) => {
584
- if ( sourceFile === undefined && allowsImporting ( stripQuotes ( module . getName ( ) ) ) ) {
566
+ if ( sourceFile === undefined || sourceFile !== from && isImportablePath ( from . fileName , sourceFile . fileName ) ) {
585
567
cb ( module ) ;
586
568
}
587
- else if ( sourceFile && sourceFile !== from && isImportablePath ( from . fileName , sourceFile . fileName ) ) {
588
- const moduleSpecifier = getNodeModulesPackageNameFromFileName ( sourceFile . fileName ) ;
589
- if ( ! moduleSpecifier || allowsImporting ( moduleSpecifier ) ) {
590
- cb ( module ) ;
591
- }
592
- }
593
569
} ) ;
594
-
595
- function getNodeModulesPackageNameFromFileName ( importedFileName : string ) : string | undefined {
596
- const specifier = moduleSpecifiers . getModuleSpecifier (
597
- compilerOptions ,
598
- from ,
599
- toPath ( from . fileName , /*basePath*/ undefined , getCanonicalFileName ) ,
600
- importedFileName ,
601
- host ,
602
- allSourceFiles ,
603
- preferences ,
604
- redirectTargetsMap ) ;
605
-
606
- // Paths here are not node_modules, so we don’t care about them;
607
- // returning anything will trigger a lookup in package.json.
608
- if ( ! pathIsRelative ( specifier ) && ! isRootedDiskPath ( specifier ) ) {
609
- const components = getPathComponents ( getPackageNameFromTypesPackageName ( specifier ) ) . slice ( 1 ) ;
610
- // Scoped packages
611
- if ( startsWith ( components [ 0 ] , "@" ) ) {
612
- return `${ components [ 0 ] } /${ components [ 1 ] } ` ;
613
- }
614
- return components [ 0 ] ;
615
- }
616
- }
617
570
}
618
571
619
572
function forEachExternalModule ( checker : TypeChecker , allSourceFiles : ReadonlyArray < SourceFile > , cb : ( module : Symbol , sourceFile : SourceFile | undefined ) => void ) {
@@ -667,69 +620,4 @@ namespace ts.codefix {
667
620
// Need `|| "_"` to ensure result isn't empty.
668
621
return ! isStringANonContextualKeyword ( res ) ? res || "_" : `_${ res } ` ;
669
622
}
670
-
671
- function createLazyPackageJsonDependencyReader ( fromFile : SourceFile , host : LanguageServiceHost ) {
672
- const packageJsonPaths = findPackageJsons ( getDirectoryPath ( fromFile . fileName ) , host ) ;
673
- const dependencyIterator = readPackageJsonDependencies ( host , packageJsonPaths ) ;
674
- let seenDeps : Map < true > | undefined ;
675
- let usesNodeCoreModules : boolean | undefined ;
676
- return { allowsImporting } ;
677
-
678
- function containsDependency ( dependency : string ) {
679
- if ( ( seenDeps || ( seenDeps = createMap ( ) ) ) . has ( dependency ) ) {
680
- return true ;
681
- }
682
- let packageName : string | void ;
683
- while ( packageName = dependencyIterator . next ( ) . value ) {
684
- seenDeps . set ( packageName , true ) ;
685
- if ( packageName === dependency ) {
686
- return true ;
687
- }
688
- }
689
- return false ;
690
- }
691
-
692
- function allowsImporting ( moduleSpecifier : string ) : boolean {
693
- if ( ! packageJsonPaths . length ) {
694
- return true ;
695
- }
696
-
697
- // If we’re in JavaScript, it can be difficult to tell whether the user wants to import
698
- // from Node core modules or not. We can start by seeing if the user is actually using
699
- // any node core modules, as opposed to simply having @types/node accidentally as a
700
- // dependency of a dependency.
701
- if ( isSourceFileJS ( fromFile ) && JsTyping . nodeCoreModules . has ( moduleSpecifier ) ) {
702
- if ( usesNodeCoreModules === undefined ) {
703
- usesNodeCoreModules = consumesNodeCoreModules ( fromFile ) ;
704
- }
705
- if ( usesNodeCoreModules ) {
706
- return true ;
707
- }
708
- }
709
-
710
- return containsDependency ( moduleSpecifier )
711
- || containsDependency ( getTypesPackageName ( moduleSpecifier ) ) ;
712
- }
713
- }
714
-
715
- function * readPackageJsonDependencies ( host : LanguageServiceHost , packageJsonPaths : string [ ] ) {
716
- type PackageJson = Record < typeof dependencyKeys [ number ] , Record < string , string > | undefined > ;
717
- const dependencyKeys = [ "dependencies" , "devDependencies" , "optionalDependencies" ] as const ;
718
- for ( const fileName of packageJsonPaths ) {
719
- const content = readJson ( fileName , { readFile : host . readFile ? host . readFile . bind ( host ) : sys . readFile } ) as PackageJson ;
720
- for ( const key of dependencyKeys ) {
721
- const dependencies = content [ key ] ;
722
- if ( ! dependencies ) {
723
- continue ;
724
- }
725
- for ( const packageName in dependencies ) {
726
- yield packageName ;
727
- }
728
- }
729
- }
730
- }
731
-
732
- function consumesNodeCoreModules ( sourceFile : SourceFile ) : boolean {
733
- return some ( sourceFile . imports , ( { text } ) => JsTyping . nodeCoreModules . has ( text ) ) ;
734
- }
735
623
}
0 commit comments