Determine if an API Is Used in a Typescript script (using the typescript compiler or something else)

81 Views Asked by At

I have a collection of user provided scripts I would like to analyze. In particular, I want to determine whether a specific API was used. The only way for a user to use the API is to interact with a parameter I inject into their script.

In this script, the API in question was used.

function main(api: ProvidedApi) {
  api.doSomething();
}

In this script, the API in question was not used.

function main(api: ProvidedApi) {
  return 5;
}

This is the format that the user scripts always take, though they can have more functions, classes, whatever separate from this 'main' function.

I've tried using the Typescript compiler to traverse the SourceFile and calling

const symbl = typeChecker.getSymbolAtLocation(node);
if (typeChecker.getFullyQualifiedName(symbl).includes('ProvidedApi')) {
  return true;
}

but that doesn't work if there's no typing information, for example in the following:

function main(api: ProvidedApi) {
  doSomethingFunc(api);
}

function doSomethingFunc(api) {
  api.doSomething();
}

Though the API in question was used, the fully qualified name will not include ProvidedApi.

2

There are 2 best solutions below

0
On

Wrap the scripts in jest tests that invoke the scripts, then use the built-in coverage support.

See https://jestjs.io/docs/cli#--collectcoveragefromglob

A test of a script which has 0% coverage of your API library will not be a user of your API.

This will effectively do all the work of decomposing the scripts into an AST and checking what the references resolve to, but without you having to do any explicit engineering to achieve it.

If the scripts use your API as a module, you should be able to alias the module locally and then use the collectCoverageFrom option to point to the local files.

0
On

It sounds like you should have the API itself record whether it was called. If you don't control the API, if I understand what you are after, could you call the various API's through a wrapper function? Then the wrapper can record what has been called. (I'm not sure where you are planning to use that info, so your mileage may vary)