0

我目前正在为 Web 应用程序开发自定义构建器。现在需要自动检测导入,所以我需要知道 tsx 源代码中哪些标识符是未解析的,以便我的脚本可以导入正确的模块。

我目前正在研究的解决方案是遍历脚本的 AST,将声明的标识符存储在当前处理的范围内,然后返回未解析的标识符。但这需要大量工作来处理不同类型的 AST 元素。

因此,由于 tsc 和 ts 后台服务器都内置了这样的功能。我想知道是否有人可以告诉我他们是如何做到的,或者至少他们在哪里做的,因为我找不到特定的代码.

谢谢

卢卡

4

1 回答 1

0

我想我找到了一种解决方案。使用 AST 并不是那么容易,而且我遇到了一些难以解决的情况,在这些情况下,很难确定哪个标识符对当前范围有效。

所以我使用打字稿编译器来获取错误消息。每条错误消息都被过滤,错误消息被解析得到标识符Name。这不漂亮,但它有效。我还看到,在诊断 SourfeFileObjects 发生错误后,还包括导出的标识符。我也需要这些,但我直接通过 AST 获取它们。

let compilerHost = {
    getSourceFile: (fname: string) => {...},
    writeFile: (name: string, text: string) => {...},
    getDefaultLibFileName: () => Path.join(__dirname, "node_modules/typescript/lib/lib.d.ts"),
    useCaseSensitiveFileNames: () => false,
    getCanonicalFileName: (fileName : string) => fileName,
    getCurrentDirectory: () => "",
    getNewLine: () => "\n",
    fileExists: (fname: string): boolean => {...},
    readFile: (fileName: string) => {...},
    directoryExists: (dname: string) => {...},
    getDirectories: () => []
};

let unresolved = []
let sourceFile = TS.createSourceFile(filepath, tsCode, TS.ScriptTarget.ES5, true, TS.ScriptKind.TSX);
let program = TS.createProgram([filepath], tsCompilerOptions, compilerHost);
let semanticDiagnostic = program.getSemanticDiagnostics();
if(semanticDiagnostic.length){
    unresolved = <string[]>semanticDiagnostic
        // Filter for Unresolved names
        .filter(m=>m.code == 2304 && m.file == this.sourceFile)
        .map(m=>{
            let matches = (m.messageText as string).match(/^Cannot find name '([A-Z]\w+)'.$/)
            if(matches){
                return matches[1];
            }
        })
        .filter(sym=>typeof(sym)=="string");
}
于 2018-06-20T12:35:57.197 回答