我想我找到了一种解决方案。使用 AST 并不是那么容易,我遇到了一些难以解决的情况,在这些情况下很难确定哪个标识符对当前范围有效。
所以我正在使用 typescript 编译器来获取错误消息。过滤每条错误消息并解析错误消息以获取标识符名称。这并不漂亮,但它有效。我还看到,在诊断 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");
}