Commit Graph
2 Commits
Author SHA1 Message Date
bompusandClaude Opus 5.5 7ff2841e37 fix(resolution): ties that decide a link break by code unit, not the host's locale
Several resolution tie-breaks sorted paths or ids with a bare
localeCompare, which follows the host's locale, so two machines could
index the same repository differently: under Czech collation `ch/` sorts
after `h/`, under Danish `aa` sorts after `z`, and locale collation puts
`alpha/` before `Beta/` where code-unit order does the opposite.

The PR fixes the nearest-declaration tie in tsFieldCall, for
`this.field.method()` on a type declared in two equally near apps. On
top, the same bug at the three other sites that decide resolution:
- cpp-type-aliases: the declaration an alias resolves to when two
  headers declare it differently, for a C++ base class named through it;
- frameworks/react-native: the Swift copy of a module's class that a
  JS-to-native call reaches;
- go-func-field-synthesizer: the last tie-break of wiringOrder, which
  decides the values a capped channel keeps (its site comparison already
  names 'en' and stays).
All compare by code unit now. Comparators that only order output (CLI,
MCP and viewer listings, dead-code and hierarchy order, the context
builder's copybook entries) are left alone. The CHANGELOG bullet moves
from the released 1.6.1 section to Unreleased.

Validation: a test each for the TS, C++ and React Native sites; all 3
fail on main and pass here. Indexing `ch/` vs `h/` fixtures for those
three under a simulated English and a simulated Czech host (a
localeCompare preload that reaches the worker threads), main links
different targets in all three, this commit the same in both. A/B, main
vs this commit on an English-locale host, 12 repos (excalidraw, zod,
vben, bulletproof-react, jq, cobra, gin, etcd, prometheus, okhttp, with
flask and spring-modulith as controls): every dump byte-identical.
Indexed again under a simulated Danish host (the Go repos) and Czech
host (the TS repos), both arms match their English dumps, so these
repos reach no tie the locale decides; the fix matters where one does.

Original PR #1983 by @bompus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:05:28 +00:00
Colby MchenryandClaude Opus 5.5 4040eab975 fix(cpp): a base class links to the class C++ name lookup finds, not a namesake (#2407)
A C++ base class (`class DynamicMessage final : public Message`) was
resolved by its name alone, so a base named like a class of another
namespace, or of another language, bound to whichever namesake ranked
first. In protocolbuffers/protobuf, `DynamicMessage`, `MapEntry`,
`ZeroFieldsBase` and two arena_unittest classes derived from
`json_internal::ResolverPool::Message`; before #2397 they derived from the
PHP extension's C struct `Message`. The Go framework resolver claimed
those: protobuf ships Go examples, so the resolver is detected, its
`resolve()` runs for every language's refs (`languages` only gates
extraction), its PascalCase-struct rule found the C struct, and the
framework language gate lets C++ reach C. google/leveldb's and rocksdb's
iterators derived from an unrelated nested `Iterator` (`SkipList::Iterator`,
`WriteThread::WriteGroup::Iterator`), and leveldb's test comparators from a
`Comparator` struct that skiplist_test.cc declares for itself.

C and C++ inheritance refs now resolve in their own matcher
(cpp-supertypes.ts), ahead of every other strategy and with no
fallthrough, so no framework resolver, import strategy or name matcher sees
them, and only C and C++ declarations are candidates. The base is looked
up the way C++ looks it up:
- from the scope the deriving class is declared in, outwards, using the
  lookup cpp-type-aliases.ts (#2399) already has: a class scope with its
  bases, a qualified name a segment at a time, an alias followed to the
  class it names; `::Base` from the global scope only;
- then through what the file writes before the class: namespace aliases
  (`namespace _pbi = ::google::protobuf::internal;`), using-declarations
  and using-directives, and fmt's macro-opened namespaces;
- a class a .cc/.c file defines belongs to that translation unit;
- a template parameter, or a member of one, names no class: no edge.
When none of that finds the class, the only visible C/C++ class with that
qualified tail is taken, since the index loses some classes' namespaces
(`class PROTOBUF_EXPORT FieldDescriptor`, classes after a partial
specialization); several are a guess, so no edge.

The base is read as written, template arguments included, so an alias
template (`bool_constant<…>`) is found. An alias that leads to no project
class (one of `std::integral_constant`, one each `#if` arm declares
differently) is linked itself, as before.

Validated with site-keyed edge diffs on leveldb, fmt, protobuf and
rocksdb, and redis, SDWebImage and gson as controls (dumps
byte-identical): first against main 02d22aeb, then again on main
dd706469 after #2405, #2408 and #2400 landed, with identical site
diffs (#2402, merged after, changes only Go's implements synthesis).
Every removed edge was wrong: 9 protobuf
`suite_.ReportFailure` guesses that reached `ForkPipeRunner`, cpp-override
edges from the wrong bases, and two rocksdb bases that are template
parameters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 03:01:39 +00:00