Skip to content

fix(resolution): calls between C, C++ and Objective-C files link by name - #3052

Merged
colbymchenry merged 1 commit into
mainfrom
claude/fix-language-family-match
Oct 30, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/fix-language-family-match

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Summary

Name matching weighed a candidate by its raw language tag, so calls between C, C++ and Objective-C files were treated as crossing languages: a call whose name had more than one definition in the other two languages linked to nothing, and the one definition of a name was a 0.5 "cross-language" guess. Now:

  • the one candidate of a name is judged by language family (TypeScript/TSX/JavaScript, Java/Kotlin/Scala, C/C++/Objective-C/Swift, …), so a .tsx component calling the only .ts function of its name, or a C test calling the C API that a .cc file defines, is a 0.9 match instead of 0.5;
  • C, C++ and Objective-C are ranked as one language when a name has several candidates: their files share one table of names, and a .h file is C, C++ or Objective-C only as far as sniffing its text can tell (Dear ImGui's C++ imgui.h reads as C). An Objective-C .m file's _glfwPlatformSetTls(…), which glfw defines in both posix_thread.c and win32_thread.c, now links to the nearer one; before, both scored −80 and the call linked to nothing.

Reimplements #1662 by @ferrine. Its headline (dropping cross-family bare-name calls) landed with #2032; this is the raw-tag-versus-family comparison it also pointed at.

Root cause

matchByExactName's single-candidate confidence, findBestMatch's same-language skip and its +50/−80 language score, and matchFuzzy's single-candidate confidence all compared candidate.language === ref.language. They predate sameLanguageFamily, which the cross-family gate already uses.

Fix, and why the ranking change is narrower than the diagnosis

  • Single-candidate confidence (exact and fuzzy) compares families.
  • findBestMatch and the weighed set beside it compare through sameRankingLanguage: the same language, or both of C, C++ and Objective-C, with the very language worth one point, which only breaks a tie (a directory nearer counts 15).

Ranking every family by family, as the triage proposed, was measured and rejected. With it, excalidraw's this.app.store.scheduleCapture() calls in the App.*.ts files moved from Store::scheduleCapture (right) to App::scheduleCapture in the App.tsx beside them (wrong), a JSON import was linked to a constant in a build script, and okhttp gained 83 Java-to-Kotlin new X.Builder() / X.Factory guesses onto whichever Builder was nearest (new OkHttpClient.Builder() → MockResponse.Builder). In those families files reach each other's names through imports, and the raw tag had been keeping a name-only pick inside one language. The new test pins the excalidraw shape.

Validation

Left out

  • imgui.h being read as C is a header-detection question of its own; its new links land on ImVector's inline methods as the C parse extracts them.
  • TS/TSX and Java/Kotlin multi-candidate ranking keeps the raw tag (see above), so T6's pr1662-rank fixture (a .tsx call with a .ts sibling and a far .tsx namesake) still picks the .tsx one.
  • Edge confidence is read today by the viewer's "uncertain" folding (under 0.6) and by the pick between strategies; in this A/B the latter changed one excalidraw edge's label (framework 0.8 → exact-match 0.9, same target).

🤖 Generated with Claude Code

Name matching compared a candidate's raw language tag with the
reference's: the single-candidate confidence in matchByExactName and
matchFuzzy, and findBestMatch's same-language skip and +50/-80 score.
So a call whose name had several definitions in another of C, C++ and
Objective-C scored -80 for each and linked to nothing (an Objective-C
file's _glfwPlatformSetTls(), a C++ call into Dear ImGui's imgui.h, which
reads as C), and the one definition of a name across TSX and TS, or C and
C++, was a 0.5 cross-language guess.

The single-candidate confidence now compares language families
(sameLanguageFamily). Ranking treats C, C++ and Objective-C as one
language (sameRankingLanguage), the very language worth a point that only
breaks a tie; other families keep the language itself, because ranking
them by family moved excalidraw's Store::scheduleCapture calls to the
App.tsx method beside them and gave okhttp 83 wrong Java-to-Kotlin
Builder picks.

Validation:
- __tests__/name-match-language-family.test.ts, 8 tests (default and
  wasm): 6 fail on the base main; the pin that a .ts call keeps its .ts
  target over a .tsx namesake beside it passes on both; all pass with
  the fix. 24 related test files (cross-language, React Native, Expo,
  Fabric, frameworks, mixed TS/JSX, Objective-C, resolution): 746 pass.
- A/B, main vs fix: glfw +4 calls from Objective-C into C, imgui +93
  from C++ into imgui.h (read as C) and imstb_rectpack.h, all to the
  definitions meant; excalidraw, okhttp, leveldb and jq gain or lose no
  edge (43, 9, 97 and 30 unique-name links go from 0.5 to 0.9 with the
  same targets); flask and gin byte-identical.
- Index time, median of 3 interleaved: imgui 7.9 s main, 7.7 s fix;
  excalidraw 9.2 s main, 9.4 s fix.

Reimplements PR #1662 by ferrine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry merged commit 6d3804c into main Oct 30, 2026
@colbymchenry
colbymchenry deleted the claude/fix-language-family-match branch October 30, 2026 08:15
bompus added a commit to bompus/codegraph that referenced this pull request Oct 31, 2026
…one candidate is judged by family (colbymchenry#3052)

Name matching compared a candidate's raw language tag with the
reference's: the single-candidate confidence in matchByExactName and
matchFuzzy, and findBestMatch's same-language skip and +50/-80 score.
So a call whose name had several definitions in another of C, C++ and
Objective-C scored -80 for each and linked to nothing, and the one
definition of a name across TSX and TS, or C and C++, was a 0.5
cross-language guess.

The single-candidate confidence now compares language families; the
fork's language_family keeps C, C++, Objective-C and Swift apart where
upstream merges them as 'native', so the check reads the fork's
code_interop_group instead. Ranking treats C, C++ and Objective-C as
one language (same_ranking_language), the very language worth a point
that only breaks a tie; other families keep the language itself.

One fork addition upstream does not need: with `.h` names now ranking
as C++ same-language candidates, an unbound C or C++ receiver could
reach the free name-guess fallback and link to a header lookalike.
The fallback now skips C and C++ receivers outright, matching the
documented fork rule that such a call stays unlinked wherever the
receiver's written type cannot be read.

Ported from upstream 6d3804c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant