Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions internal/cbm/extract_imports.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions tests/test_extraction.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
Loading