修复: 变量声明误判为符号定义

let/var 声明一律算定义致几乎任何文件误报改用符号读取
收窄为初始化为函数或类表达式才算定义,三处消费点统一收口
This commit is contained in:
lxy
2026-10-01 02:42:25 +08:00
parent 4efadf4952
commit 756d2840df
+42 -6
View File
@@ -39,7 +39,7 @@ const DEFINITION_KINDS: &[&str] = &[
"interface_declaration", "interface_declaration",
"enum_declaration", "enum_declaration",
"method_definition", "method_definition",
// TS/JS const/let/var 声明(如 const fn = () => {}) // TS/JS const/let/var 声明,仅当初始化为函数/类值才算定义(收窄判定见 is_definition_node)
"variable_declarator", "variable_declarator",
// Go // Go
"method_declaration", // Go method(receiver func) "method_declaration", // Go method(receiver func)
@@ -124,9 +124,45 @@ pub(crate) fn contains_definition(source: &str, ext: &str) -> bool {
tree_has_definition(&tree.root_node()) tree_has_definition(&tree.root_node())
} }
/// 递归遍历语法树,判断是否含任一 DEFINITION_KINDS 定义节点(contains_definition 的遍历内核)。 /// JS/TS 函数/类值表达式 kind:variable_declarator 是否算定义据此判定
const FUNCTION_VALUE_KINDS: &[&str] = &["arrow_function", "function", "generator_function", "class"];
/// 节点是否为可提取定义:kind 在表内,variable_declarator 需初始化为函数/类值。
///
/// variable_declarator 单看 kind 过宽:`let msg = "fn main() {}"` 这类普通声明也命中,
/// contains_definition 会对几乎任何 JS/TS 文件误报提示。收窄为 `const fn = () => {}`
/// 形态(初始化值是函数/类表达式)才算定义,contains_definition / read_symbol /
/// outline 三处共用同一判定。
fn is_definition_node(node: &Node<'_>) -> bool {
if !DEFINITION_KINDS.contains(&node.kind()) {
return false;
}
if node.kind() != "variable_declarator" {
return true;
}
match node.child_by_field_name("value") {
Some(v) => subtree_contains_kind(v, FUNCTION_VALUE_KINDS),
None => false,
}
}
/// 子树内是否含任一目标 kind 节点
fn subtree_contains_kind(node: Node<'_>, kinds: &[&str]) -> bool {
if kinds.contains(&node.kind()) {
return true;
}
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if subtree_contains_kind(child, kinds) {
return true;
}
}
false
}
/// 递归遍历语法树,判断是否含任一定义节点(contains_definition 的遍历内核)。
fn tree_has_definition(node: &Node<'_>) -> bool { fn tree_has_definition(node: &Node<'_>) -> bool {
if DEFINITION_KINDS.contains(&node.kind()) { if is_definition_node(node) {
return true; return true;
} }
let mut cursor = node.walk(); let mut cursor = node.walk();
@@ -246,7 +282,7 @@ pub fn read_symbol(
/// 递归遍历找匹配 symbol 名的定义节点。 /// 递归遍历找匹配 symbol 名的定义节点。
/// ///
/// 命中条件:node.kind() 在 DEFINITION_KINDS 内 + name field 文本 == symbol + kind_hint(若传)匹配。 /// 命中条件:node 为定义节点(is_definition_node)+ name field 文本 == symbol + kind_hint(若传)匹配。
/// 首个命中即返(find_definition 调用方短路)。 /// 首个命中即返(find_definition 调用方短路)。
fn find_definition<'a>( fn find_definition<'a>(
node: &Node<'a>, node: &Node<'a>,
@@ -258,7 +294,7 @@ fn find_definition<'a>(
if found.is_some() { if found.is_some() {
return; return;
} }
if DEFINITION_KINDS.contains(&node.kind()) { if is_definition_node(node) {
let kind_ok = kind_hint.map_or(true, |h| kind_matches(node.kind(), h)); let kind_ok = kind_hint.map_or(true, |h| kind_matches(node.kind(), h));
if kind_ok { if kind_ok {
if let Some(name_node) = node.child_by_field_name("name") { if let Some(name_node) = node.child_by_field_name("name") {
@@ -452,7 +488,7 @@ fn collect_top_level_symbols(
line_offset: usize, line_offset: usize,
out: &mut Vec<serde_json::Value>, out: &mut Vec<serde_json::Value>,
) { ) {
if DEFINITION_KINDS.contains(&node.kind()) { if is_definition_node(&node) {
let name = symbol_name(node, source); let name = symbol_name(node, source);
let kind = node.kind().to_string(); let kind = node.kind().to_string();
let line = node.start_position().row + 1 + line_offset; let line = node.start_position().row + 1 + line_offset;