Skip to content

Commit

Permalink
fix(typescript_indexer): limit ref/call spans to identifiers (#5695)
Browse files Browse the repository at this point in the history
In service of #5691
  • Loading branch information
zrlk committed Jun 9, 2023
1 parent 29fc369 commit 2eedf34
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
22 changes: 21 additions & 1 deletion kythe/typescript/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,26 @@ class Visitor {
this.popInfluencers();
}

getCallAnchor(callee:any) {
if (!this.host.options.emitRefCallOverIdentifier) {
return undefined;
}
for (;;) {
if (ts.isIdentifier(callee)) {
return this.newAnchor(callee);
}
if (ts.isPropertyAccessExpression(callee)) {
callee = callee.name;
continue;
}
if (ts.isNewExpression(callee)) {
callee = callee.expression;
continue;
}
return undefined;
}
}

/**
* Emits `ref/call` edges required for call graph:
* https://kythe.io/docs/schema/callgraph.html
Expand All @@ -829,7 +849,6 @@ class Visitor {
this.visitDynamicImportCall(node);
return;
}
const callAnchor = this.newAnchor(node);
const symbol = this.host.getSymbolAtLocationFollowingAliases(node.expression);
if (!symbol) {
return;
Expand All @@ -838,6 +857,7 @@ class Visitor {
if (!name) {
return;
}
const callAnchor = this.getCallAnchor(node.expression) ?? this.newAnchor(node);
this.emitEdge(callAnchor, EdgeKind.REF_CALL, name);

// Each call should have a childof edge to its containing function
Expand Down
6 changes: 6 additions & 0 deletions kythe/typescript/plugin_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export interface IndexingOptions {
* to emit `defines/implicit` edges instead of `defines/binding`.
*/
emitZeroWidthSpansForModuleNodes?: boolean;

/**
* When enabled, ref/call source anchors span identifiers instead of full
* call expressions when possible.
*/
emitRefCallOverIdentifier?: boolean;
}


Expand Down
6 changes: 4 additions & 2 deletions kythe/typescript/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function isTsFile(filename: string): boolean {
*/
function verify(
host: ts.CompilerHost, options: ts.CompilerOptions, testCase: TestCase,
plugins?: Plugin[]): Promise<void> {
plugins?: Plugin[], emitRefCallOverIdentifier?: boolean): Promise<void> {
const rootVName: kythe.VName = {
corpus: 'testcorpus',
root: '',
Expand Down Expand Up @@ -129,6 +129,7 @@ function verify(
verifier.stdin.write(JSON.stringify(obj) + '\n');
},
plugins,
emitRefCallOverIdentifier,
});
} finally {
// Ensure we close stdin on the verifier even on crashes, or otherwise
Expand Down Expand Up @@ -231,10 +232,11 @@ async function testIndexer(filters: string[], plugins?: Plugin[]) {
// plugin.ts is tested by testPlugin() test.
continue;
}
const emitRefCallOverIdentifier = testCase.name.endsWith('_id.ts');
const start = new Date().valueOf();
process.stdout.write(`${testCase.name}: `);
try {
await verify(host, config.options, testCase, plugins);
await verify(host, config.options, testCase, plugins, emitRefCallOverIdentifier);
} catch (e) {
console.log('FAIL');
throw e;
Expand Down
46 changes: 46 additions & 0 deletions kythe/typescript/testdata/refcall_id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @fileoverview Test to ensure that indexer produces ref/call edges and all data needed for callgraph.
* See https://kythe.io/docs/schema/callgraph.html.
*/

// clang-format off
//- FileInitFunc=vname("fileInit:synthetic", _, _, "testdata/refcall_id", "typescript").node/kind function
//- FileInitDef defines FileInitFunc
//- FileInitDef.node/kind anchor
//- FileInitDef.loc/start 0
//- FileInitDef.loc/end 0
// clang-format on

//- @Square defines/binding Square
//- Square.node/kind function
class Square {
//- @getWidth defines/binding GetWidth
getWidth(): number {
return 42;
}

//- @getArea defines/binding GetArea
getArea() {
//- GetWidthCall=@getWidth ref/call GetWidth
//- GetWidthCall childof GetArea
this.getWidth() ** 2;
}
}

//- @Square ref/call Square
const square = new Square();

//- GetAreaCallOne=@getArea ref/call GetArea
//- GetAreaCallOne childof FileInitFunc
square.getArea();

//- @doNothing defines/binding DoNothing
function doNothing() {
//- GetAreaCallTwo=@getArea ref/call GetArea
//- GetAreaCallTwo childof DoNothing
square.getArea();
}

//- DoNothingCall=@doNothing ref/call DoNothing
//- DoNothingCall childof FileInitFunc
doNothing();

0 comments on commit 2eedf34

Please sign in to comment.