fix(dart): attribute in-body calls to the enclosing function (signature/body siblings)
Dart models a function as a function_signature plus a SIBLING function_body (both children of program/class_body), not a single node containing the body. So a scope pushed at the signature never covers the body, and the signature's name was also unresolved by the shared resolver — in-body calls sourced to the Module (enclosing-func drift). Two parts in the unified walk: - compute_func_qn resolves a dart function_signature/method_signature name from its identifier child (method_signature wraps a function_signature). - push_boundary_scopes pushes the SCOPE_FUNC at the function_body, computing the QN from the preceding signature sibling, so the body's children attribute to the function. grammar_scripting and enclosing_parity dart cases now green. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
@@ -322,6 +322,32 @@ static const char *compute_func_qn(CBMExtractCtx *ctx, TSNode node, const CBMLan
|
||||
}
|
||||
}
|
||||
|
||||
/* Dart: function_signature / method_signature have no `name` field; the name
|
||||
* is an `identifier` child (method_signature wraps a function_signature). The
|
||||
* shared resolver doesn't cover them, so resolve here for call-scope so an
|
||||
* in-body call sources to the function, not the Module. */
|
||||
if (ctx->language == CBM_LANG_DART && (strcmp(ts_node_type(node), "function_signature") == 0 ||
|
||||
strcmp(ts_node_type(node), "method_signature") == 0)) {
|
||||
TSNode sig = node;
|
||||
if (strcmp(ts_node_type(node), "method_signature") == 0) {
|
||||
TSNode fs = cbm_find_child_by_kind(node, "function_signature");
|
||||
if (!ts_node_is_null(fs)) {
|
||||
sig = fs;
|
||||
}
|
||||
}
|
||||
TSNode id = cbm_find_child_by_kind(sig, "identifier");
|
||||
if (!ts_node_is_null(id)) {
|
||||
char *nm = cbm_node_text(ctx->arena, id, ctx->source);
|
||||
if (nm && nm[0]) {
|
||||
if (state->enclosing_class_qn) {
|
||||
return cbm_arena_sprintf(ctx->arena, "%s.%s", state->enclosing_class_qn, nm);
|
||||
}
|
||||
return cbm_fqn_compute_source_lang(ctx->arena, ctx->project, ctx->rel_path, nm,
|
||||
ctx->language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve the function name via the single shared resolver (extract_defs) so
|
||||
* call-scope attribution agrees with definition extraction across all ~130
|
||||
* grammars. The old private 4-case copy returned NULL for Fortran subroutine,
|
||||
@@ -1071,6 +1097,24 @@ static void push_boundary_scopes(CBMExtractCtx *ctx, TSNode node, const CBMLangS
|
||||
push_scope(state, SCOPE_CLASS, depth, tqn);
|
||||
}
|
||||
}
|
||||
} else if (ctx->language == CBM_LANG_DART && strcmp(ts_node_type(node), "function_body") == 0) {
|
||||
/* Dart models a function as `function_signature` + `function_body` SIBLINGS
|
||||
* (the signature node does not contain the body). A scope pushed at the
|
||||
* signature never covers the body, so in-body calls source to the Module.
|
||||
* Push the function scope at the BODY using the preceding signature
|
||||
* sibling's QN, so the body's children attribute to the function. */
|
||||
TSNode prev = ts_node_prev_sibling(node);
|
||||
while (!ts_node_is_null(prev) &&
|
||||
strcmp(ts_node_type(prev), "function_signature") != 0 &&
|
||||
strcmp(ts_node_type(prev), "method_signature") != 0) {
|
||||
prev = ts_node_prev_sibling(prev);
|
||||
}
|
||||
if (!ts_node_is_null(prev)) {
|
||||
const char *fqn = compute_func_qn(ctx, prev, spec, state);
|
||||
if (fqn) {
|
||||
push_scope(state, SCOPE_FUNC, depth, fqn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spec->call_node_types && cbm_kind_in_set(node, spec->call_node_types)) {
|
||||
|
||||
Reference in New Issue
Block a user