From c06a363513510a1e2fc2635b9900b57fb32e44f7 Mon Sep 17 00:00:00 2001 From: rudi193-cmd Date: Mon, 17 Aug 2026 19:36:36 -0600 Subject: [PATCH 1/4] fix(registry): drop unique_name CALLS across language boundaries Python `from unittest.mock import patch` to a unique TSX `patch`. Same language-family guard; JS/TS/TSX stay one family. Fixes #1572 Signed-off-by: rudi193-cmd Co-authored-by: Cursor Signed-off-by: rudi193-cmd --- src/pipeline/pass_calls.c | 7 ++-- src/pipeline/pass_parallel.c | 5 ++- src/pipeline/pipeline.h | 12 +++--- src/pipeline/registry.c | 28 ++++++++----- tests/test_pipeline.c | 79 +++++++++++++++++++++++++++++++++++- tests/test_registry.c | 42 ++++++++++++++++--- 6 files changed, 146 insertions(+), 27 deletions(-) diff --git a/src/pipeline/pass_calls.c b/src/pipeline/pass_calls.c index 84958954cf..85c48435a8 100644 --- a/src/pipeline/pass_calls.c +++ b/src/pipeline/pass_calls.c @@ -676,9 +676,10 @@ static int resolve_single_call(cbm_pipeline_ctx_t *ctx, CBMCall *call, if (!target_node || source_node->id == target_node->id) { return 0; } - /* #725: suffix_match is language-agnostic and will attach a Python - * Store.commit() call to a JS function named commit (or a Bash main - * to a Python main). Drop that weak cross-language edge. */ + /* #725/#1572: suffix_match and unique_name are language-agnostic and + * will attach a Python Store.commit() call to a JS function named + * commit, or a Python `with patch(...)` to a unique TSX `patch`. Drop + * those weak cross-language edges. */ if (cbm_suppress_cross_language_suffix_match(lang, target_node->file_path, res.strategy)) { return 0; } diff --git a/src/pipeline/pass_parallel.c b/src/pipeline/pass_parallel.c index e85ad015f1..6ca7f6af2c 100644 --- a/src/pipeline/pass_parallel.c +++ b/src/pipeline/pass_parallel.c @@ -3024,8 +3024,9 @@ static void resolve_file_calls(resolve_ctx_t *rc, resolve_worker_state_t *ws, CB memory_order_relaxed); if (target_node && source_node->id != target_node->id && cbm_suppress_cross_language_suffix_match(lang, target_node->file_path, res.strategy)) { - /* #725: same guard as pass_calls.c — do not emit a suffix_match - * CALLS edge across a language boundary. */ + /* #725/#1572: same guard as pass_calls.c — do not emit a + * suffix_match or unique_name CALLS edge across a language + * boundary. */ continue; } if (!target_node || source_node->id == target_node->id) { diff --git a/src/pipeline/pipeline.h b/src/pipeline/pipeline.h index e5a672cb0b..f76c54be13 100644 --- a/src/pipeline/pipeline.h +++ b/src/pipeline/pipeline.h @@ -320,11 +320,13 @@ bool cbm_weak_member_unique_name_exempt(bool is_python, bool receiver_is_self_at bool cbm_suppress_weak_local_binding_call(bool enabled, bool callee_is_locally_bound, const char *strategy); -/* #725: drop a suffix_match CALLS edge when the caller language and the - * target file's language disagree. unique_name (candidates == 1) is #1572 - * and is left alone; same_module / import_map / lsp_* are kept. JS/TS/TSX - * are one family so a .ts helper calling a .tsx function is not dropped. - * Pure; unit-tested in test_registry.c. */ +/* #725/#1572: drop a suffix_match or unique_name CALLS edge when the caller + * language and the target file's language disagree. suffix_match is the + * import-distance winner among many same-named symbols (#725); + * unique_name is the candidates==1 case of the same class (#1572). + * same_module / import_map / lsp_* are kept. JS/TS/TSX are one family so a + * .ts helper calling a .tsx function is not dropped. Pure; unit-tested in + * test_registry.c. */ bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const char *target_file_path, const char *strategy); diff --git a/src/pipeline/registry.c b/src/pipeline/registry.c index c99c72d8d5..87de4a5440 100644 --- a/src/pipeline/registry.c +++ b/src/pipeline/registry.c @@ -697,7 +697,8 @@ bool cbm_suppress_weak_local_binding_call(bool enabled, bool callee_is_locally_b static bool js_ts_family(CBMLanguage lang) { return lang == CBM_LANG_JAVASCRIPT || lang == CBM_LANG_TYPESCRIPT || lang == CBM_LANG_TSX || - lang == CBM_LANG_ARKTS; + lang == CBM_LANG_ARKTS || lang == CBM_LANG_VUE || lang == CBM_LANG_SVELTE || + lang == CBM_LANG_ASTRO; } /* C and C++ are one family for cross-language checks: .h maps to CBM_LANG_CPP @@ -707,6 +708,10 @@ static bool c_cpp_family(CBMLanguage lang) { return lang == CBM_LANG_C || lang == CBM_LANG_CPP; } +static bool jvm_family(CBMLanguage lang) { + return lang == CBM_LANG_JAVA || lang == CBM_LANG_KOTLIN || lang == CBM_LANG_GROOVY; +} + static const char *path_basename(const char *path) { if (!path || !path[0]) { return path; @@ -736,15 +741,12 @@ bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const cha /* Two same-named symbols in different languages: suffix_match picks one * winner by import-distance and attaches every bare-name call to it * (#725, Bash/Python main, JS/Python commit). unique_name is the - * candidates==1 case (#1572) and is not this guard — except for a build - * or configuration caller, where even a unique match into another - * language is a collision by construction. */ - if (!strategy) { - return false; - } - bool config_caller = build_config_language(caller_lang); - if (strcmp(strategy, "suffix_match") != 0 && - !(config_caller && strcmp(strategy, "unique_name") == 0)) { + * candidates==1 case of the same class (#1572, Python + * `from unittest.mock import patch` binding to a unique TSX `patch`). + * Build/config callers have no cross-language call semantics, so their + * unique_name collisions are covered by the same guard. */ + if (!strategy || + (strcmp(strategy, "suffix_match") != 0 && strcmp(strategy, "unique_name") != 0)) { return false; } if (caller_lang == CBM_LANG_COUNT || !target_file_path || !target_file_path[0]) { @@ -760,6 +762,12 @@ bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const cha if (js_ts_family(caller_lang) && js_ts_family(target_lang)) { return false; } + if (c_cpp_family(caller_lang) && c_cpp_family(target_lang)) { + return false; + } + if (jvm_family(caller_lang) && jvm_family(target_lang)) { + return false; + } return true; } diff --git a/tests/test_pipeline.c b/tests/test_pipeline.c index 6ef16a89be..652d78acaf 100644 --- a/tests/test_pipeline.c +++ b/tests/test_pipeline.c @@ -8102,7 +8102,7 @@ TEST(pipeline_python_cross_module_call) { /* #725: two same-named symbols across languages must not share CALLS edges. * Python Store.commit is the real callee of save(); the JS Editor.commit * function is a distinct binding and must have no inbound CALLS from Python. - * unique_name (candidates==1) is #1572 and is not this claim. */ + * unique_name (candidates==1) is the #1572 pipeline test. */ TEST(pipeline_cross_language_same_name_does_not_share_calls_issue725) { const char *files[] = {"store.py", "app.py", "web/src/pages/Editor.js"}; const char *contents[] = {"class Store:\n" @@ -8183,6 +8183,82 @@ TEST(pipeline_cross_language_same_name_does_not_share_calls_issue725) { PASS(); } +/* #1572: unique_name (candidates==1) must not bind a Python mock.patch + * call to the only project symbol named `patch` when that symbol is TSX. + * The issue fixture is two files: frontend/Panel.tsx and backend/test_thing.py. */ +TEST(pipeline_cross_language_unique_name_does_not_share_calls_issue1572) { + const char *files[] = {"frontend/Panel.tsx", "backend/test_thing.py"}; + const char *contents[] = { + "function patch(x: string) {\n" + " return x;\n" + "}\n", + + "from unittest.mock import patch\n" + "\n" + "def test_one():\n" + " with patch(\"os.path.exists\"):\n" + " pass\n" + "\n" + "def test_two():\n" + " with patch(\"os.path.join\"):\n" + " pass\n"}; + + if (setup_lang_repo(files, contents, 2) != 0) + FAIL("tmpdir"); + char db[512]; + snprintf(db, sizeof(db), "%s/test.db", g_lang_tmpdir); + + cbm_pipeline_t *p = cbm_pipeline_new(g_lang_tmpdir, db, CBM_MODE_FULL); + ASSERT_NOT_NULL(p); + ASSERT_EQ(cbm_pipeline_run(p), 0); + + cbm_store_t *s = cbm_store_open_path(db); + ASSERT_NOT_NULL(s); + const char *proj = cbm_pipeline_project_name(p); + + cbm_node_t *patches = NULL; + int npatch = 0; + cbm_store_find_nodes_by_name(s, proj, "patch", &patches, &npatch); + ASSERT_GT(npatch, 0); + + int64_t tsx_id = 0; + for (int i = 0; i < npatch; i++) { + if (patches[i].file_path && strstr(patches[i].file_path, "Panel.tsx")) + tsx_id = patches[i].id; + } + ASSERT_TRUE(tsx_id != 0); + + cbm_edge_t *into_tsx = NULL; + int ntsx = 0; + cbm_store_find_edges_by_target_type(s, tsx_id, "CALLS", &into_tsx, &ntsx); + ASSERT_EQ(ntsx, 0); + + const char *callers[] = {"test_one", "test_two"}; + for (int c = 0; c < 2; c++) { + cbm_node_t *fns = NULL; + int nfn = 0; + cbm_store_find_nodes_by_name(s, proj, callers[c], &fns, &nfn); + ASSERT_GT(nfn, 0); + cbm_edge_t *from_fn = NULL; + int nfrom = 0; + cbm_store_find_edges_by_source_type(s, fns[0].id, "CALLS", &from_fn, &nfrom); + for (int i = 0; i < nfrom; i++) { + ASSERT_TRUE(from_fn[i].target_id != tsx_id); + } + if (from_fn) + cbm_store_free_edges(from_fn, nfrom); + cbm_store_free_nodes(fns, nfn); + } + + if (into_tsx) + cbm_store_free_edges(into_tsx, ntsx); + cbm_store_free_nodes(patches, npatch); + cbm_store_close(s); + cbm_pipeline_free(p); + teardown_lang_repo(); + PASS(); +} + TEST(pipeline_go_type_classification) { /* Port of TestGoTypeClassification */ const char *files[] = {"types.go"}; @@ -15191,6 +15267,7 @@ SUITE(pipeline) { RUN_TEST(pipeline_swift_cross_package_import); RUN_TEST(pipeline_python_cross_module_call); RUN_TEST(pipeline_cross_language_same_name_does_not_share_calls_issue725); + RUN_TEST(pipeline_cross_language_unique_name_does_not_share_calls_issue1572); RUN_TEST(pipeline_go_type_classification); RUN_TEST(pipeline_go_grouped_types); RUN_TEST(pipeline_kotlin_project); diff --git a/tests/test_registry.c b/tests/test_registry.c index 5f751a8993..112666c147 100644 --- a/tests/test_registry.c +++ b/tests/test_registry.c @@ -831,9 +831,10 @@ TEST(cross_language_config_caller_drops_unique_name_too) { cbm_suppress_cross_language_suffix_match(CBM_LANG_CMAKE, "src/main.c", "unique_name")); ASSERT_TRUE( cbm_suppress_cross_language_suffix_match(CBM_LANG_YAML, "app/models.py", "unique_name")); - /* A code caller's unique_name into another language is still #1572. */ - ASSERT_FALSE(cbm_suppress_cross_language_suffix_match( - CBM_LANG_PYTHON, "web/src/pages/Editor.js", "unique_name")); + /* A code caller's unique_name into another language is #1572. */ + ASSERT_TRUE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, + "web/src/pages/Editor.js", + "unique_name")); /* Same-language config targets are untouched. */ ASSERT_FALSE( cbm_suppress_cross_language_suffix_match(CBM_LANG_MAKEFILE, "lib/Makefile", "unique_name")); @@ -912,7 +913,7 @@ TEST(registry_tie_break_is_independent_of_registration_order) { TEST(cross_language_suffix_match_drops_py_vs_js) { /* #725: two same-named symbols in different languages. suffix_match is the - * strategy that collapses them; unique_name is #1572 and must stay. */ + * strategy that collapses them. unique_name is covered by the #1572 test. */ ASSERT_TRUE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "web/src/pages/Editor.js", "suffix_match")); ASSERT_TRUE( @@ -921,8 +922,6 @@ TEST(cross_language_suffix_match_drops_py_vs_js) { cbm_suppress_cross_language_suffix_match(CBM_LANG_BASH, "cli/main.py", "suffix_match")); ASSERT_FALSE( cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "store.py", "suffix_match")); - ASSERT_FALSE(cbm_suppress_cross_language_suffix_match( - CBM_LANG_PYTHON, "web/src/pages/Editor.js", "unique_name")); ASSERT_FALSE(cbm_suppress_cross_language_suffix_match( CBM_LANG_PYTHON, "web/src/pages/Editor.js", "same_module")); ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, @@ -987,6 +986,36 @@ TEST(go_bare_ref_never_binds_field) { PASS(); } +TEST(cross_language_unique_name_drops_py_vs_tsx) { + /* #1572: unique_name is the candidates==1 case of the same class as + * suffix_match. Python `from unittest.mock import patch` must not bind + * to a unique TSX `function patch`. */ + ASSERT_TRUE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "frontend/Panel.tsx", + "unique_name")); + ASSERT_TRUE(cbm_suppress_cross_language_suffix_match(CBM_LANG_TSX, "backend/test_thing.py", + "unique_name")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "backend/test_thing.py", + "unique_name")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "frontend/Panel.tsx", + "same_module")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "frontend/Panel.tsx", + "import_map")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_PYTHON, "frontend/Panel.tsx", + "lsp_direct")); + /* JS/TS/TSX are one family — a .ts caller of a .tsx unique_name stays. */ + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_TYPESCRIPT, "frontend/Panel.tsx", + "unique_name")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_JAVASCRIPT, "frontend/Panel.tsx", + "unique_name")); + /* C/C++, JVM, and Vue→TS families stay exempt for unique_name. */ + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_C, "bpf/probe.h", "unique_name")); + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_GROOVY, "buildSrc/Foo.java", "unique_name")); + ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_VUE, "services/Queue.ts", + "unique_name")); + PASS(); +} + TEST(dynamic_suppress_drops_weak_method_matches) { /* #592/#606/#1276: a member call whose receiver the LSP could not type, that * landed via a WEAK short-name strategy, is generic-resolver noise → drop. @@ -1244,6 +1273,7 @@ SUITE(registry) { RUN_TEST(registry_tie_break_is_independent_of_registration_order); RUN_TEST(cross_language_ref_drops_go_vs_c); RUN_TEST(go_bare_ref_never_binds_field); + RUN_TEST(cross_language_unique_name_drops_py_vs_tsx); RUN_TEST(dynamic_suppress_drops_weak_method_matches); RUN_TEST(dynamic_suppress_keeps_high_confidence_and_non_methods); RUN_TEST(python_builtin_member_table_matches_builtin_type_methods); From e289d29188f3c0c5568a9dbeb0101b0a7fbd3909 Mon Sep 17 00:00:00 2001 From: rudi193-cmd Date: Tue, 22 Sep 2026 18:04:49 -0600 Subject: [PATCH 2/4] fix(registry): drop unused build_config_language helper Widening unique_name to all callers made the helper dead code; -Werror unused-function broke CI on the production build. Signed-off-by: rudi193-cmd Co-authored-by: Cursor Signed-off-by: rudi193-cmd --- src/pipeline/registry.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/pipeline/registry.c b/src/pipeline/registry.c index 87de4a5440..706cc932b6 100644 --- a/src/pipeline/registry.c +++ b/src/pipeline/registry.c @@ -726,16 +726,6 @@ static const char *path_basename(const char *path) { return slash ? slash + 1 : path; } -/* Build and configuration languages have no cross-language call semantics: a - * Makefile's `$(eval ...)` or a CMake `function(...)` names nothing in a C - * file, so a bare-name bind into another language is always a collision - * (2026-09-16 probe: kernel Makefile targets bound to `sk_psock.eval`). */ -static bool build_config_language(CBMLanguage lang) { - return lang == CBM_LANG_MAKEFILE || lang == CBM_LANG_CMAKE || lang == CBM_LANG_YAML || - lang == CBM_LANG_TOML || lang == CBM_LANG_JSON || lang == CBM_LANG_INI || - lang == CBM_LANG_DOCKERFILE; -} - bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const char *target_file_path, const char *strategy) { /* Two same-named symbols in different languages: suffix_match picks one From 7e6750d0a5f4348f9b834299627c3b9a714ddcec Mon Sep 17 00:00:00 2001 From: rudi193-cmd Date: Sat, 26 Sep 2026 14:12:56 -0600 Subject: [PATCH 3/4] style(tests): wrap unique_name family ASSERT_FALSE lines for lint-ci Signed-off-by: rudi193-cmd Co-authored-by: Cursor --- tests/test_registry.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_registry.c b/tests/test_registry.c index 112666c147..f19914971e 100644 --- a/tests/test_registry.c +++ b/tests/test_registry.c @@ -1008,9 +1008,11 @@ TEST(cross_language_unique_name_drops_py_vs_tsx) { ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_JAVASCRIPT, "frontend/Panel.tsx", "unique_name")); /* C/C++, JVM, and Vue→TS families stay exempt for unique_name. */ - ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_C, "bpf/probe.h", "unique_name")); ASSERT_FALSE( - cbm_suppress_cross_language_suffix_match(CBM_LANG_GROOVY, "buildSrc/Foo.java", "unique_name")); + cbm_suppress_cross_language_suffix_match(CBM_LANG_C, "bpf/probe.h", "unique_name")); + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_GROOVY, "buildSrc/Foo.java", + "unique_name")); ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_VUE, "services/Queue.ts", "unique_name")); PASS(); From b46c6d43f2efe6f0a1de8c77b73085183aa5da1a Mon Sep 17 00:00:00 2001 From: rudi193-cmd Date: Sun, 27 Sep 2026 07:53:09 -0600 Subject: [PATCH 4/4] fix(registry): widen CALLS families for CUDA, ObjC, HTML (#1702) Add CUDA and Objective-C to c_cpp_family, HTML to js_ts_family, and skip suppression when the target extension is content-disambiguated (.m, .cls, .inc, .cfc, .frm). Move pipeline #1572 integration test to the external-specifier follow-up branch. Signed-off-by: rudi193-cmd Co-authored-by: Cursor --- src/pipeline/registry.c | 27 +++++++++++++-- tests/test_pipeline.c | 77 ----------------------------------------- tests/test_registry.c | 10 ++++++ 3 files changed, 34 insertions(+), 80 deletions(-) diff --git a/src/pipeline/registry.c b/src/pipeline/registry.c index 706cc932b6..ca432e4ec3 100644 --- a/src/pipeline/registry.c +++ b/src/pipeline/registry.c @@ -698,14 +698,16 @@ bool cbm_suppress_weak_local_binding_call(bool enabled, bool callee_is_locally_b static bool js_ts_family(CBMLanguage lang) { return lang == CBM_LANG_JAVASCRIPT || lang == CBM_LANG_TYPESCRIPT || lang == CBM_LANG_TSX || lang == CBM_LANG_ARKTS || lang == CBM_LANG_VUE || lang == CBM_LANG_SVELTE || - lang == CBM_LANG_ASTRO; + lang == CBM_LANG_ASTRO || lang == CBM_LANG_HTML; } /* C and C++ are one family for cross-language checks: .h maps to CBM_LANG_CPP * in the extension table, so a .c file referencing a symbol declared in its - * own header would otherwise read as a language boundary. */ + * own header would otherwise read as a language boundary. CUDA and Objective-C + * use the same front end for header calls (#1702 census addendum). */ static bool c_cpp_family(CBMLanguage lang) { - return lang == CBM_LANG_C || lang == CBM_LANG_CPP; + return lang == CBM_LANG_C || lang == CBM_LANG_CPP || lang == CBM_LANG_CUDA || + lang == CBM_LANG_OBJC; } static bool jvm_family(CBMLanguage lang) { @@ -726,6 +728,19 @@ static const char *path_basename(const char *path) { return slash ? slash + 1 : path; } +/* Target language from basename alone is wrong for extensions whose real + * language is decided by file content during discovery (.m → MATLAB in the + * table but often Objective-C, etc.). Never suppress on filename guess alone. */ +static bool target_lang_from_filename_ambiguous(const char *target_file_path) { + const char *base = path_basename(target_file_path); + const char *dot = strrchr(base, '.'); + if (!dot || dot == base) { + return false; + } + return strcmp(dot, ".m") == 0 || strcmp(dot, ".cls") == 0 || strcmp(dot, ".inc") == 0 || + strcmp(dot, ".cfc") == 0 || strcmp(dot, ".frm") == 0; +} + bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const char *target_file_path, const char *strategy) { /* Two same-named symbols in different languages: suffix_match picks one @@ -749,6 +764,9 @@ bool cbm_suppress_cross_language_suffix_match(CBMLanguage caller_lang, const cha if (caller_lang == target_lang) { return false; } + if (target_lang_from_filename_ambiguous(target_file_path)) { + return false; + } if (js_ts_family(caller_lang) && js_ts_family(target_lang)) { return false; } @@ -783,6 +801,9 @@ bool cbm_suppress_cross_language_ref(CBMLanguage caller_lang, const char *target if (caller_lang == target_lang) { return false; } + if (target_lang_from_filename_ambiguous(target_file_path)) { + return false; + } if (js_ts_family(caller_lang) && js_ts_family(target_lang)) { return false; } diff --git a/tests/test_pipeline.c b/tests/test_pipeline.c index 652d78acaf..3aa197cfba 100644 --- a/tests/test_pipeline.c +++ b/tests/test_pipeline.c @@ -8183,82 +8183,6 @@ TEST(pipeline_cross_language_same_name_does_not_share_calls_issue725) { PASS(); } -/* #1572: unique_name (candidates==1) must not bind a Python mock.patch - * call to the only project symbol named `patch` when that symbol is TSX. - * The issue fixture is two files: frontend/Panel.tsx and backend/test_thing.py. */ -TEST(pipeline_cross_language_unique_name_does_not_share_calls_issue1572) { - const char *files[] = {"frontend/Panel.tsx", "backend/test_thing.py"}; - const char *contents[] = { - "function patch(x: string) {\n" - " return x;\n" - "}\n", - - "from unittest.mock import patch\n" - "\n" - "def test_one():\n" - " with patch(\"os.path.exists\"):\n" - " pass\n" - "\n" - "def test_two():\n" - " with patch(\"os.path.join\"):\n" - " pass\n"}; - - if (setup_lang_repo(files, contents, 2) != 0) - FAIL("tmpdir"); - char db[512]; - snprintf(db, sizeof(db), "%s/test.db", g_lang_tmpdir); - - cbm_pipeline_t *p = cbm_pipeline_new(g_lang_tmpdir, db, CBM_MODE_FULL); - ASSERT_NOT_NULL(p); - ASSERT_EQ(cbm_pipeline_run(p), 0); - - cbm_store_t *s = cbm_store_open_path(db); - ASSERT_NOT_NULL(s); - const char *proj = cbm_pipeline_project_name(p); - - cbm_node_t *patches = NULL; - int npatch = 0; - cbm_store_find_nodes_by_name(s, proj, "patch", &patches, &npatch); - ASSERT_GT(npatch, 0); - - int64_t tsx_id = 0; - for (int i = 0; i < npatch; i++) { - if (patches[i].file_path && strstr(patches[i].file_path, "Panel.tsx")) - tsx_id = patches[i].id; - } - ASSERT_TRUE(tsx_id != 0); - - cbm_edge_t *into_tsx = NULL; - int ntsx = 0; - cbm_store_find_edges_by_target_type(s, tsx_id, "CALLS", &into_tsx, &ntsx); - ASSERT_EQ(ntsx, 0); - - const char *callers[] = {"test_one", "test_two"}; - for (int c = 0; c < 2; c++) { - cbm_node_t *fns = NULL; - int nfn = 0; - cbm_store_find_nodes_by_name(s, proj, callers[c], &fns, &nfn); - ASSERT_GT(nfn, 0); - cbm_edge_t *from_fn = NULL; - int nfrom = 0; - cbm_store_find_edges_by_source_type(s, fns[0].id, "CALLS", &from_fn, &nfrom); - for (int i = 0; i < nfrom; i++) { - ASSERT_TRUE(from_fn[i].target_id != tsx_id); - } - if (from_fn) - cbm_store_free_edges(from_fn, nfrom); - cbm_store_free_nodes(fns, nfn); - } - - if (into_tsx) - cbm_store_free_edges(into_tsx, ntsx); - cbm_store_free_nodes(patches, npatch); - cbm_store_close(s); - cbm_pipeline_free(p); - teardown_lang_repo(); - PASS(); -} - TEST(pipeline_go_type_classification) { /* Port of TestGoTypeClassification */ const char *files[] = {"types.go"}; @@ -15267,7 +15191,6 @@ SUITE(pipeline) { RUN_TEST(pipeline_swift_cross_package_import); RUN_TEST(pipeline_python_cross_module_call); RUN_TEST(pipeline_cross_language_same_name_does_not_share_calls_issue725); - RUN_TEST(pipeline_cross_language_unique_name_does_not_share_calls_issue1572); RUN_TEST(pipeline_go_type_classification); RUN_TEST(pipeline_go_grouped_types); RUN_TEST(pipeline_kotlin_project); diff --git a/tests/test_registry.c b/tests/test_registry.c index f19914971e..033852af26 100644 --- a/tests/test_registry.c +++ b/tests/test_registry.c @@ -1015,6 +1015,16 @@ TEST(cross_language_unique_name_drops_py_vs_tsx) { "unique_name")); ASSERT_FALSE(cbm_suppress_cross_language_suffix_match(CBM_LANG_VUE, "services/Queue.ts", "unique_name")); + /* #1702 addendum: CUDA / ObjC / HTML inline script stay in-family. */ + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_CUDA, "kernels/vec.h", "unique_name")); + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_OBJC, "include/Foo.h", "unique_name")); + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_HTML, "static/app.js", "unique_name")); + /* .m targets are MATLAB by extension table but often ObjC — do not suppress. */ + ASSERT_FALSE( + cbm_suppress_cross_language_suffix_match(CBM_LANG_OBJC, "models/Foo.m", "unique_name")); PASS(); }