@@ -188,7 +188,7 @@ namespace ts.Completions.PathCompletions {
188188 if ( fragmentDirectory === undefined ) {
189189 const oldLength = result . length ;
190190 getCompletionEntriesFromTypings ( host , compilerOptions , scriptPath , result ) ;
191- for ( const moduleName of getNamesFromVisibleNodeModules ( fragmentDirectory , scriptPath , host ) ) {
191+ for ( const moduleName of enumerateNodeModulesVisibleToScript ( host , scriptPath ) ) {
192192 if ( ! result . some ( entry => entry . name === moduleName ) ) {
193193 result . push ( nameAndKind ( moduleName , ScriptElementKind . externalModuleName ) ) ;
194194 }
@@ -290,18 +290,6 @@ namespace ts.Completions.PathCompletions {
290290 return nonRelativeModuleNames ;
291291 }
292292
293- function getNamesFromVisibleNodeModules ( fragmentDirectory : string | undefined , scriptPath : string , host : LanguageServiceHost ) : string [ ] {
294- return flatMap ( enumerateNodeModulesVisibleToScript ( host , scriptPath ) , visibleModule => {
295- if ( fragmentDirectory === undefined ) {
296- return visibleModule . moduleName ;
297- }
298- else if ( startsWith ( visibleModule . moduleName , fragmentDirectory ) ) {
299- const nestedFiles = tryReadDirectory ( host , visibleModule . moduleDir , supportedTypeScriptExtensions , /*exclude*/ undefined , /*include*/ [ "./*" ] ) ;
300- return map ( nestedFiles , f => removeFileExtension ( getBaseFileName ( normalizePath ( f ) ) ) ) ;
301- }
302- } ) ;
303- }
304-
305293 export function getTripleSlashReferenceCompletion ( sourceFile : SourceFile , position : number , compilerOptions : CompilerOptions , host : LanguageServiceHost ) : ReadonlyArray < PathCompletion > | undefined {
306294 const token = getTokenAtPosition ( sourceFile , position , /*includeJsDocComment*/ false ) ;
307295 const commentRanges = getLeadingCommentRanges ( sourceFile . text , token . pos ) ;
@@ -389,55 +377,24 @@ namespace ts.Completions.PathCompletions {
389377 return paths ;
390378 }
391379
392- function enumerateNodeModulesVisibleToScript ( host : LanguageServiceHost , scriptPath : string ) {
393- const result : VisibleModuleInfo [ ] = [ ] ;
394-
395- if ( host . readFile && host . fileExists ) {
396- for ( const packageJson of findPackageJsons ( scriptPath , host ) ) {
397- const contents = tryReadingPackageJson ( packageJson ) ;
398- if ( ! contents ) {
399- return ;
400- }
401-
402- const nodeModulesDir = combinePaths ( getDirectoryPath ( packageJson ) , "node_modules" ) ;
403- const foundModuleNames : string [ ] = [ ] ;
404-
405- // Provide completions for all non @types dependencies
406- for ( const key of nodeModulesDependencyKeys ) {
407- addPotentialPackageNames ( contents [ key ] , foundModuleNames ) ;
408- }
409-
410- for ( const moduleName of foundModuleNames ) {
411- const moduleDir = combinePaths ( nodeModulesDir , moduleName ) ;
412- result . push ( {
413- moduleName,
414- moduleDir
415- } ) ;
416- }
417- }
418- }
419-
420- return result ;
421-
422- function tryReadingPackageJson ( filePath : string ) {
423- try {
424- const fileText = tryReadFile ( host , filePath ) ;
425- return fileText ? JSON . parse ( fileText ) : undefined ;
426- }
427- catch ( e ) {
428- return undefined ;
429- }
430- }
380+ function enumerateNodeModulesVisibleToScript ( host : LanguageServiceHost , scriptPath : string ) : ReadonlyArray < string > {
381+ if ( ! host . readFile || ! host . fileExists ) return emptyArray ;
431382
432- function addPotentialPackageNames ( dependencies : any , result : string [ ] ) {
433- if ( dependencies ) {
383+ const result : string [ ] = [ ] ;
384+ for ( const packageJson of findPackageJsons ( scriptPath , host ) ) {
385+ const contents = readJson ( packageJson , host as { readFile : ( filename : string ) => string | undefined } ) ; // Cast to assert that readFile is defined
386+ // Provide completions for all non @types dependencies
387+ for ( const key of nodeModulesDependencyKeys ) {
388+ const dependencies : object | undefined = ( contents as any ) [ key ] ;
389+ if ( ! dependencies ) continue ;
434390 for ( const dep in dependencies ) {
435391 if ( dependencies . hasOwnProperty ( dep ) && ! startsWith ( dep , "@types/" ) ) {
436392 result . push ( dep ) ;
437393 }
438394 }
439395 }
440396 }
397+ return result ;
441398 }
442399
443400 // Replace everything after the last directory seperator that appears
@@ -483,11 +440,6 @@ namespace ts.Completions.PathCompletions {
483440 */
484441 const tripleSlashDirectiveFragmentRegex = / ^ ( \/ \/ \/ \s * < r e f e r e n c e \s + ( p a t h | t y p e s ) \s * = \s * (?: ' | " ) ) ( [ ^ \3" ] * ) $ / ;
485442
486- interface VisibleModuleInfo {
487- moduleName : string ;
488- moduleDir : string ;
489- }
490-
491443 const nodeModulesDependencyKeys = [ "dependencies" , "devDependencies" , "peerDependencies" , "optionalDependencies" ] ;
492444
493445 function tryGetDirectories ( host : LanguageServiceHost , directoryName : string ) : string [ ] {
@@ -498,10 +450,6 @@ namespace ts.Completions.PathCompletions {
498450 return tryIOAndConsumeErrors ( host , host . readDirectory , path , extensions , exclude , include ) || emptyArray ;
499451 }
500452
501- function tryReadFile ( host : LanguageServiceHost , path : string ) : string | undefined {
502- return tryIOAndConsumeErrors ( host , host . readFile , path ) ;
503- }
504-
505453 function tryFileExists ( host : LanguageServiceHost , path : string ) : boolean {
506454 return tryIOAndConsumeErrors ( host , host . fileExists , path ) ;
507455 }
0 commit comments