使用tree-sitter-javascript提取函数名失败,求问题原因及替代方案
问题原因
tree-sitter 的 tree.walk() 方法不接受回调函数,它返回的是一个 TreeCursor 实例,需要你手动调用游标的移动方法(如 gotoFirstChild()、gotoNextSibling())来遍历语法树节点。你之前试图给 walk() 传回调的写法完全不符合 API 设计,所以回调逻辑根本不会被执行,最终得到空数组。
修复与替代实现方法
方法一:使用 TreeCursor 手动遍历
通过手动控制游标遍历整个语法树,筛选出函数声明和函数表达式的名称节点:
const Parser = require('tree-sitter'); const JavaScript = require('tree-sitter-javascript'); const parser = new Parser(); parser.setLanguage(JavaScript); const code = ` function foo() {} const bar = function() {}; `; const tree = parser.parse(code); const functionNames = []; const cursor = tree.walk(); let hasNext = true; while (hasNext) { const node = cursor.node; // 匹配函数声明和函数表达式节点 if (node.type === 'function_declaration' || node.type === 'function_expression') { const nameNode = node.childForFieldName('name'); if (nameNode) { functionNames.push(nameNode.text); console.log('找到函数名:', nameNode.text); } } // 深度优先遍历逻辑:先遍历子节点,没有子节点则移动到下一个兄弟,直到回到根节点 if (cursor.gotoFirstChild()) { continue; } while (!cursor.gotoNextSibling()) { if (!cursor.gotoParent()) { hasNext = false; break; } } } console.log(functionNames); // 输出: ['foo', 'bar']
方法二:使用 Tree-sitter Query(推荐)
Tree-sitter 提供了查询语法,可以精准匹配目标节点,代码更简洁易维护,还能轻松扩展匹配箭头函数、类方法等:
const Parser = require('tree-sitter'); const JavaScript = require('tree-sitter-javascript'); const parser = new Parser(); parser.setLanguage(JavaScript); const code = ` function foo() {} const bar = function() {}; const baz = () => {}; `; const tree = parser.parse(code); const functionNames = []; // 定义查询规则,匹配多种函数类型的名称节点 const query = parser.getLanguage().query(` (function_declaration (identifier) @func-name) (function_expression (identifier) @func-name) (arrow_function (identifier) @func-name) `); // 执行查询并提取结果 const matches = query.matches(tree.rootNode); matches.forEach(match => { const funcNameNode = match.captures.find(c => c.name === 'func-name').node; functionNames.push(funcNameNode.text); console.log('找到函数名:', funcNameNode.text); }); console.log(functionNames); // 输出: ['foo', 'bar', 'baz']
内容的提问来源于stack exchange,提问作者Aadesh Kulkarni
相关产品推荐
相关产品推荐

