@@ -3,7 +3,33 @@ import * as ts from 'typescript';
33import { SymbolInformation , SymbolKind } from 'vscode-languageserver-types' ;
44import { isTypeScriptLibrary } from './memfs' ;
55import { SymbolDescriptor } from './request-type' ;
6- import { path2uri } from './util' ;
6+ import { path2uri , toUnixPath } from './util' ;
7+
8+ /**
9+ * Returns a SymbolDescriptor for a ts.DefinitionInfo
10+ */
11+ export function definitionInfoToSymbolDescriptor ( info : ts . DefinitionInfo , rootPath : string ) : SymbolDescriptor {
12+ const rootUnixPath = toUnixPath ( rootPath ) ;
13+ const symbolDescriptor : SymbolDescriptor = {
14+ kind : info . kind || '' ,
15+ name : info . name || '' ,
16+ containerKind : info . containerKind || '' ,
17+ containerName : info . containerName || '' ,
18+ filePath : info . fileName
19+ } ;
20+ // If the symbol is an external module representing a file, set name to the file path
21+ if ( info . kind === ts . ScriptElementKind . moduleElement && info . name && / [ \\ \/ ] / . test ( info . name ) ) {
22+ symbolDescriptor . name = '"' + info . fileName . replace ( / (?: \. d ) ? \. t s x ? $ / , '' ) + '"' ;
23+ }
24+ // If the symbol itself is not a module and there is no containerKind
25+ // then the container is an external module named by the file name (without file extension)
26+ if ( info . kind !== ts . ScriptElementKind . moduleElement && ! info . containerKind && ! info . containerName ) {
27+ symbolDescriptor . containerName = '"' + info . fileName . replace ( / (?: \. d ) ? \. t s x ? $ / , '' ) + '"' ;
28+ symbolDescriptor . containerKind = ts . ScriptElementKind . moduleElement ;
29+ }
30+ normalizeSymbolDescriptorPaths ( symbolDescriptor , rootUnixPath ) ;
31+ return symbolDescriptor ;
32+ }
733
834/**
935 * Transforms definition's file name to URI. If definition belongs to the in-memory TypeScript library,
@@ -136,10 +162,7 @@ export function navigationTreeToSymbolDescriptor(tree: ts.NavigationTree, parent
136162 }
137163 symbolDescriptor . containerKind = ts . ScriptElementKind . moduleElement ;
138164 }
139- // Make all paths that may occur in module names relative to the workspace rootPath
140- symbolDescriptor . name = symbolDescriptor . name . replace ( rootPath , '' ) ;
141- symbolDescriptor . containerName = symbolDescriptor . containerName . replace ( rootPath , '' ) ;
142- symbolDescriptor . filePath = symbolDescriptor . filePath . replace ( rootPath , '' ) ;
165+ normalizeSymbolDescriptorPaths ( symbolDescriptor , rootPath ) ;
143166 return symbolDescriptor ;
144167}
145168
@@ -167,3 +190,18 @@ export function navigationTreeIsSymbol(tree: ts.NavigationTree): boolean {
167190 }
168191 return true ;
169192}
193+
194+ /**
195+ * Makes paths relative to the passed rootPath and strips `node_modules` out of paths
196+ */
197+ function normalizeSymbolDescriptorPaths ( symbol : SymbolDescriptor , rootPath : string ) {
198+ for ( const key of [ 'name' , 'containerName' , 'filePath' ] as [ 'name' , 'containerName' , 'filePath' ] ) {
199+ // Make all paths that may occur in module names relative to the workspace rootPath
200+ symbol [ key ] = symbol [ key ] . replace ( rootPath , '' ) ;
201+ // Remove node_modules part from a module name
202+ // The SymbolDescriptor will be used in the defining repo, where the symbol file path will never contain node_modules
203+ // It may contain the package name though if the repo is a monorepo with multiple packages
204+ const regExp = / [ ^ " ] * n o d e _ m o d u l e s \/ / ;
205+ symbol [ key ] = symbol [ key ] . replace ( regExp , '' ) ;
206+ }
207+ }
0 commit comments