Repository navigation
merge(upstream): reconcile #2157–#2172 in the native resolver - #345
Merged
Merged
Conversation
…nry#2157) Only `<builder>.METHOD(…, use: handler)` registrations were read. Now also: - trailing-closure routes, `app.get("hello", ":name") { req in … }`, and `app.webSocket("chat") { req, ws in … }` (method WS), `routes.on(.GET, "x") { … }` — statement-start only, so `if let v = req.parameters.get("x") {` and an HTTP client's `req.client.get("https://…") { … }` don't count; - `routes.on(.POST, "x", body: .collect(…), use: handler)`, with only unlabeled string arguments as path segments. Routes main → this branch: SwiftPackageIndex-Server 13→34, vapor 6→265 (its tests), swiftchat 0→1, SteamPress 27→27, penny-bot 0→0. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…g slash (colbymchenry#2158) - FastEndpoints: an endpoint class (`: Endpoint<…>`, `EndpointWithoutRequest`, `Ep.…`) declares `Get(…)` / `Post(…)` in `Configure()`; each becomes a route linked to the class's own HandleAsync / ExecuteAsync (the bare-member scope from colbymchenry#2151 keeps two `List` endpoints apart). A constant path (`CreateContributorRequest.Route`) is read in postExtract from wherever the class declares it; `$"/{nameof(Project)}s"` reads as `/Projects`. - `app.MapGet("api/todos", …)` is named `/api/todos`. A/B: ardalis/CleanArchitecture 0 → 24 routes (+24 edges); eShopOnWeb and eShop only re-key routes whose path gained a leading slash; realworld and jasontaylordev/CleanArchitecture byte-identical. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…chenry#2159) The README said every bridge hop carries `metadata.synthesizedBy`, but only the synthesized channels (rn-event-channel, fabric-native-impl) did; a resolver-made hop (Swift↔ObjC, RN legacy / TurboModules, Expo Modules JS) carried only `resolvedBy: 'framework'`, and `expo-module-extract` named nothing that exists. The framework loop now adds `metadata.framework` (the resolver's name: swift-objc-bridge, react-native-bridge, expo-modules-js, fabric-view, rails, laravel, …) and the README says what each kind carries. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…mchenry#2160) Read at the site: - a later link of a chain (the extractor keeps one receiver level; the line shows the dot) reaches a member whose owner the receiver chain is named after (call / type arguments dropped: `proc("x").call()` → proc, `checker.value.onWrite` → checker), or a same-file member; never a package object's function unless it is a Scala 3 `extension` method; - a name the enclosing def binds (parameter, val/var/def, lambda / for param) is only a def inside that function; - otherwise a member of the types around it, an anonymous subclass's bases (`new OptionParser[C]("x") { head(…) }`), their extends/with supertypes (source-read heads), same file, or an imported object (`import Foo._`, `import Foo.{bar}`); a value import (`import builder._`) leaves the file unjudged. A/B (edges removed / added): cats -1693/+678, sttp -887/+271, munit -265/+175, scopt -245/+78, os-lib -115/+43. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) tree-sitter-javascript can't parse Flow annotations; `render(): React.Node` ended a class early (segmented-control's component had no methods). A `.js` / `.jsx` whose leading comments carry `@flow` (not `@noflow`) now detects as `tsx`, and the TS extractor's offset-preserving preParse blanks Flow-only syntax for those files: exact object `{| |}`, a maybe type's `?`, an inexact object's bare `...`, `import typeof`, `opaque type`. preParse is hoisted before the kernel, so both paths parse the same bytes; kernel-parity now routes .js/.jsx through detectLanguage too (RN core Libraries: 0 diffs over 641 files). Grammar preload adds tsx whenever JavaScript is present. Parse errors over 400 RN-core Flow files: 10,626 (JS grammar) → 391 (TSX). A/B edges: RN core Libraries 29,649 → 38,194 (+12,639 / −4,094, the removals mostly `root.render(…)` → the one DrawerLayoutAndroid::render the old parse left, and edges re-keyed onto recovered methods); segmented-control +35/−5; express and react-native-netinfo byte-identical. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ss-file (colbymchenry#2162) The sealed-module rule only covered modules exporting nothing. Per symbol now: a JS/TS top-level binding declared by its own statement (function, const/let/var, class, interface, type, enum) in an ES module is reachable from another file only if it's exported — the `export` keyword (node flag or its line), an `export { a as b }` list, `export default x` or `export default { a, b }`. Classic scripts, CommonJS, `declare global`, `.d.ts`, qualified members, object-literal members (zustand store actions) and `proto.x = function x()` are exempt. Applied at the reachability gate, so the winner is rejected rather than another promoted. A/B (edges removed / added): zod -229 (package `z` imports → a local `z`), excalidraw -66 (DOM `Element` → a test helper's type), kit -50, typeorm -47 (`import { ColumnMetadata } from "typeorm"` → a fixture's local), trpc -26, hono -8, axios -1; express byte-identical. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…t returns (colbymchenry#2163) `const { getDefaultActivityRoute } = useDefaultActivity(); getDefaultActivityRoute()` bound the name locally, which ruled out every cross-file candidate, so the call resolved to nothing. A bare JS-family call through a name destructured (`{ key: alias }` included) from a call's result now resolves the callee — through the file's imports, else the same file, else the project's one function of that name (Nuxt's `~/` alias) — checks its source returns the key, and takes the function declared in its body, else the module-level one it returns. A later declaration at the call's scope shadows the binding. Returned object literals now count as exporting their names for colbymchenry#2162's unexported-binding rule. A/B edges added (removed): mealie +176 (-4), excalidraw +156 (`const { t } = useI18n()`), halo +58, kit +34 (-14, `validate` now the validator's own), elk +19; trpc byte-identical. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… aliases (colbymchenry#2165) - Route tables compose nested paths: a child's `path` is relative to the path-bearing routes around it (`children` of a data router, nested `<Route>` elements), absolute ones reset. `lazy: () => import('./x')` (object and JSX) renders the module's default export (`Component` export as fallback) via a claimed `lazy-import:` ref. `path: paths.app.root.path` keeps its parts on the node's signature and is named in postExtract from the constant's object literal (found through the file's import). The route keeps its extracted id; `isReactRouterRoute` accepts it. An element wrapped in parentheses or a guard (`<ProtectedRoute>`, `<Suspense>`, `*Provider`, `*Guard`) renders the first element inside. - Import aliases: the tsconfig / jsconfig nearest the importing file that declares `paths` is tried before the root's, so each monorepo app resolves its own `@/*` / `~/*`. A/B (edges removed / added): bulletproof-react -43/+367 (0 → 9 named, linked routes; cross-app imports fixed), react-native-reusables -103/+193, kit -184/+218, trpc -45/+71 (examples' `~/…` now their own), create-t3-turbo -1/+13; excalidraw, halo, obytes, realworld byte-identical. colbymchenry#1348's nested fixtures now expect composed paths (`/dashboard/settings`, `/data/prefs`). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…olbymchenry#2166) `Name.method()` where `Name` reads as a type in the language's conventions and nothing in the project (same language family) is called `Name` — JDK / BCL / DOM / Indy types — now leaves the method-call matcher before the capitalized-receiver and name-overlap guesses. Not applied in Go (exported package variables), C / C++ / Rust / CUDA / Metal; in Pascal only Delphi type prefixes (T/E/I…) and `Exception` count, since parameters and locals are capitalized there too. A/B (edges removed): commons-lang -1636 (`Integer.valueOf` → StringUtils ×804, `Calendar.getInstance`, `Instant.now`), horse -89 (`Exception.Create` → EHorseException), retrofit -79 (OkHttp `RequestBody.create` / `HttpUrl.get`), typeorm -74 (`Object.assign` → ObjectUtils), gson -100, zod -63, Newtonsoft.Json -57, jsoup -18; gin and cobra byte-identical. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…henry#2167) The extractors keep one receiver level, so chain links arrive as bare names. Read at the call site: - bare (no `.` / `::` before it): never a method — Rust reaches one only through `self.` / `Type::`, Go through a receiver (axum's routing `get(handler)` went to a cookie jar's `get`, tokio's `drop(x)` to `Drop` impls, colbymchenry#1861's pinned `reset()` → `Target::reset` is now the free fn); - chained (after `.`, receiver read back through arguments, macros `name!`, `::` paths and Go composite literals): never a free function, and a standard-library method name (Option/Result/iterator/collection/string methods; Go's String/Error/Header/locks/reflect/time) needs a receiver named after its owner — project-specific names keep their match (clap's `flag("n").short('n')` → Arg::short, cobra's `c.Root().Name()`, gin's `c.Set(…)`). The same std gate applies to the method-call matcher's unique-name guess. A/B (edges removed / added): clap -1496/+93, tokio -1064/+235, axum -695/+42, ripgrep -477/+32, cobra -167, serde -119/+1, bat -40/+4, gin -32/+26. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ames stay std (colbymchenry#2168) - tree-sitter-kotlin can't read `class Name` / (comments) / `internal constructor(…) : Super {` on separate lines — the class is dropped and its members become loose top-level functions (okio's ByteString, Kotlin Multiplatform's `expect` classes). The Kotlin preParse now blanks that constructor's modifiers / annotations / keyword to spaces, so `(…) : Super {` parses as the primary constructor; offsets and lines survive, and preParse runs before the kernel, so both paths parse the same bytes. - With members back on their classes, a Kotlin standard-library name on an untyped chain link (scope functions, collection / string / conversion methods — not names project types commonly carry) needs a receiver named after its owner, in the exact / fuzzy filters and the unique-name guess. A/B (edges removed / added): okio -1028/+1127, okhttp -979/+1145, kotlinx-datetime -426/+515 (mostly re-keyed onto recovered classes), koin -60/+4 (`msg.contains(…)` → a dependency map's `contains`). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…type (colbymchenry#2169) When a receiver's type is inferred from its declaration or initializer and the method isn't on it, the matcher used to fall through to its capitalized-name and name-overlap guesses. If the inferred name is a type (capitalized last segment) that nothing in the project declares — JDK / BCL / okhttp / Django types — it now stops: the method is that outside type's. Python's initializer pattern no longer reads a keyword argument (`prefix=IPNetwork(…),` inside a call) as a binding of `prefix`. A/B (edges removed): commons-lang -1296 (`append` / `length` / `charAt` on JDK types), Newtonsoft.Json -496 (`MemoryStream.ToArray`, `ToString`), gson -367 (`List.add`, `Map.put`), retrofit -321 (okhttp `Request.headers()` / `method()`), jsoup -130, okio -26, pytest -44 (pathlib / io), netbox -25, healthchecks -9 (`TimestampSigner.sign`), flask -9, zod -1. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…bymchenry#2170) Swift's extractor keeps one receiver level, so super.init(…), a longer chain's removeAll() and a bare min(a, b) all arrive as bare names and exact-matched whichever project member shared the name. A bare or self./ super. call now reaches only a member of the types around it and what they inherit or conform to (source-read heads, UIKit ancestry, the standard collection protocols), nearest first; a standard-named chain link needs a receiver that names the owner, an outside owner, or an argument label only the project's method takes; playground and test-target globals stay put. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… type (colbymchenry#2171) C# / Java / Kotlin receivers that are fields, properties or parameters were typed only when declared in the calling method without generics, so a call through a field fell to the receiver-word guess: Newtonsoft's _innerWriter.WriteValue() landed on the wrapper's own WriteValue, a TextWriter's Write() on a test writer's, commons-lang's DateFormat field's parse() on DateParser 284 times. - read class-level member declarations (brace depth 1, comments skipped), walking base classes with their type arguments substituted, C# using aliases, type-parameter bounds, generic and for-each declarations - C# interface members default public and namespace-level types internal (TS extractor + kernel, parity 0 diffs); interface calls resolve at all - the receiver-word guess weighs the owner type's name only, the receiver's last link (a constant's type), and its head noun; .NET std names need a receiver named after the owner; production code never lands in a test suite's mock Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…#2172) A receiver-less Kotlin call exact-matched any class's same-named method: koin's module { } in one test went to another test class's private module 268 times, error("…") to a Logger's error, get() inside a definition lambda to Koin's get rather than the Scope it runs on. A bare call now reaches a method of a class, anonymous object or extension receiver around it (read from nodes and from the source's braces, so a class the parser lost still counts) and what those inherit (with Android framework ancestry), of a type the project's function types take as a lambda receiver (plus outside types it writes extensions on), or of an object the file imports. with/apply/run blocks and .kts scripts are left unjudged; Kotlin's require/check/assert preconditions are the stdlib's. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…in the native resolver
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Merge upstream colbymchenry#2157 through colbymchenry#2172 at
2e2b98c9, before the Kotlin scanner patch in colbymchenry#2173. Calls through declared Java/C# members and destructured factory results now reach their declared targets, and call-site scope rules reject unrelated methods in Kotlin, Swift, Scala, Rust and Go. Flow JavaScript, FastEndpoints, Vapor closures and nested/lazy React Router routes receive the upstream extraction changes.The fork ports resolver changes into its native kernel and keeps the source-preserving Kotlin workarounds. Name-only survivors keep the fork's 0.7 ceiling. The merge commit preserves upstream ancestry for fast-forward integration on operator direction.
Validation:
README rows checked: upstream merge point, parser/name-resolution comparison, dispatch and endpoint/navigation coverage, supported language list, ASP.NET/Vapor/React Router framework rows, and measured results. The merge point and coverage text are updated with matching site pages. Historical measured rows retain their stated baseline; their previously deferred re-measure remains pending. Corpus numbers imported in upstream changelog entries describe upstream measurements, not fresh fork measurements.