Repository navigation
Conversation
…re not hubs (#2122) Found by the README-wide sweep: vendored bundles topped "most depended on" across many repos — delphimvcframework's bundled `Buffer` (6,162) and four `n`s (2,386 each), retrofit's docs `main.js` `t`/`e`/`i`, TestBox's `__webpack_require__` — because only `*.min.js` was recognized as generated. - detectGeneratedFile (index time, persisted as files.generated) now also flags a .js/.mjs/.cjs file whose text is mostly lines of 1,000+ chars AND whose long lines are code (≥3% `;{}(),`) — not an ordinary file carrying one long base64 string — and any file that defines webpack's `__webpack_require__` loader, however readable its lines. The path rule also matches `-min.js` (underscore-min.js). - Entry points' hubs skip nodes in generated files, as they skip tests. Scanned every .js file of express, axios, lodash, excalidraw, typeorm, zod, trpc, hono, bulletproof-react: zero new flags on hand-written code; newly caught: lodash vendor/underscore/underscore-min.js, retrofit website main.js (754 KB) + prism.js, TestBox syntaxhighlighter.js (webpack). Co-authored-by: Claude Opus 5.5 <[email protected]>
…2123) Found by the README-wide sweep: cats' most-depended-on symbols were an `implicit def A` (4,916) and a `case class B()` declared inside a test method (3,573) — every type parameter `A`/`B`/`F` in the library bound to them; getx's `T` to a constant `T`; serde's `E`/`T`/`D`/`S`/`F` to test structs. New seam gate (type-parameters.ts, applied in resolveOne so every strategy obeys it): - A resolved TYPE reference whose name an enclosing declaration declares as a type parameter is that parameter: read from the heads (the index records none) — after the declared name (`class Foo<T>`, `fn f<T>`, `func F[T any]`, `def f[F[_]: Monad, A]`), before it detached from a type (`<T> T max(`, `fun <T> f`), a C++ `template <…>` above; annotations (`@sp(Int) A`), variance and keywords skipped; a `[…]` list counts only [] and () so Scala's `B >: A` bound does not close it; lists up to 40 lines. - Scala: a bare name a `def` takes as a value parameter (`(f: A => B)`, `(implicit G: …)`) is that parameter — cats bound 846 `f(a)` calls to a case class's `f` field. Class parameters are fields and are left alone. - Scala: a BARE (in the source) type reference reaches a member of another type only from inside it, a subtype, or a file importing its members; otherwise the in-scope type of that name is taken when one fits (cats' `trait FlatMap`, not `Eval`'s nested `FlatMap`; sttp's `trait Backend`). Name matcher: - A type (class/struct/enum/interface/trait/alias) declared inside a function is only reachable from inside it, like nested functions (#1230). - A capitalized Scala type position never names a method. A/B vs main (edge diffs, every change classified; each arm's init exit code checked — an earlier cut crashed resolution on a Scala method named `*`, now pinned by the test): cats −25,281/+179 (the gains retargets to the in-scope FlatMap/State; the real types Shown and IsEq kept 5/5 and 315/315), sttp −1,237/+23, getx −430, serde −446/+9, typeorm −632/+152 (`EntityTarget<Entity>`'s type parameter; codemod fixtures' function-local classes), gson −9; okio/fmt ±2, Newtonsoft.Json and gin byte-identical. Co-authored-by: Claude Opus 5.5 <[email protected]>
Found by the README-wide sweep: ripgrep bound 469 `Some(x)` calls to its own `EncodingMode::Some` variant and 536 `Ok(x)` to `ParseResult::Ok`; serde bound its `Ok(…)`/`Result<…>` to the `struct Ok` / `struct Result` its macro-hygiene test declares (845 on one); tokio 924 `Ok` onto `TransitionToIdle::Ok`, 290 `drop(x)` onto a `drop` method. For a name that is bare IN THE SOURCE (a `::` path is kept by its last segment and is not a prelude lookup — checked at the reference's column): - an enum variant is in scope only through a `use` of it (and its enum) or of its enum's `*`, and never names a type; - a prelude name (Ok/Err/Some/None/Result/Option/Box/Vec/String/drop/…) reaches a project item in another file only through a project `use` of that name or a glob of that item's own module (`use crate::glob::*`, `use super::*` for the parent) — `use std::…` trees don't count, and the `use` scan runs on comment-stripped text (a doc comment's "…use the Option…" once read as an import); - fuzzy matching is case-exact for Rust (`Bytes` ≠ method `bytes`, `Ok` ≠ fn `ok`). Applied as a candidate filter (so the in-scope item can win) and at resolveOne's seam — a Rust framework resolver's `Ok(x)` → `struct Ok` construction bypassed name matching. A/B vs main (edge diffs, every change classified): ripgrep −1,462/+0, serde −2,072/+40, tokio −1,820/+2, clap −752/+7, axum −397/+4, bat −45/+0 — losses are Ok/Some/Err/Result/Option/Vec/drop and same-named variants pinned on project items; gains are pre-existing same-name ambiguity (serde's two `Content` enums). Co-authored-by: Claude Opus 5.5 <[email protected]>
… never by name alone (#2125) Found by the README-wide sweep — Django/Flask/FastAPI apps' most-depended-on lists were test and serializer methods: netbox `UserConfig.all` (3,610 from `X.objects.all()`), `PortSerializer.create` (2,093 from `.objects.create`), a test-local `FakeQuerySet.count` (1,910); healthchecks `AuthTestCase.get` (880 from `Channel.objects.get()`), `ProfileAdmin.login` (702 from `self.client.login()`); mealie `_FakeHTTPResponse.json`. Python keeps a call through a receiver it cannot name (`User.objects.get`, `self.client.login`, `request.POST.get`) as the bare `get` / `login`, and exact-name matching then took any class's method by proximity. The call's shape is now read at its column (the call's start): - `bare` (`get(1)`): not a method — Python has no implicit self — and not a project symbol when the file takes that name `from` a module the project doesn't contain (`from django.shortcuts import render`); - `chained`: only a member of what the chain names last — a method of a class of that name (case/underscores ignored: `self.store` → `Store`, `self.user_service` → `UserService`) or a function/class in a module of that name (`app.helpers.slugify()` → helpers.py); - `self.x()` / `cls.x()`, and chains split across lines: unchanged. Fuzzy matching is case-exact for Python (`dir(…)` ≠ class `Dir`). Lexical reachability now walks every enclosing scope, so a method of a class declared inside a function is only reachable in there (memoized per candidate). A/B vs main (edge diffs, every change classified): netbox −18,091/+73 (indexes 8s → 5s), healthchecks −3,354/+361, pytest −2,950/+105, mealie −1,802/+6, allauth −1,086/+57, DRF −943/+50, flask −167/+17, httpx −147/+24. Gains are precise member links (`self.channel.notify` → Channel.notify, `item.stash.get` → Stash.get, `config.cache.get` → Cache.get, `self.provider.verify_token`); the one deliberate loss class is calls through an instance whose type needs inference (`flask.g.setdefault` in flask's own repo). excalidraw, typeorm, gson, okio, AutoMapper, gin and hono byte-identical. Co-authored-by: Claude Opus 5.5 <[email protected]>
…atic imports (#2126) Found by the README-wide sweep: halo's most-depended-on symbols were an `EmailVerificationService.verify` (1,038 — Mockito's `verify(mock)`) and a builder's `eq` (845 — ArgumentMatchers `eq`); retrofit's a test helper's `assertThat` (1,357 — Truth); mall's a DTO's `hashCode` (Object's). A bare Java call (`verify(x)`, `helper()`, `this.x()`, `super.x()`) now has only method candidates declared on a class around it, on one of that class's supertypes (read transitively from the declarations' `extends` / `implements` — the resolved edges don't exist yet on the first pass), or imported statically (`import static a.B.m;` / `a.B.*`). Memoized per type and per file. A/B vs main (edge diffs, every change classified): halo −2,103/+145, retrofit −1,380/+18, commons-lang −202/+87, jsoup −92/+45, mall −76, gson −7/+4. Gains are the right target where one exists: halo's `and` / `equal` / `isNull` through `import static …Queries.*`, jsoup's `attr(…)` through `LeafNode`, commons-lang's `addExact` on its own class instead of a nested MathBridge, retrofit's `getRawType` through `CallAdapter.Factory`. Co-authored-by: Claude Opus 5.5 <[email protected]>
…2128) Calls in `.vue`, `.svelte` and `.astro` files carry their own language, so the JS/TS rules from #2120 never applied to them: halo's `t('…')` from `useI18n()` went to an interface property `t` (562 callers) and `ref(…)` from `vue` to a local `ref` (523). "Outside the repository" is now a package the importing file's package.json chain (or a Deno import map) declares, a Node built-in, `@std/…`, or a framework's virtual module. An alias the resolver can't follow — SvelteKit's `$lib/…`, a nested Nuxt app's `~/…`, a nested app's own `@/…` — stays the project's, and a `workspace:`/`file:`/`link:` dependency is in the repo. SFC files also get the JS built-ins (`fetch`, `Error`, `Map`), and a file's own import of a built-in's name (`import Map from './Map.svelte'`) is the import. Untyped three-segment chains (`api.groupReports.getAll()`) keep resolving in SFCs, where they reach their API client class. Co-authored-by: Claude Opus 5.5 <[email protected]>
…repo (#2129) create-t3-turbo, tamagui's starter and react-native-reusables keep an Expo app beside a Next.js app. Expo Router read the Next app's `app/` folder as its own, so `layout.tsx` became a `/layout` screen, `page.tsx` a `/page` one, `_components/posts.tsx` and `api/auth/[...all]/route.ts` screens too, and a shared `packages/app/` library's files became screens as well. A resolver can now name `appDependencies`; its extractor runs on a file only when that file's package.json or an enclosing one declares one of them. When no manifest in the project declares any, detection found the framework by other evidence and it runs everywhere, as before. Expo Router names `expo-router`, Next.js `next`. Co-authored-by: Claude Opus 5.5 <[email protected]>
…uxt routes only in Nuxt (#2130) vue-element-admin, vue-admin-template and vben had no routes: their tables are named arrays (`export const constantRoutes = [...]`, `const routes: RouteRecordRaw[] = [...]`) or per-module objects (`const tableRouter = {…}`) handed to `new Router(...)`, and most of their screens are `children`. The Vue Router reader now reads those tables in any file that builds a router, imports vue-router or lives in a router/ directory; joins children onto their parent's path (a parent is a screen only when no child claims its address and it doesn't redirect); binds a lazy view by the FILE it imports (all of vue-element-admin's are `…/index.vue`), through an alias the resolver can't follow by the one file in the app with that path; links each screen to its parents' components as layouts; and takes `this.$router.push`. Nuxt's file routes move into their own `nuxt` resolver, detected only in a Nuxt app: halo's plain-Vue console got 30 made-up screens from its `pages/` folders. A Nuxt app at the repository root now gets its routes, and a top-level `pages/index.vue` is `/`, not `/index`. Co-authored-by: Claude Opus 5.5 <[email protected]>
…rs (#2131) A `(group)` directory shares a layout and is never part of the URL, and a parameter's `=matcher` checks its value. Kept in the name, shadcn-svelte's `src/routes/(app)/(layout)/blocks/+page.svelte` was `/(app)/(layout)/blocks`, so no `goto('/blocks')` or `<a href="/blocks">` ever reached it and its Screens showed no navigation at all. Co-authored-by: Claude Opus 5.5 <[email protected]>
#2132) react-boilerplate's header links are `export default styled(Link)`…``, used as `<HeaderLink to="/features">`; takenote's guards render v5's `<Redirect to="/" />`. Neither tag was read, so both apps had routes and no links between their screens. The link synthesizer now reads `<Redirect to>` (navMethod `redirect`) and any styled-components / emotion wrapper of `Link` / `NavLink` — declared in the file, or imported from a file that declares or default-exports one. Co-authored-by: Claude Opus 5.5 <[email protected]>
…elative navigate (#2133) From the router sweep: - angular-spotify had 12 routes all named `/` and no navigation. Its lazy routes are `async () => (await import('@ws/home')).HomeModule` through an Nx library's `src/index.ts` barrel, which the mount pass never looked through; and every lib is its own `src/`, so each routes file got its own route table and no template's `routerLink` found the screen it names. - jira-clone had 3 routes and no navigation: its issue route is `issue/:${ProjectConst.IssueId}` (a class `static readonly`), its root redirect lives in `app.routes.ts`, which only mounts, and `navigate(['project', 'issue', id])` has no leading `/`. Now: lazy mounts follow `export … from` barrels (and an NgModule's routing imports); `(await import(x)).M` is read; route constants may be class statics (strings or objects), enum members, or live behind a barrel, and a template-literal path takes constant holes; a routes file that only mounts contributes its redirects at its mount prefix; the route table is keyed by the `angular.json` / `nx.json` workspace; and `router.navigate` / `createUrlTree` without `relativeTo` resolve a bare first command from the root, as Angular does (template `routerLink` stays relative). Co-authored-by: Claude Opus 5.5 <[email protected]>
…ly imports (#2134) - Expo Modules: a JS call on a `requireNativeModule('N')` binding — typed (`<CameraNativeModule>`) or not, local or imported (expo-camera's `import CameraManager from './ExpoCameraManager'`) — resolves to module N's declared function, Swift first and Kotlin beside it, else to the member on the binding's declared type. It went to the same-named static method making the call. - A JS/TS member call on an import binding never picks a method declared in the calling file, and ruling those out never manufactures a unique guess. - `import type { X }` was parsed as a default import named `type` (every type-only import bound `type`), and `{ a, type B }` bound `type B`. - A name the file binds from an out-of-repo package names nothing in the project, for every reference kind, and JS/TS fuzzy matching is exact-case: trpc's 402 `Record<…>` references went to a `record` property, element-plus's 121 `mount` imports from @vue/test-utils to a test helper. Co-authored-by: Claude Opus 5.5 <[email protected]>
…st decides (#2135) - `app/blog/og-image/[post]+api.ts` was a screen named `/blog/og-image/[post]+api` (evanbacon.dev). An Expo API route is now one endpoint per exported HTTP method (`GET /blog/og-image/:post`), bound to its handler, the way Next.js `route.ts` files are. - The per-app framework gate (#2129) took ANY enclosing manifest's declaration: react-native-true-sheet's root declares expo-router for its example app, so its `docs/` Next.js app got 16 Expo screens (`/layout`, `/page`, `/api/search/route`, …). Walking up from a file, the first manifest that names any gated framework now decides. Co-authored-by: Claude Opus 5.5 <[email protected]>
Extraction keeps `super.didMoveToWindow()` under the bare method name, so every strategy resolved it to the enclosing override itself. Across the bridge sweep that was 139 self-edges on Charts, 142 on commons-lang, 101 on BookStack, 92 on realm-swift, 82 on react-native-svg — lifecycle overrides and delegates drawn as recursion. `gateSuperSelfCall` declines a `calls` result that targets the calling node when the call site is written through `super` / `base` (C#) / `[super …]` (Objective-C) / `parent::` (PHP) / `super().` / `super(C, self).` (Python). Plain recursion keeps its edge. Co-authored-by: Claude Opus 5.5 <[email protected]>
…SX via default imports (#2137) - `requireNativeComponent('X')` (Paper) now emits the same JS `component` node a Codegen spec does, so the Fabric pass links it to the native view / manager classes; the extractor also runs on `.js` / `.jsx` spec modules (segmented-control's spec is Flow `.js`). react-native-maps' `AIRMap` gains its iOS implementation. - A JSX tag that names no node is the file's DEFAULT import of a module's one component: `<RNCSegmentedControlNativeComponent>`, and element-plus's test `<Autocomplete>` for `autocomplete.vue` (whose component node is `autocomplete`). A named import never takes a barrel's one component. Co-authored-by: Claude Opus 5.5 <[email protected]>
…hannel (#2138) The rn-event-channel pairs a native emit with a JS listener on the event's LITERAL name. Most libraries name events through constants — NetInfo listens with `addListener(PrivateTypes.DEVICE_CONNECTIVITY_EVENT, …)`, many emit with `.emit(EVENT_NAME, …)` or `sendEventWithName:kEvent` — so their channels were empty. Identifier / member-chain event names are now read to the literal their declaration holds (JS/TS const & enum, Java `static final`, Kotlin `const val`, ObjC `NSString *const` / `#define`, Swift `let` / enum case), scoped as the language scopes them: a bare name in the same file or behind an import, `Owner.NAME` inside Owner or a namespace import's file. The handler of a constant-named listener is a function in the same file, else the enclosing one. A first cut that read constants by name alone turned a `.emit(eventName, …)` parameter into some test's `eventName = "pong"`. Co-authored-by: Claude Opus 5.5 <[email protected]>
…e languages (#2139) The last-resort fuzzy match looks names up in a lowercase index — right for PHP, Pascal/Delphi, CFML, COBOL and VB.NET, whose identifiers ignore case, and wrong for every other language. jsoup's 1,844 `@Test` annotations decorated a `CharPredicate.test` method; commons-lang's `new BitSet()` instantiated a `bitSet` field accessor 64 times; mall's `new Info()` an `info()` endpoint; gson's `Method` type a test's `method()`; fmt's `#include <optional>` gtest's `Optional`. This generalizes the per-language exact-case rules (Rust, Python, JS) into one: outside CASE_INSENSITIVE_LANGUAGES a fuzzy candidate must match the reference's exact name. The cross-language fuzzy-gate test now builds its winner from an exact-case name. Co-authored-by: Claude Opus 5.5 <[email protected]>
…ls (#2140) A `<script>` block goes through the TS/JS extractor, which extracts no symbol for a method in an object literal — so every Vue 2 component, and every Vue 3 one not on `<script setup>`, had no `handleLogin`, no `mounted`: their calls, their `this.$router.push`, and the template's `@click="handleLogin"` all belonged to the file. `vue-options-api.ts` reads the options object the default export is (directly, or via defineComponent / Vue.extend / Vue.component) and names each function in it — `methods`, `computed` (incl. get/set objects), `watch` (incl. `{ handler }`), `data`, `setup`, lifecycle hooks, Nuxt 2's asyncData/fetch — as `method` nodes owned by the component; the Vue extractor re-attributes the references and edges written inside each. A component's own method is only reached as `this.m()` in that component: the member-call and exact-name strategies no longer hand it `e.preventDefault()` (ImageCropper's `preventDefault` method took every event's call), `this.editor.setValue()`, or `this.$refs['input'].click()`. Co-authored-by: Claude Opus 5.5 <[email protected]>
…n()` is a bare call (#2141) - The name prefilter checks a case-SENSITIVE set of known names, so in PHP, Pascal, CFML, COBOL and VB.NET — whose identifiers ignore case — a call written in another case (`formatprice()` for `FormatPrice`, TestBox's `ToMatchWithCase()`) was dropped before any strategy ran. Those languages now also check a lowercase set (built lazily, only when asked). - `isBarePhpCall` took any `>` before a name for `->`: every call after `=>` in a PHP array (`'total' => count($items)`, `'by' => user()->id`, `'label' => trans('…')`) was a member call, and found a same-named method — 166 wrong edges on BookStack (`trans` → LocaleDefinition::trans, `new Response` → ImageStorageDisk::response, `url()`, `config()`, `count()`). It now requires `->` / `?->` / `::`. - A fuzzy `instantiates` never names a method. Co-authored-by: Claude Opus 5.5 <[email protected]>
…archy (#2142) Extraction records `$this->m()` under the bare name, so exact and fuzzy matching took ANY same-named method: Drupal core's tests' `$this->assertEquals()` (PHPUnit's) went to a comparator class 8,832 times, `$this->assertSession()` to WebDriverTestBase 9,556 times, `$this->t()` to `Views::t` 6,811 times; Laravel's `$this->assertCount()` to FilesystemAdapter 1,722 times. A call written through `$this->` / `self::` / `static::` (or `parent::`) now takes only a METHOD of the enclosing class's ancestry — `extends` and trait `use`, read from source and resolved through the file's `namespace` / `use` imports (aliases included) to fully qualified classes — or a subclass's (a base calling what a subclass defines). Past an ancestor outside the repository (Orchestra's TestCase) a repository trait's method still counts, an unrelated class's never does. Inside a trait, `$this` is the using class, so trait bodies are not scoped. Multi-line `use A,\n B;` trait lists parse. Co-authored-by: Claude Opus 5.5 <[email protected]>
A Lua `local` (variable or function) belongs to the file that declares it, but cross-file name matching treated it like a global. kong's spec helpers re-bind busted's globals (`local it = it`, `local assert = require "luassert"`), and every other spec file's `it(…)` / `assert(…)` / `describe(…)` linked to them — 15,776 edges; koreader's `local ipairs = ipairs` in one module took the project's `ipairs` / `pairs` / `type` / `tonumber` (2,329). isVisibleAcrossFiles now reads a Lua/Luau variable or function's declaration line and rejects a `local` one from another file (the reference stays unresolved rather than taking a runner-up). Globals stay visible. Co-authored-by: Claude Opus 5.5 <[email protected]>
testthat runs each test file in an environment of its own, so a variable a test assigns is invisible to the package and to other tests. ggplot2's `c <- ggplot(…)` in test-facet-grid-.R was the one node named `c`, and took 2,455 of the package's `c(…)` calls (the sweep's top-depended symbol). isVisibleAcrossFiles rejects an R variable/constant under `tests/` from another file — except `helper-*.R` / `setup-*.R`, which testthat sources for every test. (A first cut that limited every R call to function nodes lost ggplot2's factory-defined `geom_point <- make_constructor(…)`, dplyr's `summarize <- summarise` and shiny's aliases.) Co-authored-by: Claude Opus 5.5 <[email protected]>
A receiver-less Dart call now reaches only a method of the enclosing class, something it extends / mixes in / implements, or an extension on one of those types, and the nearest one wins. The hierarchy is read from each declaration's head (comments and type arguments dropped), since supertype edges don't exist on the first pass. Body-less abstract members (extracted as owned functions) are scoped too. Mixin-application classes (`class A = B with C;`) were extracted as `<anonymous>` with no supertypes; both the wasm extractor and the Rust kernel now name them and emit their extends/implements refs (kernel parity verified on bloc, riverpod, shelf, dio, getx). A/B (edges removed / added): riverpod -1945/+517, shelf -785, getx -855/+18, bloc -178/+95, dio -78. Co-authored-by: Claude Opus 5.5 <[email protected]>
…2146) A Kotlin call's top-level candidate (a function, an extension function, a property) must be in the caller's package, imported by name, or in a star-imported package. Class members aren't judged: a lambda's receiver can put any type's members in scope. A function type with a qualified receiver (`(A.Builder.() -> Unit)?`) broke the tree-sitter-kotlin parse badly enough to drop the enclosing class; an offset-preserving preParse blanks the qualifier (hoisted, so the kernel parses the same bytes — parity 0 diffs on Exposed, okhttp, nowinandroid). A/B (edges removed / added): Exposed -5370/+4256 (1,318 R2DBC assertEquals misroutes; DatabaseTestsBase's members and 250 extends/imports edges back), koin -965/+960, okhttp -690/+675 (567 MockResponse to the imported mockwebserver3 class), okio -98/+44, nowinandroid -14. Co-authored-by: Claude Opus 5.5 <[email protected]>
Ruby types nothing, so two guesses produced most of a Ruby repo's wrong
call edges:
- `receiver.m()` through an untyped receiver took the project's one method
named `m`. It now also needs a word shared between the receiver and the
method's owner (`web_push_request.legacy_encrypt` → WebPushRequest);
`self` / `self.class` are exempt.
- a bare `m()` inside a class took any class's `m`. It now reaches only the
class's ancestry — superclasses and include/extend/prepend modules, read
from source and resolved against the lexical nesting. Calls in module
bodies and top-level blocks (specs, DSLs) are not judged.
A/B (edges removed / added): rubocop -4406/+262, mastodon -2642/+540,
jekyll -343/+10, lobsters -243/+4, sinatra -207/+2, devise -112/+3.
Deliberate losses: instance_eval'd DSL blocks inside a class method
(sinatra's own tests' `mock_app { get '/' }`), and helpers on a framework
class the repo reopens past an external superclass (devise setup_mailer).
Co-authored-by: Claude Opus 5.5 <[email protected]>
…2148) - A bare call in a .cfc reaches only the component's own methods and those of the components it extends (extends="a.b.C" read from source, matched to indexed .cfc files by longest path suffix). Calls in .cfm templates and multi-line chain links (name not on the ref's line) are not judged. - The untyped-receiver rule from the Ruby fix now covers CFML too: the one project method named `m` needs a receiver named after its owner. The word match also accepts the receiver's whole name (`cbsecurity` → CBSecurity) and ignores trailing digits (`executor1` → Executor); Ruby is byte-identical to main. A/B (edges removed / added): coldbox -2429/+295, TestBox -255/+31, fw1 -103/+4, cbsecurity -8/+5, cfdocs 0. Deliberate losses: framework-repo calls through conventionally named, untyped receivers (ColdBox's `event.*` → RequestContext, TestBox's `variables.assert.*` → Assertion). Co-authored-by: Claude Opus 5.5 <[email protected]>
VB.NET's extractor keeps a call's last name only, so `Me.Panel.Controls.Add(x)` and `New System.Drawing.Size(1, 2)` arrived as bare `Add` / `Size` and exact / fuzzy matching took any class's member (even an enum case). The receiver is now read from the line: a member candidate needs `Me` / `MyBase` / `MyClass`, its own type or module as the last receiver segment, or a `(Of T)` type argument (`GetService(Of Notifier).Notify()`). Genuinely bare names are unchanged. A/B (edges removed / added): SCrawler -3452/+6, remoteapptool -143/+0, CompactGUI -31/+5, ViVeTool-GUI -1, TaskbarX 0. Co-authored-by: Claude Opus 5.5 <[email protected]>
…g on Node 22 (#2424) go-ethereum's `codegraph init` sat in "Resolving refs" for good on Node 22 (killed after 1 h 55 min and 9,203 CPU-seconds). It was not Go: two resolver pool workers each sat on one 500-ref chunk of graphql/internal/graphiql/graphiql.min.js, a 980 KB bundle on one line (18,388 refs, 2,234 functions). Whether a JS function binds a name itself (jsFunctionLocalScope, #2226) is read off its comment-stripped code with a parameter-list regex that starts with a `(?<!\b(?:if|while|for|switch|with)\s*)` lookbehind. Node 22's V8 compiles new regexes without optimization once a process has generated about a megabyte of regex code and holds 16 MB of executable memory, which a pool worker reaches after some 30,000 refs. Unoptimized, the lookbehind runs at every position and its `\s*` reads back through the whole run of blanks before it, so a run of n blanks costs n^2/2 steps. The comment stripper, which doesn't know regex literals, reads the `//` that closes `/Trident\//` as a comment and blanks the remaining 961,968 characters of the line. In a worker's state the regex took 36 ms over 16 K characters of that line, 5.1 s over 32 K and 54 s over 64 K, against 0.23 ms over 128 K in a fresh process. Compiling 20,000 throwaway regexes first reproduces it in a bare Node 22 process, and --no-regexp-optimization reproduces it anywhere. Node 24's V8, the runtime release bundles ship, kept optimizing after 60,000, so released installs finish: 1.6.2 indexes go-ethereum on its bundled Node 24 and stalls the same way on Node 22. The stall is as old as #2226. - A leading `(?=\()` keeps the lookbehind to where a parameter list opens. Every match starts with `(` anyway, so the regex matches exactly what it did. - The jsx-render pass split the file, sliced a function's lines and scanned them for tags once per function: 2,234 times over the bundle's line, 25 of the 28 s its linking passes took on Node 22 (9 of 13 on Node 24), for no edges. Functions that span the same lines now share one scan, and the file is split once. Graph: go-ethereum dumps (nodes, edges, unresolved refs, files) are byte-identical between main on Node 24 (main never finishes on Node 22) and this change on Node 22 and on Node 24. Main and this change also match byte for byte on bootstrap4, legend-state, takenote, mantis, excalidraw (482 jsx-render edges), qwik, gin, prometheus, etcd and hugo. Time, go-ethereum: on Node 22 main never finishes and this change takes 36 s; on Node 24 (three interleaved rounds, medians) 42.1 s -> 38.3 s wall, with resolution 17.7 s -> 12.7 s and the linking passes 6.5 s -> 1.5 s. Tests: js-local-binding-backtracking forces V8's unoptimized mode and indexes a function with a 60,000-character comment before a call (69 s on main, 1.4 s now); jsx-render-work counts the tag scans of 60 components on one line (60 on main, 1 now). Co-Authored-By: Claude Opus 5.5 <[email protected]>
… by embedding (#2414) Since goImplementsEdges counts promoted methods, a struct can satisfy an interface with methods its embedded types declare. The interface-dispatch bridge linked each interface method only to a method the struct declares itself, so a call through such a method reached nothing when the embedded type does not implement the interface on its own: prometheus's scraper.Report never reached Target.Report through targetScraper. For a Go struct's synthesized implements edge, each interface method the struct does not declare now links to the method Go's selector picks: the shallowest embedded type that has it, nothing when two occurrences tie at that depth (one type reached along two paths included), and nothing when an embedded interface provides it, which is a dynamic call again. These links come after the per-implementer loop, from what the struct's cap has left, so every existing edge is unchanged. They keep interface-impl metadata plus promotedInto, and registeredAt names the struct's embedding; codegraph_explore labels the hop as a promoted method. The embedding test is shared with goImplementsEdges. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ppears later (#2422) A router names the page or layout it loads lazily by the module's path: React Router's `lazy-import:./pages/Team`, Vue Router's and Angular's `import:./home/home.component#HomeComponent`, each also behind `layout:`. Sync retries a parked failed ref by name_tail (#1240), and these were parked under a fragment of the path ('/pages/Team', 'component#HomeComponent') that no file's keys match. So a route whose module was added after the router was indexed, or whose module gained its component in a later edit, stayed unlinked until the router file changed or the project was indexed again. #2392 fixed the same gap for imports, #2403 for Liquid's path references. - referenceNameTail parks a module reference under the stem of its path behind 'module:' ('module:Team'), a key no symbol's name can be, so name lookups never retry it by a namesake. - Sync adds the changed files' moduleReferenceKeys (importPathKeys behind 'module:') to the symbol retry: an added file can be the module, and an edit can give the module the component the route renders. - Schema v14 rewrites the tails parked before. Its select keeps SQLite off idx_unresolved_status with `+status`, reading idx_unresolved_name ranges instead of every failed row (vscode's index: about 1 s down to ~12 ms). - The retry resolves in row order, as a full index does, so when a route's module reference and its layout reference make the same edge, sync keeps the one a fresh index keeps (ghostfolio's markets page). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…2412) bulletproof-react's router imports its app shell as `import { default as AppRoot, ErrorBoundary as AppRootErrorBoundary } from './routes/app/root'`. The import mapping recorded AppRoot as a named import of an export called `default`, which no module declares, so resolveViaImport found nothing for it and every reference fell through to name matching. The route /app bound to AppRoot by exact-match, and in a project where another file declares an AppRoot (or a default export is imported under a name another file uses) the call, route or JSX attribute bound to that file's symbol instead. The mapping now records `{ default as X }` as the default import, the same as `import X from`, so every reader of isDefault agrees with it: the import resolver finds the module's default export, the binding's own `imports` reference links the module file as a default import's does, and the JSX-child, Expo native-module, HTTP-client and styled Link lookups read it as the default import. Re-exports (`export { default as X } from`) were already chased as the default. `require('./x').default` is unchanged: `.default` there is a property of module.exports, which a CommonJS module can set by name. alan2207/bulletproof-react: 4 edges re-resolved at the same sites (the route /app reaches AppRoot by import; three binding imports link their module file). bitwarden/clients: 2 failed Storybook imports now link their module. bradtraversy/proshop_mern, leerob/next-saas-starter and t3-oss/create-t3-turbo: byte-identical. Dead-code reports unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…own languages (#2415) Strategy 1 of resolveOneInner ran every detected framework's resolve() on every reference, whatever its language: `languages` gated only extraction, and gateFrameworkLanguage lets every `calls` result through. Express, detected in etcd by its file-content scan, linked Go `*zap.Logger` result types to a method named `Logger`, and in harbor and bitwarden it linked Python and Rust `validate()` / `authenticate()` calls to an unrelated method or to the calling function itself. getResolvingFrameworks() narrows the loop to the frameworks whose `resolveLanguages` (else `languages`) list the reference's language; one declaring neither stays universal. `resolveLanguages` lets a resolver read a language it extracts nothing from without running extract() there: Svelte reads TS/JS ($lib imports, runes in .svelte.ts), ASP.NET reads Razor (a page's `@model` is the PageModel beside it). claimsReference() stays universal: protobuf's leading-`::` C++ calls get past the name pre-filter only on the Swift/ObjC bridge's claim. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…the parser misreads (#2426) tree-sitter recovers from a construct it can't parse by inserting the token it expected, and inside a class body that is often a `}`: an unknown macro in front of a member (`PROTOBUF_FUTURE_ADD_EARLY_NODISCARD absl::string_view name() const`) or in a class head (`struct ALIGN_AS(64U) HandleImpl`) closed the class there, and every `}` after it closed the scope one level out. Recovery also ran the other way, keeping a scope open past its own `}` once an ERROR swallowed it. The walker scoped declarations by tree nesting, so qualified names lost their namespace and class segments, or gained ones they don't belong to: protobuf's `FieldDescriptor`, `MapFieldBase` and `MutableRepeatedFieldProxyImpl`, fmt's `detail::` buffers (and `fmt::format_int` put in `detail`), rocksdb's clock_cache classes and the `Opts` structs nested in them, gtest's `PrettyUnitTestResultPrinter`. Every such file parses with errors, and the kernel defers those to wasm, so the wasm walker produced all of them; the kernel's walker has the same tree-nested stack and reaches erroring trees only under the CODEGRAPH_KERNEL_CCPP_ERROR_EXTRACT sweep hatch. For a C++ file whose tree has errors, the walker now takes each declaration's namespaces, and at declaration level its enclosing classes, from the source's braces (languages/cpp-brace-scopes.ts: comments, literals, raw strings, digit separators and preprocessor lines skipped, each #if branch read from the braces open at the #if). A class-like node ends at its body's `}`, and a class the tree glued into a namespace-level declaration's type is walked as a class. A file whose braces don't balance, and every file that parses cleanly, keeps the tree's scopes. Ported to the kernel (ccpp/brace_scopes.rs) so the hatch stays parity-true: the same erroring files diverge before and after (UTF-8/UTF-16 recovery), every other one is byte-identical. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…er a method of its name (#2416) A Go type position -- a parameter or result type, a composite literal's type -- names a type of the package Go reads it from. Name matching (and the instance-method guess, and the Express resolver reading Go refs) took whatever declaration shared the name: etcd's `func (ti *treeIndex) KeyIndex(keyi *keyIndex) *keyIndex` linked both types to the method `treeIndex.keyIndex`, prometheus's `samples{...}` literals to `sampleRing.samples`, and `config.URL{...}` from an outside package to `scrape.Target.URL`. gateTargetKind now hands every Go type position to goTypePositionTarget: a method or function target moves to the type of that name in the reference's own package (bare) or the imported project package (`pkg.T`), or is dropped when there is none; a bare name that found another package's type moves to its own package's type when it declares one (prometheus's `prompb` builds its own `Histogram_CountInt`). A generic method's receiver (`func (p *Pool[T]) Get() T`) now declares type parameters for gateTypeParameter. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ater (#2425) A router's navigation call (`history.push('/login')`, `navigate('/login')`, `router.push('/x')`, `goto('/x')`) names its route by path and its reference by the router's method, so sync never noticed a route that changed in another file. A synced index then kept answers a fresh index of the same files does not have (CG-33): - A call parked as failed while its route was missing never matched the #1240 retry, which keys on the names the synced files define. - A call bound to a catch-all, a parameter route or the other arm of a conditional kept that binding. - A route renamed in place by runPostExtract kept the calls bound to it. - Template links from a routes file that matches no synthesis trigger were never redrawn. When a navigation router is detected, sync now reads the route nodes at its first file change and again after runPostExtract. For each route on one side only, it puts back the calls the routers' new `navigation` hook (method tails and app scope) says that route can answer: the failed ones, and the `navigates` edges a resolver made. The orchestrator's orphan sweep resolves them, under the same 500-per-name ceiling, and the sync refreshes synthesis. This covers re-extracted and removed files, postExtract renames and cross-file table routes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…#2419) goImplementsEdges (#584) offered only structs as implementers. A Go defined type over a slice, map, function or basic type declares methods the same way (gin's `formSource map[string][]string` has TrySet, prometheus's `staticDiscoverer []*targetgroup.Group` has Run, an adapter `HandlerFunc func(...)` has ServeHTTP) and is extracted as a `type_alias` that owns them through go-method-contains edges. So it never satisfied an interface, and interfaceOverrideEdges, which walks only class, struct and union, could not link a call through the interface to its methods. Structs and defined types are now candidates together, in one canonical (file, line) order. A defined type declares every method it has, so under the per-interface cap it ranks with the structs that declare theirs, ahead of promoted-only ones. interfaceOverrideEdges also walks Go `type_alias` nodes. Every Go type's embeddings come from the batched prefetch (the per-type lazy lookup for defined types is gone), and a type without a method is dropped before the per-interface loop. A true alias (`type A = B`) is not extracted, so it never implements anything itself. iterateNodesByKindIn takes several kinds, interleaved in its one order. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…owercase name calls that type's own member (#2413) A C++ call on a variable, parameter or member the calling function or its class declares as a namespace-qualified type the project does not declare, with a lowercase name (std::string, std::vector, absl::flat_hash_set, ...), no longer falls through to Strategy 3's guess by the method's name. leveldb's `std::string saved_key_; saved_key_.clear()` reached Slice::clear, protobuf's `std::string proto; proto.append(...)` LeftoverBuffer::append. The gate applies to `.` on a value and `->` through a raw pointer; `->` on a smart pointer, iterator or optional still reaches the element type. It skips declarations it cannot trust: read from outside the caller's function and class (including a class nested in the caller's), contradicted by the call (`.` on a pointer), shadowed by an unreadable re-declaration (`auto`, range-for, structured binding), unqualified, with unbalanced `<>` (the tail of a multi-line declaration), or a `_t` name (scalars, tags, traits like std::conditional_t). A `std::` name counts as the project's only when the project declares it in `std` (vendored googletest's testing::internal::string). Receiver inference now blanks comments before matching declarations, so `// ... non-null imm_` no longer types leveldb's imm_ as `null`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…t names (#2417) tree-sitter-go parses `type Event = mvccpb.Event` as a `type_alias`, beside the `type_spec` of a defined type, and both extractors read `type_spec` only. etcd's client/v3 `Event` had no node; a use through its package (`clientv3.Event`, prometheus's `storage.AOptions{…}`) linked to nothing, and a use inside it linked by name to any type so named, another package's included. - Extraction (TS and kernel): an alias is a `type_alias` node referencing each type its right-hand side names, at the name so resolution reads the package back; an alias of a struct or interface literal is a struct or interface. The alias's own type parameters and Go's predeclared types are skipped. A generic alias, which tree-sitter-go 0.23 parses as a `type_spec` around an error, reads as an alias on wasm; the kernel defers its file. - A method called on an alias-typed value is the aliased type's: an alias of a project type is followed in its own package, through pointers and further aliases; one of an outside type resolves by name as before. - An alias's target written through a package that is none of the file's imports as indexed stays unresolved, as an embedded type's does, so the alias never links to itself or a namesake. - With Go defined types as implementers (#2419), an alias that owns methods written with it as the receiver implements what they satisfy, in place of the type it names. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ers no JSX child (#2442) The jsx-render pass reads tag names off a parent's source with a pattern, and two kinds of name it read that way linked a same-named class or component elsewhere: - A name written only in a type argument or type parameter list: outline's `<PaginatedList<Document> …>` and `useState<User>()`, or bulletproof-react's generic `<Entry extends BaseEntity>(…) =>`. A `<Name` right after an identifier opens a type argument list (the rule #2420 applies to the values a file declares, here for every name), and a `<Name extends …` opens a type parameter list. - A name the parent binds itself by its first tag, a `const`/`let`/`var` or a parameter (name-matcher's `jsCodeBindsName`, now exported): outline's `const Content = variant === "dropdown" ? DropdownMenu.SubContent : ContextMenu.SubContent`, `(Widget, index) => <Widget />`. Such a tag renders only a component the parent declares inside itself, else nothing. The check runs only for names the parent also writes outside a tag. Destructured names still link by name, as for a destructured call. Fresh before/after indexes on 13 repos (main ed199e6): 66 jsx-render edges removed and none added; no other edge, node, ref or file changes. Every removal checks out against the TypeScript compiler (38 names with no JSX tag in the parent, 28 tags bound to a local); 64 of the 66 targets were wrong, 2 right by luck. mantis, proshop_mern, next-saas-starter and create-t3-turbo are byte-identical, and Screens is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…edder's method of that name (#2430) Go has no inheritance. A struct that embeds another (`type Engine struct { RouterGroup }`) has an `extends` edge to it since #2397, and the interface-dispatch bridge read every `extends` edge as an override, so it linked RouterGroup.Use to Engine.Use. A call on a *RouterGroup only ever runs RouterGroup's own Use, so a flow or impact walk through it went on into Engine.Use and the code only the engine runs. The bridge now skips a Go type's supertype edge unless it points at an interface: only a call through an interface dispatches. Structs that embed an interface keep their links, and so do the go-implements edges, so a call through IRoutes still reaches both RouterGroup.Use and Engine.Use. Other languages are unchanged. Removed on gin / prometheus / etcd: 1 / 112 / 60 interface-impl edges, all from a struct's method to a struct embedding it; nothing else in the graph changed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…can't read (#2449) tree-sitter-cpp has no preprocessor, so an attribute macro where it expects a name or a type misparses the declaration around it. The C++ preParse already blanked one export macro before a class name, an inline macro before a return type, and a lone macro line before a declaration. It missed: - several macros, or one with arguments, between `class` and the name (protobuf's generated `class PROTOBUF_EXPORT PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Any final : public Message`, rocksdb's `struct ALIGN_AS(64U) HandleImpl`), and a macro before a partial specialization's name; - a macro between a pointer and the declared name (`const Descriptor* PROTOBUF_NONNULL descriptor()`), after a parameter list (`unknown_fields() const ABSL_ATTRIBUTE_LIFETIME_BOUND {`, leveldb's `LOCKS_EXCLUDED(mu_) {`), after a declared name (`int count_ GUARDED_BY(mu_);`), or opening a declaration (`PROTOBUF_FUTURE_ADD_EARLY_NODISCARD absl::string_view name() const`); - a lone macro line with a comment under it ({fmt}'s `FMT_BEGIN_EXPORT` above `// A generic formatting context ...`). Every generated protobuf message class misparsed, so its members were indexed as namespace-level functions; leveldb's annotated methods became phantoms named after the annotation. The new passes match on the code alone (comments and directives as spaces, literals as placeholders), blank only the macro tokens, and keep every offset. They run in the hoisted preParse, so files that now parse clean go through the native kernel, at parity. The passes share one mask per file: a pass that blanks nothing hands the next the same string, and one that blanks hands it the mask blanked the same way. #2426's brace-scope fixtures misparsed only through PROTOBUF_FUTURE_ADD_EARLY_NODISCARD and ALIGN_AS(64U), which the preParse now blanks. They now use macros it doesn't know (NODISCARD, cacheline_aligned(64U)), with the same expected scopes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…xport (#2433) `const X = require('./x').default` and `const { default: X } = require('./x')` map to a named import of `default`. That is right for a CommonJS module that sets the property itself (`exports.default = fn`, or the dual `module.exports = X; module.exports.default = X`), but a module written as an ES module and compiled to CommonJS sets it to its default export, which is no named export. References through the binding stayed unresolved (bitwarden's `new OsBiometricsServiceMac(...)`) or fell to name matching: the local variable holding the module, or a namesake method in another package. findExportedSymbolWalk now falls back to the module's ESM default export when the named lookup finds no `default`. Only for JS-family refs, only in the module the require names (`export * from` forwards no default), and only when that module has an ESM default export at all: a single-file component, or an `export default` statement. A CommonJS module's `exports.x = function` declarations are flagged exported, so without that gate the first-exported-function guess would invent a default for it. bitwarden +2 edges (the two failed `instantiates` refs). react-native +872 -617: all 617 re-resolved at the same site (541 from the local require binding to the real function or class, 47 from a namesake method in another package to the right module, 28 metadata only, 1 from a type signature to the implementation), 870 of 872 added edges on the declared default or what it holds. express, eslint, mocha, koa, body-parser, fastify, topcoder, proshop_mern, next-saas-starter and create-t3-turbo byte-identical. Dead-code claims unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…method (#2444) Both extractors record `srv.(KVServer).Range(ctx, in)` as a bare `Range` call at the column where its receiver expression starts, as they record any call through an expression. Resolution matched the name alone, so every handler protoc-gen-go-grpc emits went to the `UnimplementedKVServer` stub beside the `KVServer` interface (72 edges in etcd), and calls like `c.Reader.(*pipe).Close()`, `p.(Pausable).Pause()` or `v.(featuregate.MutableFeatureGate).Set(…)` linked to a namesake or to nothing. The call's chain is now read back from its column (operand, selectors, assertions, calls and indexes, past strings, runes and comments, and on to the next line after a trailing `.`). When the link of the call's name follows an assertion, the call is a method of the asserted type, found where Go finds it: - a bare `T` or `*T` in the call's own package, or one it dot-imports; - a `pkg.T` in the imported project package; - its own method, the one its interface declares, or one promoted from a type it embeds, through the package-scoped lookup #2361 added; an alias is followed to the type it names (#2417). A type from outside the project (`http.Flusher`), a predeclared one (`error`), an alias of an outside type (`type Ctx = context.Context`, for which the package-scoped lookup would fall back to matching by name) or a type literal (`interface{ Flush() }`) links nothing. The check runs ahead of the framework, import and name strategies, and ahead of the built-in filter, which dropped a method named `close` or `copy` called through an assertion. Two calls of one name in a chain share the column (`b.(*Builder).Add(1).Add(2)`); both are taken for the one made through the assertion, whose edge is there either way. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…a test (#2434) Google names C++ tests `foo_unittest.cc` (protobuf, Breakpad, glog, Chromium), not `foo_test.cc`. The test-file check wanted a separator right before `test`, so each one read as production code: search and explore ranked it alongside the code it tests, `codegraph affected` never listed it, and the resolver's test rules ran backwards for it. Production calls landed on a unittest's own declarations (`stack_frame_entries_.size()` on a unittest's `StackHelper`, a template's `AddressType()` on a unittest's typedef), and a unittest's calls into test suites outside what it includes (a Python `*_unittest.py` using a `tests/` fake) were treated as production calls. #2421 already links a C/C++ unittest to the test helpers it includes. `unittest` and `unittests` join the separator-delimited test suffixes (`foo_unittest.cc`, `foo-unittest.cpp`, `foo.unittest.js`), and a file named so is a test suite to the resolver, as `foo_test.cc` is. A bare `unittest.go` stays production code: promtool's runs rule tests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…al named like an import is that variable (#2448) goRefQualification read a dotted Go call's package qualifier from its line, as the line's only `X.Name` spelling. A second spelling of the name left it with none (`Digest:` beside `digest.Digest(dig)`, `"Log using Infof"`), and another selector before it was taken instead (`klog` for `err.Error` in `klog.Error(err.Error())`). It now takes the reference name's first segment, the only one that can be a package. A call through a parameter or local that takes an import's name (etcd's `jwt, err := newTokenProviderJWT(…)`, testify suites' `suite` receivers) is a call on that variable. A per-file scope reader finds the parameters, receivers, results, `:=`, `var` and `const` names in scope at the call, so such a call is no longer one into the package. The variable's declared type, when its declaration writes one, decides what the call reaches: - An outside package's type, or a value an outside package's function hands out (`clock := clocktesting.NewFakePassiveClock(…)`), has none of the project's methods. - A project package's type is resolved as the receiver's type. This also covers parameters declared through a package (`logger logger.Interface`). - A field read through the local (`metadata.Type.String()`) keeps its own type. A sync drops a file's scope reading with the other per-file memos. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ckage imports look local (#2437) The out-of-repo import guard (`isOutOfRepoImport`) never fired in two setups: - A catch-all `paths` key. The guard started with `isExternalImport`, which treats an import as local when it starts with a root alias's prefix, and a `"*"` key's prefix is empty. On cord-field (`"*": ["./typings/*"]`), 169 imports of `Typography` from `@mui/material` bound to the project's own `Typography`. - An alias that lands on disk but outside the index. `fileExists` falls back to `fs.existsSync`, which also answers for a directory or a file under `node_modules`. home-assistant's `"lit/decorators": ["./node_modules/lit/decorators.js"]` bound 4,916 `@property()` decorators to an unrelated `property` field, and topcoder's `config` package landed on its `config/` folder. The guard now skips the alias-prefix test (it already asks `resolveImportPath` whether an alias maps the import to a file) and counts that resolution only when it lands on an indexed file. Other callers of `isExternalImport` are unchanged: resolving an import still needs the prefix test so `"*": ["src/*"]` aliases resolve at all. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…e first — graph byte-identical (#2431) bareCallReceiver joined the ref's line with the seven after it for every bare-recorded call, then cut the text at the ref's column. On a minified bundle that line is the whole file, so every call copied it: about 1 MB per call on go-ethereum's graphiql.min.js, 9 GB over that repo's call refs. It now searches the ref's own line from the column first. Every match of the call pattern starts with the name, so a match there with no earlier occurrence of the name on the line is where the joined lines match first too. With no match on the line (a call that continues on the next one), or with the name earlier on it (an earlier `name[…` or `name<…` can run past the line break and enclose the match), the joined lines decide as before. The result is the same for every input. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A Go defined type (`type WatchChan <-chan WatchResponse`, gin's `type HandlerFunc func(*Context)` and `type HandlersChain []HandlerFunc`) is a `type_alias` node, and it referenced nothing: only an `=` alias (#2417) named the types on its right-hand side. Impact on `WatchResponse` or gin's `Context` missed the declarations built from them, and everything that uses those. Fix (TS extractor and the Rust kernel, mirrored): goAliasTypeNames / alias_type_names walk the `type` field of every type_alias node, a defined type's as well as an alias's, so each type it names becomes a `references` ref on that name, where resolution reads the package qualifier back. Still skipped: the declaration's own type parameters, Go's predeclared types, and now its own name written bare, which in a recursive type (prometheus' `type stateFn func(*Lexer) stateFn`) is the declaration itself: no self-edge, and no failed row that would make dead code treat every namesake as referenced. A qualified name is never skipped (`type PutResponse pb.PutResponse` names pb's). Resolution is unchanged. A defined type is a new type: goAliasTarget still follows `=` aliases only, so a method called on a defined type is not looked up on its underlying type. The gateTargetKind rule that leaves a type_alias's reference written through a package the index doesn't know unresolved now covers defined types too; without it, every such name bound to the same-file declaration of its name (`type Op clientv3.Op` linked itself). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ds (#2436) A data router's `lazy: () => import('@/pages/invocation_page')` loads the folder's `index.ts`. When that file only forwards the page, with `export * from './invocation_page'`, `export { default } from './page'` or `export { Page as Component } from './page'`, the route linked nothing: the module was read for an export of its own and none was found. The lookup now follows the module's re-exports a few hops to the file that declares the page, the way JavaScript resolves them (`export *` never forwards the default, a name two `export *` modules both forward is exported by neither), and reads a module's own `export { Page as Component }` clause. `React.lazy` values in a route file, which go through the same lookup, follow such barrels too. On luci-go's milo/ui, 51 of 91 failed lazy route refs now link; the rest load a file under `src/build/` (not indexed), export only a `loader` or a `handle`, or pick a named export in an async loader. Sync links a page added or edited behind its barrel the way a fresh index does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…t counts (#2447) goImplementsEdges matched method names only, so a struct whose same-named method takes or returns a different number of values, which Go can never accept, was linked as an implementation (etcd's watch cache as a peerGetter), and enough such look-alikes filled the per-interface cap before the real implementer (grpc-go's xDS TransportBuilder). Each wanted method now also needs a declaration with its parameter and result counts, read off the stored signature text; a signature that doesn't read rules nothing out. A gRPC client interface (every method takes `opts ...grpc.CallOption` last) also accepts its RPCs' server arities, so `KVClient.Range -> kvServer.Range`, the bridge explore follows from a client call to its handler, stays. Defined types (#2419) are held to the same counts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…s own class's method (#2443) normalizeCppTypeName cut each `<…>` at its first `>`, so a declared type with template arguments nested in its template arguments kept debris: `autovector<std::pair<int, FileMetaData*>>` read as `autovector >` and `Striped<CacheAlignedWrapper<port::Mutex>>` as `Striped >`. No class has such a name, so the call was never resolved on the receiver's class. A capitalized debris name made isUndeclaredTypeName take the type for an outside one and silence the call (rocksdb's `mutex_.Get(key)`), and a lowercase one fell to a guess by the receiver's words (rocksdb's `files_marked_for_compaction_.clear()` reached `CompactionInputFiles::clear`). Template arguments are now stripped with their nesting by cpp-type-aliases' depth-tracking helper, exported as stripCppTemplateArguments; cpp-supertypes' identical private copy now imports it. A `>` that closes no `<` is the end of a declaration begun on an earlier line (`std::unique_ptr<BlobContents>>>& blob_reqs` under `autovector<std::pair<…,`): a depth strip alone would read the argument's type there, so such text names no type. The scan back to the receiver's declaration then marks it shadowed (#2413), as it does for a declaration whose type it can't read, so a member or earlier variable of the same name found further up doesn't decide the call. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tion the query names (#2453) Explore's named walk is breadth-first, and the first callee listed claimed each node it reached. An interface method calls every implementation at the same depth, so when several of them call the next named symbol, the Flow went through whichever implementation the index listed first, even when the query named another one. On prometheus, `Engine.execEvalStmt Queryable.Querier fanout.Querier NewMergeQuerier` went through the TSDB's `DB.Querier`; on gin, once defined types count as implementers, `setter.TrySet` went through `headerSource.TrySet` when the query named `formSource.TrySet`. A node reached again from the same depth now takes the route that ends on fewer unnamed hops, then the one through more named symbols, and keeps the first otherwise. Of two equally deep named ends, the seed keeps the one whose route passes more named symbols. The expansion order, the visited set and the NAMED_VISIT_CAP bound are unchanged, so the walk makes the same callee lookups. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aration is indexed (#2446) `struct Foo { … } foo;`, `class Bar { … } bar;` and `static struct { … } SPT;` outside any function or class body went to the variable extractor, which skipped the declaration's children, so the type, its methods and its enumerators were never indexed in either extraction engine. Both engines now walk such a type before the variables: in C always, and in C++ when the tree has no errors or the file is walked in brace scopes. This converges with #2426's walk for erroring C++ files; a C++ file whose braces don't balance is still left alone, since error recovery can run a class past its own `}` there. The declaration's function-as-value scan skips the walked type, which captured its own. An unnamed struct, union or enum takes the name of the first variable its declaration declares (also inside function bodies, where it was `<anonymous>`), as `typedef struct { … } Name;` already takes the typedef name, and the comment above the declaration is the type's docstring. cDeclaratorIdentifier moves to languages/c-cpp.ts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…of exactly that name (#2445) The resolver's name-existence pre-filter read no leading `::`: its `::` branch wanted the separator past the first character, and the single-`:` loop skips names holding `::`. So `::leveldb::RepairDB(…)`, `::ROCKSDB_NAMESPACE::RepairDB(…)` or protobuf's `::_pbi::…` calls were dropped before any strategy ran, unless a detected framework claimed them. protobuf's got through only because it ships three Swift files: the Swift ↔ Objective-C bridge claims any name with a `:` in it, which is why #2415 left claimsReference() universal. - The pre-filter checks a C or C++ name without its leading `::`. - claimsReference() is asked only of the frameworks that resolve the reference's language (frameworksFor), like resolve() since #2415. - matchByQualifiedName takes a global-qualified C/C++ name as exactly that qualified name. Its suffix match took a namesake nested in another namespace or class: with the pre-filter alone, 23 of the 24 edges it added on leveldb, fmt and rocksdb were wrong, mostly wrappers like fmt's mock `test::open` linked to the `::open(…)` they wrap, and protobuf's `::operator delete` went to `DynamicMessage::operator delete`. A declaration inside a namespace a macro opens (fmt's `struct pipe`) only looks global in the index, so it is skipped; step 5 still reads those. - `::std::…` and `::memset` count as `std::…` and `memset` for the built-in check, and step 5 returns early for a single-segment name. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…2429) `const Wrapper = styled.div<WrapperProps>` + a template literal came out as a `constant`, so the JSX-render synthesizer skipped it: `<Wrapper>` got no render edge, or bound to a same-named component in another file. tree-sitter's tagged-template call takes no type arguments, so when the type argument also reads as an expression the initializer parses as comparisons, `(styled.div < WrapperProps) > template`, not as a call. (A type argument that can't be an expression, `<{ open: boolean }>`, error-recovers into a call on the tag, which #841 already took.) reactComponentHoc now also takes that comparison chain: the leftmost operand is the `styled` tag against a `<`, the rightmost is the template against a `>` (`>>` when the type argument ends in its own `<...>`), and operators in between belong to the type argument (`<A & B>`). Mirrored in the kernel's TS/JS walker. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…n the module appears later (#2450) A default, namespace or aliased import binds a name its module never declares: `import tagsController from './tag/tag.controller'`, `import { Component as GroupsPageWrapper } from './groups_page'`. Every reference through that name (the import, a call, `new`, a base class, a JSX or template tag, an Express mount) was parked under the name, which no file a sync adds or changes carries. So a module added after its importers were indexed, restored after a delete, or given its export in a later edit never relinked them, while a fresh index did. Such a reference is now parked under its project module's key (`module:tag`), which sync already looks up for every file it adds or changes (#2422), and it is still found by its own name: a binding its module never resolves is linked by that name alone, as vben's `{ VbenFormSchema as FormSchema }` from a workspace package is. Schema v15 adds the partial index that by-name lookup needs; its leading `status` keeps the planner off idx_unresolved_status, which read 830K rows on vscode's index. Co-Authored-By: Claude Opus 5.5 <[email protected]>
tree-sitter-go puts the comment above `type Foo struct{}` before the
`type_declaration`, but the node is made from the spec inside it, so both
extractors found no docstring for an ungrouped struct, interface, defined
type or alias. A type inside a `type ( ... )` group kept its own comment,
which sits beside it in the parentheses.
Go's docstring is now read from the declaration when the declaration
holds one spec and nothing precedes that spec inside it. The leading
comment of a group with several members stays the group's.
Reading from the declaration exposed comments that trail the line above:
`const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto
package` would have become `type MetricType int32`'s doc. For every Go
declaration, a comment that begins after code on its line, and one that
begins on the line such a comment ends, is now left out, as go/parser
reads them. Seven function docstrings on etcd and prometheus lose one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )