修复: 变量声明误判为符号定义
let/var 声明一律算定义致几乎任何文件误报改用符号读取 收窄为初始化为函数或类表达式才算定义,三处消费点统一收口
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user