Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit c0aa984

Browse files
authored
Fix workspace/xreferences (#296)
- Move SymbolDescriptor path normalization to function - Move `defInfoToSymbolDescriptor` to symbols module - Strip node_modules from SymbolDescriptor paths
1 parent c4a274c commit c0aa984

File tree

4 files changed

+52
-43
lines changed

4 files changed

+52
-43
lines changed

src/symbols.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,33 @@ import * as ts from 'typescript';
33
import { SymbolInformation, SymbolKind } from 'vscode-languageserver-types';
44
import { isTypeScriptLibrary } from './memfs';
55
import { 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)?\.tsx?$/, '') + '"';
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)?\.tsx?$/, '') + '"';
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 = /[^"]*node_modules\//;
205+
symbol[key] = symbol[key].replace(regExp, '');
206+
}
207+
}

src/test/typescript-service-helpers.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -925,9 +925,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
925925
uri: rootUri + 'c.ts'
926926
},
927927
symbol: {
928-
filePath: 'node_modules/dep/dep.ts',
928+
filePath: 'dep/dep.ts',
929929
containerKind: '',
930-
containerName: '"node_modules/dep/dep"',
930+
containerName: '"dep/dep"',
931931
kind: 'var',
932932
name: 'x'
933933
}
@@ -952,9 +952,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
952952
uri: rootUri + 'c.ts'
953953
},
954954
symbol: {
955-
filePath: 'node_modules/dep/dep.ts',
955+
filePath: 'dep/dep.ts',
956956
containerKind: '',
957-
containerName: '"node_modules/dep/dep"',
957+
containerName: '"dep/dep"',
958958
kind: 'var',
959959
name: 'x',
960960
package: {
@@ -1051,9 +1051,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
10511051
uri: rootUri + 'c.ts'
10521052
},
10531053
symbol: {
1054-
filePath: 'node_modules/dep/dep.ts',
1054+
filePath: 'dep/dep.ts',
10551055
containerKind: '',
1056-
containerName: '"node_modules/dep/dep"',
1056+
containerName: '"dep/dep"',
10571057
kind: 'var',
10581058
name: 'x'
10591059
}

src/typescript-service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ import {
5151
WorkspaceSymbolParams
5252
} from './request-type';
5353
import {
54-
defInfoToSymbolDescriptor,
5554
getMatchingPropertyCount,
5655
getPropertyCount,
5756
JSONPTR,
@@ -66,6 +65,7 @@ import { castArray, merge, omit } from 'lodash';
6665
import * as url from 'url';
6766
import { extractDefinitelyTypedPackageName, extractNodeModulesPackageName, PackageJson, PackageManager } from './packages';
6867
import {
68+
definitionInfoToSymbolDescriptor,
6969
locationUri,
7070
navigateToItemToSymbolInformation,
7171
navigationTreeIsSymbol,
@@ -408,7 +408,7 @@ export class TypeScriptService {
408408
if (!sourceFile) {
409409
throw new Error(`Expected source file ${definition.fileName} to exist in configuration`);
410410
}
411-
const symbol = defInfoToSymbolDescriptor(definition, this.root);
411+
const symbol = definitionInfoToSymbolDescriptor(definition, this.root);
412412
if (packageDescriptor) {
413413
symbol.package = packageDescriptor;
414414
}
@@ -802,7 +802,7 @@ export class TypeScriptService {
802802
// Find definition for node
803803
return Observable.from(config.getService().getDefinitionAtPosition(source.fileName, node.pos + 1) || [])
804804
.mergeMap(definition => {
805-
const symbol = defInfoToSymbolDescriptor(definition, this.root);
805+
const symbol = definitionInfoToSymbolDescriptor(definition, this.root);
806806
// Check if SymbolDescriptor without PackageDescriptor matches
807807
const score = getMatchingPropertyCount(queryWithoutPackage, symbol);
808808
if (score < minScore || (params.query.package && !definition.fileName.includes(params.query.package.name))) {

src/util.ts

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -147,35 +147,6 @@ export function isDeclarationFile(filename: string): boolean {
147147
return filename.endsWith('.d.ts');
148148
}
149149

150-
/**
151-
* Converts a ts.DefinitionInfo to a SymbolDescriptor
152-
*/
153-
export function defInfoToSymbolDescriptor(info: ts.DefinitionInfo, rootPath: string): SymbolDescriptor {
154-
const rootUnixPath = toUnixPath(rootPath);
155-
const symbolDescriptor: SymbolDescriptor = {
156-
kind: info.kind || '',
157-
name: info.name || '',
158-
containerKind: info.containerKind || '',
159-
containerName: info.containerName || '',
160-
filePath: info.fileName
161-
};
162-
// If the symbol is an external module representing a file, set name to the file path
163-
if (info.kind === ts.ScriptElementKind.moduleElement && info.name && /[\\\/]/.test(info.name)) {
164-
symbolDescriptor.name = '"' + info.fileName.replace(/(?:\.d)?\.tsx?$/, '') + '"';
165-
}
166-
// If the symbol itself is not a module and there is no containerKind
167-
// then the container is an external module named by the file name (without file extension)
168-
if (info.kind !== ts.ScriptElementKind.moduleElement && !info.containerKind && !info.containerName) {
169-
symbolDescriptor.containerName = '"' + info.fileName.replace(/(?:\.d)?\.tsx?$/, '') + '"';
170-
symbolDescriptor.containerKind = ts.ScriptElementKind.moduleElement;
171-
}
172-
// Make paths relative to root paths
173-
symbolDescriptor.containerName = symbolDescriptor.containerName.replace(rootUnixPath, '');
174-
symbolDescriptor.name = symbolDescriptor.name.replace(rootUnixPath, '');
175-
symbolDescriptor.filePath = symbolDescriptor.filePath.replace(rootUnixPath, '');
176-
return symbolDescriptor;
177-
}
178-
179150
/**
180151
* Compares two values and returns a numeric score between 0 and 1 defining of how well they match.
181152
* E.g. if 2 of 4 properties in the query match, will return 2

0 commit comments

Comments
 (0)