Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions src/test/typescript-service-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
[rootUri + 'a.ts', 'class a { foo() { const i = 1;} }'],
[rootUri + 'foo/b.ts', 'class b { bar: number; baz(): number { return this.bar;}}; function qux() {}'],
[rootUri + 'c.ts', 'import { x } from "dep/dep";'],
[rootUri + 'package.json', '{ "name": "mypkg" }'],
[rootUri + 'node_modules/dep/dep.ts', 'export var x = 1;']
[rootUri + 'package.json', JSON.stringify({ name: 'mypkg' })],
[rootUri + 'node_modules/dep/dep.ts', 'export var x = 1;'],
[rootUri + 'node_modules/dep/package.json', JSON.stringify({ name: 'dep' })]
])));

afterEach(shutdownService);
Expand Down Expand Up @@ -865,7 +866,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 10,
character: 9,
line: 0
}
},
Expand All @@ -892,7 +893,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 10,
character: 9,
line: 0
}
},
Expand All @@ -905,7 +906,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
assert.deepEqual(result, []);
});
it('should return all references to a symbol from a dependency', async function (this: TestContext & ITestCallbackContext) {
const result: ReferenceInformation[] = await this.service.workspaceXreferences({ query: { name: 'x', containerName: '' } })
const result: ReferenceInformation[] = await this.service.workspaceXreferences({ query: { name: 'x' } })
.reduce<jsonpatch.Operation, ReferenceInformation[]>(jsonpatch.applyReducer, null as any)
.toPromise();
assert.deepEqual(result, [{
Expand All @@ -916,7 +917,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 9,
character: 8,
line: 0
}
},
Expand All @@ -931,6 +932,38 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
}
}]);
});
it('should return all references to a symbol from a dependency with PackageDescriptor query', async function (this: TestContext & ITestCallbackContext) {
const result: ReferenceInformation[] = await this.service.workspaceXreferences({ query: { name: 'x', package: { name: 'dep' } } })
.reduce<jsonpatch.Operation, ReferenceInformation[]>(jsonpatch.applyReducer, null as any)
.toPromise();
assert.deepEqual(result, [{
reference: {
range: {
end: {
character: 10,
line: 0
},
start: {
character: 8,
line: 0
}
},
uri: rootUri + 'c.ts'
},
symbol: {
filePath: 'node_modules/dep/dep.ts',
containerKind: '',
containerName: '"node_modules/dep/dep"',
kind: 'var',
name: 'x',
package: {
name: 'dep',
repoURL: undefined,
version: undefined
}
}
}]);
});
it('should return all references to all symbols if empty SymbolDescriptor query is passed', async function (this: TestContext & ITestCallbackContext) {
const result: ReferenceInformation[] = await this.service.workspaceXreferences({ query: {} })
.reduce<jsonpatch.Operation, ReferenceInformation[]>(jsonpatch.applyReducer, null as any)
Expand All @@ -951,7 +984,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 6,
character: 5,
line: 0
}
},
Expand All @@ -973,7 +1006,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 10,
character: 9,
line: 0
}
},
Expand All @@ -995,7 +1028,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 24,
character: 23,
line: 0
}
},
Expand All @@ -1010,7 +1043,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 9,
character: 8,
line: 0
}
},
Expand Down Expand Up @@ -1039,7 +1072,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 6,
character: 5,
line: 0
}
},
Expand All @@ -1061,7 +1094,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 10,
character: 9,
line: 0
}
},
Expand All @@ -1083,7 +1116,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 23,
character: 22,
line: 0
}
},
Expand All @@ -1105,7 +1138,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 52,
character: 51,
line: 0
}
},
Expand All @@ -1127,7 +1160,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor
line: 0
},
start: {
character: 68,
character: 67,
line: 0
}
},
Expand Down
36 changes: 22 additions & 14 deletions src/typescript-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
InitializeResult,
PackageDescriptor,
PackageInformation,
ReferenceInformation,
SymbolDescriptor,
SymbolLocationInformation,
WorkspaceReferenceParams,
Expand All @@ -53,7 +54,6 @@ import {
defInfoToSymbolDescriptor,
getMatchingPropertyCount,
getPropertyCount,
isSymbolDescriptorMatch,
JSONPTR,
normalizeUri,
observableFromIterable,
Expand Down Expand Up @@ -761,14 +761,21 @@ export class TypeScriptService {
*/
workspaceXreferences(params: WorkspaceReferenceParams, span = new Span()): Observable<jsonpatch.Operation> {
const queryWithoutPackage = omit(params.query, 'package');
return Observable.from(this.projectManager.ensureAllFiles(span))
.mergeMap<void, ProjectConfiguration>(() => {
const minScore = Math.min(4.75, getPropertyCount(queryWithoutPackage));
return this.isDefinitelyTyped
.mergeMap(isDefinitelyTyped => {
if (isDefinitelyTyped) {
throw new Error('workspace/xreferences not supported in DefinitelyTyped');
}
return this.projectManager.ensureAllFiles(span);
})
.mergeMap(() => {
// if we were hinted that we should only search a specific package, find it and only search the owning tsconfig.json
if (params.hints && params.hints.dependeePackageName) {
return observableFromIterable(this.packageManager.packageJsonUris())
.filter(uri => (JSON.parse(this.inMemoryFileSystem.getContent(uri)) as PackageJson).name === params.hints!.dependeePackageName)
.take(1)
.mergeMap<string, ProjectConfiguration>(uri => {
.mergeMap(uri => {
const config = this.projectManager.getParentConfiguration(uri);
if (!config) {
return observableFromIterable(this.projectManager.configurations());
Expand Down Expand Up @@ -796,35 +803,36 @@ export class TypeScriptService {
.filter((node): node is ts.Identifier => node.kind === ts.SyntaxKind.Identifier)
.mergeMap(node => {
try {
// Get DefinitionInformations at the node
// Find definition for node
return Observable.from(config.getService().getDefinitionAtPosition(source.fileName, node.pos + 1) || [])
.mergeMap(definition => {
const symbol = defInfoToSymbolDescriptor(definition, this.root);
// Check if SymbolDescriptor without PackageDescriptor matches
if (!isSymbolDescriptorMatch(queryWithoutPackage, symbol)) {
const score = getMatchingPropertyCount(queryWithoutPackage, symbol);
if (score < minScore || (params.query.package && !definition.fileName.includes(params.query.package.name))) {
return [];
}
span.log({ event: 'match', score });
// If no PackageDescriptor query, return match
if (!params.query.package || !params.query.package) {
return [symbol];
}
// If SymbolDescriptor matched and the query contains a PackageDescriptor, get package.json and match PackageDescriptor name
// TODO match full PackageDescriptor (version)
// TODO match full PackageDescriptor (version) and fill out the symbol.package field
const uri = path2uri(definition.fileName);
return this._getPackageDescriptor(uri)
.mergeMap(packageDescriptor => {
return Observable.from(this._getPackageDescriptor(uri, span))
.filter(packageDescriptor => !!(packageDescriptor && packageDescriptor.name === params.query.package!.name!))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be a test for a query with PackageDescriptor.

.map(packageDescriptor => {
symbol.package = packageDescriptor;
return packageDescriptor && packageDescriptor.name === params.query.package!.name!
? [symbol]
: [];
return symbol;
});
})
.map(symbol => ({
.map((symbol: SymbolDescriptor): ReferenceInformation => ({
symbol,
reference: {
uri: locationUri(source.fileName),
range: {
start: ts.getLineAndCharacterOfPosition(source, node.pos + 1),
start: ts.getLineAndCharacterOfPosition(source, node.pos),
end: ts.getLineAndCharacterOfPosition(source, node.end)
}
}
Expand Down