Hvordan får man alle referencer til en node ved hjælp af TypeScript API'en?
Brugssag: givet en variabeldeklaration som let i=0 eller const j=getSomething();, find ud af om variablen er et heltal, et flydende tal eller noget andet (ikke kun number vs ikke-number). For at gøre dette antager jeg, at den generelle måde at gøre det på er at finde alle steder, hvor værdien sættes, finde ud af deres typer (rekursivt) og se, om nogen sætter den til noget andet end et heltal.
Jeg har adgang til en ts.TypeChecker og ts.Program, hvis det er nødvendigt. Et par tweets fra Daniel Rosenwasser indikerer, at checker-API'en er vejen frem, men jeg kan ikke finde ud af, hvilke API'er jeg skal bruge.
Relevant GitHub-issue og relevant kildefil.
Rediger: Dette er ikke så enkelt som typeChecker.getSymbolAtLocation. Antag, at vi har følgende blok:
function someScope() {
let myInt = 0;
let myFloat = 0;
for (let i = 0; i < 3; i += 1) {
myInt = i;
myFloat = i;
}
if (external) {
myInt = 7;
} else {
myFloat = 7.5;
}
return myInt * myFloat;
}
Jeg prøver at få et program, der gennemsøger træet, til at forstå, at myInt faktisk er en int (ikke bare et generelt number), mens myFloat er af typen float, og someScope returnerer float (ikke int).
Det 'værste tilfælde'-scenario ville være at kravle gennem den variablets omfattende scope, finde alle referencer til den og rekursivt få deres typer. Der må da være en standard måde at gøre dette på?
Svar #1
Du kan gøre sådan:
const ts = require('typescript');
const service = ts.createLanguageService(host);
let identNode;
function visit(node) {} // ...visit and find decl of your ident blahblah
for (const file of service.getProgram().getSourceFiles()) {
if (!file.isDeclarationFile) {
ts.forEachChild(file, visit);
}
}
const refs = service.findReferences(identNode.getSourceFile().fileName, identNode.getStart());
const refNodes = new Set();
refs?.forEach(ref => {
const { references } = ref;
references?.forEach(reference => {
const sourceNode = service.getProgram().getSourceFile(reference.fileName);
ts.forEachChild(sourceNode, node => {
// traverse stuff..., logic as:
// if node.textSpan === references.textSpan
// refNodes.add(node);
});
})
})
"refNodes" er, hvad du har brug for. Og du kan også se lignende kode på linket
