GitNexus/gitnexus/vendor/tree-sitter-kotlin
glier d27fd11c4b
fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271)
* fix(lang-kotlin): support `fun interface` extraction via tree-sitter-kotlin re-vendor

Vendored tree-sitter-kotlin@0.3.8 (fwcd) parsed `fun interface Foo` as an
ERROR node and dropped the declaration plus its abstract method, so functional
(SAM) interfaces were never extracted. The fix landed upstream in
fwcd/tree-sitter-kotlin#169 (closes #87), merged to main 2025-04-25, but is not
in any npm release (latest tag 0.3.8; main is the unreleased 0.4.0).

Re-vendor the grammar from the unreleased fwcd main commit c8ac3d26:
- refresh src/{parser.c,scanner.c,node-types.json,tree_sitter/*.h} and
  bindings/node/index.js; bump the vendor version 0.3.8 -> 0.4.0; record the
  pinned SHA + rationale in _vendoredBy and the vendor README.
- switch the prebuild workflow's kotlin registry kind 'npm' -> 'vendored' (the
  fix is unreleased on npm, so prebuilds must build from the vendored C source,
  like swift/dart/proto).
- add a hold to .github/vendored-grammars.json so the weekly auto-update
  monitor does not strict-inequality-revert the pin to the broken npm 0.3.8
  (isNewer compares 0.3.8 != 0.4.0).
- add 3 regression tests + a fixture asserting fun interfaces extract as
  Interface nodes with their abstract methods, and that plain-interface
  heritage still resolves.

Existing KOTLIN_QUERIES need no change: the new grammar models `fun interface`
as a class_declaration with an "interface" keyword child (plus an extra "fun"
modifier child), which the existing interface rule already matches. Full Kotlin
suite green against the new grammar (300 unit/cfg/resolver + 233 integration).

NOTE: prebuilds/ are intentionally not in this commit. The version bump
auto-triggers .github/workflows/build-tree-sitter-prebuilds.yml, which
regenerates all 6 platform binaries from the vendored source in a separate PR.
Until that lands, CI loads the committed 0.3.8 prebuild, so the new kotlin
tests are red and the grammar change is inert at runtime. Merge the prebuild PR
first or together.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(ci): count kotlin's vendored hold as a 0.25-readiness blocker

The kotlin `hold` added in the previous commit makes the tree-sitter
upgrade-readiness report count it as a blocker — the report treats every
held vendored grammar as frozen below a runtime upgrade (same as the
intentionally-pinned tree-sitter-cpp and the ABI-held tree-sitter-c),
"in-range ABI or not". So the report's blocker count goes 2 -> 3.

Update the hardcoded count in
test_issue_update_summary_regex_matches_current_report (and the
_render_report docstring) accordingly — exactly as that test instructs:
"if a grammar is added/removed or a pin/hold changes, update the expected
counts". kotlin's ABI (14) is in range; the hold is what flags it, with the
reason recorded in .github/vendored-grammars.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(ci): refresh kotlin baselines for the grammar bump

Two committed baselines pinned the pre-bump kotlin state and broke when the
grammar was re-vendored (0.3.8 -> 0.4.0):

- cli-commands.test.ts pinned the vendored kotlin package version at 0.3.8 ->
  update to 0.4.0.
- bench/scope-capture/baselines.json: the new kotlin-fun-interface fixture joins
  the lang-resolution/kotlin-* corpus AND the new grammar parses `fun interface`
  as a class_declaration (not an ERROR node), so the capture fingerprint drifts.
  Rebaselined to the NEW grammar's fingerprint (verified by building the vendored
  parser.c against tree-sitter@0.21.1 and running measure.mjs --check); scaling
  ~0.83 (linear).

Like the fun-interface integration tests, the scope-capture --check passes only
once the regenerated prebuilds land; until then CI loads the committed 0.3.8
binary, so it stays red.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(prebuilds): rebuild + commit grammar prebuilds into the PR on vendored-source change

build-tree-sitter-prebuilds.yml previously rebuilt a grammar's native prebuilds
only when its package.json VERSION bumped, and delivered them via a separate bot
PR. Now any change to the vendored grammar source re-cuts the prebuilds and they
ride into the same PR.

- Trigger on any build-affecting change under gitnexus/vendor/tree-sitter-*/**
  (parser.c, grammar.js, binding.gyp, scanner, bindings), not just version bumps.
  The prebuilds/ subtree is negated in the paths filter AND excluded from the
  guard's source diff, so the bot's own prebuild commit can never retrigger the
  workflow (no build -> commit -> build loop).
- The guard builds a grammar when its recorded version changed OR its vendored
  source changed vs the PR base.
- Same-repo PRs get the rebuilt prebuilds committed straight onto their own head
  branch (included in the SAME PR) via a non-force push that only adds a commit
  on top of head. Manual dispatch still opens a fresh chore/ PR; fork PRs stay
  artifacts-only (a bot cannot push into a fork branch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(prebuilds): deliver rebuilt prebuilds to fork PRs via a trusted workflow_run stage

A fork PR's producer run has a read-only token and no secrets, so it can build and
validate the prebuilds but can't commit them. Add the safe two-stage handoff that
mirrors the pr-autofix producer/publish split.

- build-tree-sitter-prebuilds.yml (untrusted producer): on a fork PR, upload a
  pr-meta artifact (schema, pr_number, head_sha, head_ref, head_repo, base_repo)
  alongside the prebuild artifacts. Values flow through env + jq, never
  interpolated into a shell.
- commit-fork-prebuilds.yml (trusted, workflow_run): downloads ONLY the artifacts
  (never executes fork code — it checks out the pinned HEAD SHA solely to add
  files), allowlist-validates every metadata field, cross-checks identity against
  the workflow_run authority (head_sha / head_repo / pr_number, via
  commits/{sha}/pulls for forks), then pushes the prebuilds onto the fork head
  branch with --force-with-lease + http.extraheader auth. No PAT: this works when
  the contributor left "Allow edits by maintainers" on; on push failure it posts a
  sticky comment telling them to enable it or commit the downloaded artifacts.

zizmor: allowlist commit-fork-prebuilds.yml's workflow_run dangerous-trigger with
the documented mitigation, matching the existing ci-report / pr-autofix entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(vendor): rebuild tree-sitter-kotlin prebuilds for the re-vendored fun-interface grammar

The fun-interface re-vendor changed vendor/tree-sitter-kotlin source but left main's
old (0.3.8) prebuilds in place, so all 6 platform binaries were stale relative to the
new parser. Replace them with the freshly cross-built + ABI-validated binaries from
build-tree-sitter-prebuilds run 28010841458 — each .node was require()-loaded and
parsed a snippet on its target platform-arch before upload.

This is the manual equivalent of the commit-fork-prebuilds.yml delivery, which can't
run for this fork PR until it lands on main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(lang-kotlin): read extension-function receiverType from the re-vendored grammar's `receiver` field

The fun-interface re-vendor changed the kotlin AST: an extension function's
receiver is now a `receiver_type` exposed via a named `receiver` field, where the
old grammar emitted a bare user_type before the name. extractReceiverType only
matched the old shape, so receiverType came back null
(method-extraction.test.ts > Kotlin MethodExtractor > extracts receiverType).
Prefer the `receiver` field (unwrapping it), and keep the old child-scan — now
also recognizing `receiver_type` — as a fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-23 10:01:28 +01:00
..
bindings/node fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271) 2026-06-23 10:01:28 +01:00
prebuilds fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271) 2026-06-23 10:01:28 +01:00
src fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271) 2026-06-23 10:01:28 +01:00
binding.gyp feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
LICENSE feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
package.json fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271) 2026-06-23 10:01:28 +01:00
README.md fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271) 2026-06-23 10:01:28 +01:00

GitNexus vendor notice

This directory is a GitNexus-managed minimal runtime package derived from tree-sitter-kotlin (fwcd), pinned to the unreleased main commit c8ac3d26 (package.json version 0.4.0). It is pinned to main rather than a tagged release because the latest release, 0.3.8 (tagged 2024-08-03), predates fun interface (functional/SAM interface) support: it parsed fun interface Foo as an ERROR node and dropped the declaration. That fix landed in PR #169 (closing issue #87), merged into main 2025-04-25 but not yet in any npm release.

It carries bindings/node/, LICENSE, the native prebuilds/, and the full C source — src/parser.c, src/scanner.c, src/node-types.json, src/tree_sitter/, and binding.gyp. The source IS vendored (despite the ~33 MB generated parser.c) for two reasons: it lets build-tree-sitter-grammars.cjs source-build the binding on a toolchain host when no prebuild matches, and — because the pinned commit is unreleased on npm — it is the source the prebuild workflow itself compiles from (see below).

Why this is vendored (unlike the npm grammars)

Upstream tree-sitter-kotlin ships source only — its npm tarball has no prebuilds/ — so a plain npm install compiles the native binding from source and requires a C/C++ toolchain (python3/make/g++). To make Kotlin parsing toolchain-free on every host (Swift parity), GitNexus builds the platform prebuilds itself and vendors them here. node-gyp-build selects the correct binary at require time; build-tree-sitter-grammars.cjs activates the binding (prefer prebuild, else source-build) at install time.

tree-sitter-swift is handled the same way: its source is vendored and its prebuilds are GitNexus-cross-built from that vendored source. Kotlin now uses this exact path too (workflow registry kind: 'vendored', switched from 'npm' when this pin moved to an unreleased commit), so all of Dart/Proto/Swift/Kotlin go through one uniform kind: 'vendored' build.

Updating this vendor package

  1. Bump the pin: update version in package.json (this is the value the build-tree-sitter-prebuilds workflow diffs to decide whether to rebuild) and refresh _vendoredBy with the new ref.
  2. Refresh bindings/node/*, src/parser.c, src/scanner.c, src/node-types.json, src/tree_sitter/*, and binding.gyp from the new upstream ref (a release tag, or — as now — a pinned main commit). For a pinned commit the generated parser.c is committed upstream, so copy it directly; if you re-pin to a ref that does not commit parser.c, regenerate it with tree-sitter generate first.
  3. Regenerate the six native prebuilds by running the build-tree-sitter-prebuilds GitHub Actions workflow (it builds {linux,darwin,win32}-{x64,arm64} from this vendored source and opens a PR committing them under prebuilds/). While kind: 'vendored', the workflow does NOT touch npm for kotlin.
  4. Verify the packed GitNexus tarball can require('tree-sitter-kotlin') and parse a Kotlin snippet (including a fun interface) on each target platform-arch (the workflow's validate step does this in CI).

Note: darwin-x64 prebuilds depend on GitHub's macos-15-intel image, whose x86_64 macOS runners sunset ~Aug 2027. After that, darwin-x64 needs cross-compilation or dropping.