我目前正在为 Web 应用程序开发自定义构建器。现在需要自动检测导入,所以我需要知道 tsx 源代码中哪些标识符是未解析的,以便我的脚本可以导入正确的模块。
我目前正在研究的解决方案是遍历脚本的 AST,将声明的标识符存储在当前处理的范围内,然后返回未解析的标识符。但这需要大量工作来处理不同类型的 AST 元素。
因此,由于 tsc 和 ts 后台服务器都内置了这样的功能。我想知道是否有人可以告诉我他们是如何做到的,或者至少他们在哪里做的,因为我找不到特定的代码.
谢谢
卢卡
我目前正在为 Web 应用程序开发自定义构建器。现在需要自动检测导入,所以我需要知道 tsx 源代码中哪些标识符是未解析的,以便我的脚本可以导入正确的模块。
我目前正在研究的解决方案是遍历脚本的 AST,将声明的标识符存储在当前处理的范围内,然后返回未解析的标识符。但这需要大量工作来处理不同类型的 AST 元素。
因此,由于 tsc 和 ts 后台服务器都内置了这样的功能。我想知道是否有人可以告诉我他们是如何做到的,或者至少他们在哪里做的,因为我找不到特定的代码.
谢谢
卢卡
我想我找到了一种解决方案。使用 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");
}