diff --git a/internal/cbm/extract_imports.c b/internal/cbm/extract_imports.c index 2d8ed1e4e..cf70d1289 100644 --- a/internal/cbm/extract_imports.c +++ b/internal/cbm/extract_imports.c @@ -133,6 +133,19 @@ static void parse_go_import_spec(CBMExtractCtx *ctx, TSNode spec) { return; } + /* cgo: `import "C"` names the cgo PSEUDO-package, not a real one — "C" is + * reserved by go/build and no package with that import path can exist. + * Emitting it as an ordinary import makes the import resolver fall through + * to its symbol-name fallback (cbm_pipeline_resolve_import_node Strategy 3, + * pass_pkgmap.c), which matches the literal name "C" against every project + * node called C and picks the lexicographically smallest: on a real Go repo + * all 27 cgo files pointed their IMPORTS edge at the same unrelated `C` + * member of a test helper. Drop it — the C side is not a graph package, and + * the file's remaining imports are unaffected. */ + if (strcmp(path, "C") == 0) { + return; + } + TSNode name_node = ts_node_child_by_field_name(spec, TS_FIELD("name")); const char *local_name = !ts_node_is_null(name_node) ? cbm_node_text(a, name_node, ctx->source) : path_last(a, path); diff --git a/tests/test_extraction.c b/tests/test_extraction.c index 73219f4da..e3f743657 100644 --- a/tests/test_extraction.c +++ b/tests/test_extraction.c @@ -2865,6 +2865,25 @@ TEST(go_imports) { PASS(); } +/* cgo's `import "C"` is a pseudo-package, not a real import: keeping it lets the + * import resolver name-match "C" onto an arbitrary project symbol called C. The + * real imports of the same file must survive. */ +TEST(go_cgo_pseudo_import_dropped) { + CBMFileResult *r = extract("package m\n\n/*\nstatic int helper(void) { return 1; }\n*/\n" + "import \"C\"\n\nimport \"fmt\"\n\n" + "func Run() { fmt.Println(C.helper()) }\n", + CBM_LANG_GO, "t", "cgo.go"); + ASSERT_NOT_NULL(r); + ASSERT_FALSE(r->has_error); + ASSERT(has_import(r, "fmt")); + for (int i = 0; i < r->imports.count; i++) { + ASSERT_NOT_NULL(r->imports.items[i].module_path); + ASSERT_TRUE(strcmp(r->imports.items[i].module_path, "C") != 0); + } + cbm_free_result(r); + PASS(); +} + TEST(java_imports) { CBMFileResult *r = extract( "import java.util.List;\nimport java.util.ArrayList;\nimport static java.lang.Math.PI;\n" @@ -6543,6 +6562,7 @@ SUITE(extraction) { RUN_TEST(python_imports); RUN_TEST(js_imports); RUN_TEST(go_imports); + RUN_TEST(go_cgo_pseudo_import_dropped); RUN_TEST(java_imports); RUN_TEST(rust_imports); RUN_TEST(c_imports);