โครงสร้างต้นไม้ไวยากรณ์นามธรรม - ตัวคอมไพเลอร์ TypeScript: จะรับ FunctionDeclaration ของฟังก์ชันต้นฉบับจาก CallExpression ได้อย่างไร?
ฉันเพิ่งเริ่มต้นศึกษาเกี่ยวกับภายในของ TypeScript และฉันสับสนว่าฉันจะได้ Signature หรือ FunctionDeclaration ของฟังก์ชันต้นฉบับได้อย่างไรเมื่อมีการอ้างอิงถึงการใช้งานของมันใน CallExpression ใด ๆ
พิจารณาตัวอย่าง:
class A<T> {
...
}
function f<T>(): A<T> {
return new A<T>();
}
function test(): void {
const foo = f;
foo<number>();
}
เมื่อได้รับการอ้างอิงถึง foo<number>() CallExpression ฉันสามารถสรุปประเภทที่ถูกทำให้เป็นวัตถุรวมถึงประเภทของค่าที่ส่งคืนได้อย่างง่ายดายด้วย typechecker.getTypeAtLocation(node) อย่างไรก็ตาม สิ่งที่ฉันต้องการทำจริง ๆ คือการดึงประเภทของฟังก์ชันต้นฉบับ ซึ่งคือ function f<T>(): A<T> { ... } และฉันไม่แน่ใจว่าจะทำให้สำเร็จได้อย่างไร
ฉันจะขอบคุณมากหากได้รับความช่วยเหลือด้านนั้น ขอบคุณ!
คำตอบ #1
คุณจำเป็นต้องรับสัญลักษณ์ของชนิดก่อน แล้วคุณจึงสามารถรับประกาศสำหรับสัญลักษณ์นั้นได้:
import * as ts from 'typescript'
let p = ts.createProgram({
rootNames: ["test.ts"],
options: {
}
})
const t = p.getTypeChecker();
var source = p.getSourceFile("test.ts");
const decl = source.statements[2] as ts.FunctionDeclaration; // function test(): void {....}
const fnCallStatement = decl.body.statements[1] as ts.ExpressionStatement; // foo<number>();
const fnCall = fnCallStatement.expression as ts.CallExpression; // foo<number>()
const fnTarget = fnCall.expression; // foo
let type = t.getTypeAtLocation(fnTarget) // <T>() => A<T>
let symbol = type.getSymbol() // symbol: f
let fnDecl = symbol.getDeclarations()[0]
console.log(fnDecl.getFullText());
// output:
// function f<T>(): A<T> {
// return new A<T>();
// }
