以下是用于recursively walk a source file's abstract syntax tree (AST)的两个打字稿功能。我设法找出导致我的程序只访问部分树的问题,但我不明白为什么解决方案有效。
walkTree1
函数是遍历整个树的有效解决方案。 walkTree2
函数仅访问树的一部分。这两个函数只有一行(用注释标记),显然return
行为以某种方式与此有关,但我没有在网上找到任何有用的东西。
function walkTree1(firstNode: ts.SourceFile, visitor: (node: ts.Node) => void): void {
visitInterfacesRecursive(firstNode);
function visitInterfacesRecursive(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.InterfaceDeclaration:
visitor(node); break; // correct
default:
ts.forEachChild(node, visitInterfacesRecursive);
}
}
}
function walkTree2(firstNode: ts.SourceFile, visitor: (node: ts.Node) => void): void {
visitInterfacesRecursive(firstNode);
function visitInterfacesRecursive(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.InterfaceDeclaration:
return visitor(node); // offending change
default:
ts.forEachChild(node, visitInterfacesRecursive);
}
}
}
最后,我很难过。我觉得我在这里遗漏了一些明显的东西。我已经检查了生成的源,并且似乎没有任何意外(除了类型擦除之外没有真正的区别)。现在我发布原始代码;如果有必要的话,我会在以后回家的时候把更可重复的东西放在一起。
其他详情:
node -v
:v8.5.0 tsc -v
:版本2.3.4 ts.forEachChild
source 答案 0 :(得分:2)
更改的唯一区别是让visitInterfacesRecursive
返回调用visitor(node)
的结果(在walkTree2
中),而在walkTree1
visitInterfacesRecursive
中可靠地返回undefined
。*
无论调用visitInterfacesRecursive
是什么,都清楚地看到它的回报值。在walkTree1
中,该返回值可靠undefined
。在walkTree2
中,有时undefined
,有时visitor(node)
返回。看来visitor(node)
会返回除undefined
以外的内容(至少有时会),而且无论是visitInterfacesRecursive
的返回值,都会解释非undefined
返回值意思是"停止。"
*"可靠地返回undefined
" - 从技术上讲,ECMAScript规范区分了一个根本不使用return
的函数和一个使用return
或return undefined
的函数,但它所做的区别是不可观察的在我们的代码中。调用该函数在所有三种情况下都会得到相同的结果。
答案 1 :(得分:2)
这是因为在所有情况下ts.forEachChild()
实际上并没有在每个孩子身上跑过。来自链接的source:
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns // a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
因此,既然你要回归visitor(node)
,那么它有时必须是真实的。即使您已将visitor()
声明为void
- 返回函数,这可能会在运行时发生,我猜? (您已经忽略了您使用的特定visitor()
,因此我不确定)因为您不关心visitor()
它的返回值最好不要从visitInterfacesRecursive()
返回。
希望有所帮助;祝你好运!