Skip to content

Meta: Go / cgo / Go+C extraction — tracking issue #1932

Description

@ilyabrykau-orca

Tracking issue for the Go / cgo / Go+C extraction work. Method: count a construct in source, count the same thing in the graph, treat any mismatch as a defect. Every item was minimised to a dummy fixture before filing, measured on one real Go + C/C++ repository (~1150 Go files, eBPF C probes, a Windows C++ driver — counts only), and carries a SQL detection recipe that works on any indexed repo. Each fix PR ships a reproduce-first test (RED proven before the change) and a fresh field census on the same tree.

Ledger — bugs

Issue Defect PR State Measured effect
#1906 Weak short-name strategies fabricate CALLS for Go selector calls #1907 open, CI green suffix_match 3817 → 113, same_module 3267 → 224; weak share of CALLS 36.0% → 12.4%, lsp_* 8481 → 10672 (re-resolved, not deleted)
#1909 Method QNs ignore the receiver — same-name methods collapse onto one node #1913 open, CI green Close methods 15 → 86, Process 12 → 47, Task 1 → 8; kills the flat same_module key
#1910 Multiple init() per package collapse onto one QN #1915 open, CI green init nodes 7 → 29, matching source exactly
#1926 cgo's import "C" resolves to an arbitrary project symbol named C #1931 open, CI green 27 false IMPORTS → 0
#1927 field_type_hint binds by receiver variable-name substring, not declared type #1936 open, CI green 1484 → 356; single-char receivers 376 → 0; Go→C/C++ 34 → 0; zero relocation
#1928 USAGE/WRITES/READS never consult the #725 cross-language guard (both resolvers) #1937 open, CI green Go→C/C++ WRITES 835 → 0, USAGE 1545 → 0; 6432 cross-language refs dropped, none same-language; CALLS/IMPORTS byte-identical
#1934 A Go import can resolve to a Function/Method (Strategies 1b + 3 are language-blind) #1938 open, CI green IMPORTS targets: Method 85 → 0, Function 4 → 0, Folder 2206 kept
#1935 Go struct fields never extracted (find_class_body stops one level above field_declaration_list) #1940 open, CI green 0 → 4533 Field nodes with declared types; blank _ padding skipped
#1942 A bare Go reference binds a struct Field (found field-validating #1940) #1944 open, CI green USAGE onto Go fields 21308 → 0, WRITES 5191 → 0

Combined stack (#1937 + #1940 + #1944) vs main: USAGE 29198 → 21035, WRITES 2681 → 774, +4533 field nodes — the graph gets nodes and loses junk edges.

Ledger — design-shaped (awaiting maintainer ack, no PR)

Issue Gap Damage
#1911 Build-tag twin files collide on one QN — draft PR #1946#-suffix, #495 pattern), ready on design ack 2177 τ-suffixed nodes / 372 files; swallowed-twin files 319 → 281; CALLS +62 — no edge-mass loss
#1929 cgo invisible — draft PR #1947: //export → 22 export_linkage contracts (exact), C.* CALLS 1 → 0, preamble flagged in coverage; C-grammar preamble parse stays open 39 call-shaped C.f( → 0 CALLS; 12 preamble functions → 0 nodes on main
#1930 Go chan/goroutines unmodelled — draft PR #1949: grammar-precise send/receive/select → gochan topology Channel nodes 2 → 205, EMITS 1 → 162, LISTENS_ON 2 → 256 on the measured repo; range/go/element-types deferred

Ledger — CI

Issue Problem PR State
#1952 test-windows-guards setup flake (nodes: None): counts read from list_projects, whose stats publish asynchronously — the index response carries them synchronously #1958 open; root cause reproduced off-CI deterministically, setup steps also retry once
#1959 CI never indexes Go end to end — the only binary-level harness fixtures are TS-only, which is where this whole defect family hid #1961 (stacked on #1958) open; polyglot fixture (structs, build-tag twins, cgo, channels) + Go-definition count in the path-equality gate; measured 28/46/12 defs, go=7, equal across ASCII/Latin-1/Cyrillic

Merge order

Cross-cutting theme

One failure mode at every layer: a heuristic binds by name shape and nothing checks the language or what the name can denote. #1906 (CALLS, guarded) → #1927 (field_type_hint, exempted on a false premise) → #1928 (references, never guarded) → #1934 (imports, label-blind) → #1942 (references, label-blind). Guarding one relocates mass to the next unguarded one — which is why every fix PR above now carries negative/exact-count probes (ei_edge_count_is, zero-project-edge assertions, parallel-twin fixtures) rather than floor-only asserts, closing #1932's original test-infra gap in place.

Verified working (audit surface closed, no issues needed)

Generics (receiver-qualified QNs unwrap generic_type; no [ in any QN) · embedding + interface dispatch (lsp_embed_dispatch 42, lsp_interface_dispatch 79, fan-out via 434 IMPLEMENTS) · //go:linkname (body-less decls get nodes; callers bind lsp_direct) · defer/closures (attributed to the enclosing named function) · implicit interface satisfaction + method values (lsp_callable_alias) · TESTS edges and Variable coverage · internal import resolution (2206/~2242 same-module imports → correct package Folder; residual was #1934). Assembly (.s): untested — no fixtures in the measured repo.

Detection recipes (run on any indexed repo)

-- call-graph shape
SELECT json_extract(properties,'$.strategy') AS strategy, count(*) AS n,
       round(avg(json_extract(properties,'$.confidence')), 3) AS conf
FROM edges WHERE type='CALLS' GROUP BY 1 ORDER BY n DESC;

-- node recovery vs source: grep -rc '^func init()' --include='*.go' .
SELECT count(*) FROM nodes WHERE name='init';

-- swallowed twins: a file whose only node is its own __file__
SELECT file_path, count(*) c FROM nodes GROUP BY 1 HAVING c = 1;

-- cross-language reference edges (any Go↔C/C++ row is suspect)
SELECT e.type, count(*) FROM edges e
JOIN nodes s ON s.id=e.source_id JOIN nodes t ON t.id=e.target_id
WHERE s.file_path LIKE '%.go'
  AND (t.file_path LIKE '%.c' OR t.file_path LIKE '%.h'
    OR t.file_path LIKE '%.cpp' OR t.file_path LIKE '%.hpp')
GROUP BY 1;

-- references onto Go fields (must be zero: field access is selector-only)
SELECT e.type, count(*) FROM edges e JOIN nodes t ON t.id=e.target_id
WHERE t.label='Field' AND t.file_path LIKE '%.go'
  AND e.type IN ('READS','WRITES','USAGE') GROUP BY 1;

-- Go import targets (anything not Folder/Module/File is false)
SELECT t.label, count(*) FROM edges e
JOIN nodes s ON s.id=e.source_id JOIN nodes t ON t.id=e.target_id
WHERE e.type='IMPORTS' AND s.file_path LIKE '%.go' GROUP BY 1;

Every census lives inline in its issue's body (and in the fix PR's description); issues in this family are self-contained.

Related work in other ecosystems: #1893 (Swift, method-QN class), #1276 (Python, closed), #495 (Rust cfg twins — the pattern #1911 wants), #725 (cross-language CALLS guard), #1114 (dispatch fan-out), #787 (file attribution).

Metadata

Metadata

Assignees

No one assigned

    Labels

    parsing/qualityGraph extraction bugs, false positives, missing edgeswindowsWindows-specific issues

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions