ค้นหาเว็บไซต์

โครงสร้างต้นไม้ไวยากรณ์นามธรรม - ตัวคอมไพเลอร์ 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>();
// }

บทความที่เกี่ยวข้อง