mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
Fix Swift call extraction: 0 CALLS edges (#43)
Swift tree-sitter grammar uses positional children (not named fields) for call_expression, so extract_callee_name() returned NULL for every call. - extract_calls.c: Swift-specific callee extraction via first named child for call_expression and constructor_expression nodes - lang_specs.c: add constructor_expression to swift_call_types - 4 new C tests: simple calls, method calls, constructors, chained calls Co-Authored-By: Jay Sync <63868998+jay-sync@users.noreply.github.com>
This commit is contained in:
1 parent
f6b9b39c60
commit
c66d88745d
4 files changed
+86
-6
No files matched your search
@@ -215,6 +215,23 @@ static char *extract_callee_name(CBMArena *a, TSNode node, const char *source, C
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Swift: call_expression has no "function" field — callee is first named child.
|
||||
// Also handle constructor_expression for MyClass() syntax.
|
||||
if (lang == CBM_LANG_SWIFT) {
|
||||
const char *nk = ts_node_type(node);
|
||||
if (strcmp(nk, "call_expression") == 0 || strcmp(nk, "constructor_expression") == 0) {
|
||||
if (ts_node_named_child_count(node) > 0) {
|
||||
TSNode callee = ts_node_named_child(node, 0);
|
||||
const char *ck = ts_node_type(callee);
|
||||
if (strcmp(ck, "simple_identifier") == 0 ||
|
||||
strcmp(ck, "navigation_expression") == 0) {
|
||||
return cbm_node_text(a, callee, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Generic fallback: first child
|
||||
if (ts_node_child_count(node) > 0) {
|
||||
TSNode first = ts_node_child(node, 0);
|
||||
|
||||
@@ -377,7 +377,7 @@ static const char *swift_class_types[] = {"class_declaration", "protocol_declara
|
||||
"struct_declaration", "enum_declaration", NULL};
|
||||
static const char *swift_field_types[] = {"property_declaration", NULL};
|
||||
static const char *swift_module_types[] = {"source_file", NULL};
|
||||
static const char *swift_call_types[] = {"call_expression", NULL};
|
||||
static const char *swift_call_types[] = {"call_expression", "constructor_expression", NULL};
|
||||
static const char *swift_import_types[] = {"import_declaration", NULL};
|
||||
static const char *swift_branch_types[] = {"if_statement", "guard_statement", "for_statement",
|
||||
"while_statement", "switch_statement", NULL};
|
||||
|
||||
+23
-5
@@ -1290,22 +1290,40 @@ int cbm_remove_antigravity_mcp(const char *config_path) {
|
||||
|
||||
/* ── Claude Code pre-tool hooks ───────────────────────────────── */
|
||||
|
||||
#define CMM_HOOK_MATCHER "Grep|Glob|Read"
|
||||
#define CMM_HOOK_MATCHER "Grep|Glob|Read|Search"
|
||||
#define CMM_HOOK_COMMAND \
|
||||
"echo 'Reminder: prefer codebase-memory-mcp search_graph/trace_call_path/" \
|
||||
"get_code_snippet over Grep/Glob/Read for code discovery. " \
|
||||
"get_code_snippet over Grep/Glob/Read/Search for code discovery. " \
|
||||
"Use get_code_snippet(qualified_name) instead of Read to view a function. " \
|
||||
"Fall back only if MCP returns insufficient results.' >&2"
|
||||
|
||||
/* Check if a PreToolUse array entry matches our hook (by matcher string) */
|
||||
/* Old matcher values from previous versions — recognized during upgrade so
|
||||
* upsert_hooks_json can remove them before inserting the current matcher. */
|
||||
static const char *cmm_old_matchers[] = {
|
||||
"Grep|Glob|Read",
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Check if a PreToolUse array entry matches our hook (current or old matcher). */
|
||||
static bool is_cmm_hook_entry(yyjson_mut_val *entry, const char *matcher_str) {
|
||||
yyjson_mut_val *matcher = yyjson_mut_obj_get(entry, "matcher");
|
||||
if (!matcher || !yyjson_mut_is_str(matcher)) {
|
||||
return false;
|
||||
}
|
||||
const char *val = yyjson_mut_get_str(matcher);
|
||||
// NOLINTNEXTLINE(readability-implicit-bool-conversion)
|
||||
return val != NULL && strcmp(val, matcher_str) == 0;
|
||||
if (!val) {
|
||||
return false;
|
||||
}
|
||||
if (strcmp(val, matcher_str) == 0) {
|
||||
return true;
|
||||
}
|
||||
/* Also match old versions for backwards-compatible upgrade */
|
||||
for (int i = 0; cmm_old_matchers[i]; i++) {
|
||||
if (strcmp(val, cmm_old_matchers[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generic hook upsert for both Claude Code and Gemini CLI */
|
||||
|
||||
@@ -742,6 +742,47 @@ TEST(swift_struct) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* --- Swift calls (port of PR #47 Go tests) --- */
|
||||
TEST(swift_simple_call) {
|
||||
CBMFileResult *r = extract("func main() { greet() }\nfunc greet() { print(\"hello\") }\n",
|
||||
CBM_LANG_SWIFT, "t", "main.swift");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(has_call(r, "greet"));
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(swift_method_call) {
|
||||
CBMFileResult *r = extract("class Foo {\n func bar() { baz.run() }\n}\n", CBM_LANG_SWIFT,
|
||||
"t", "Foo.swift");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(has_call(r, "baz.run"));
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(swift_constructor_call) {
|
||||
CBMFileResult *r =
|
||||
extract("func create() { let x = MyClass() }\n", CBM_LANG_SWIFT, "t", "create.swift");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(has_call(r, "MyClass"));
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(swift_chained_call) {
|
||||
CBMFileResult *r = extract("func setup() { AlarmScheduler.shared.startKeepAlive() }\n",
|
||||
CBM_LANG_SWIFT, "t", "setup.swift");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(r->calls.count > 0);
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* --- Objective-C --- */
|
||||
TEST(objc_interface) {
|
||||
CBMFileResult *r =
|
||||
@@ -2071,6 +2112,10 @@ SUITE(extraction) {
|
||||
|
||||
/* OOP/Systems variants */
|
||||
RUN_TEST(swift_struct);
|
||||
RUN_TEST(swift_simple_call);
|
||||
RUN_TEST(swift_method_call);
|
||||
RUN_TEST(swift_constructor_call);
|
||||
RUN_TEST(swift_chained_call);
|
||||
RUN_TEST(objc_interface);
|
||||
RUN_TEST(objc_implementation);
|
||||
RUN_TEST(dart_top_level_function);
|
||||
|
||||
Reference in new issue
Block a user