mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-06 02:49:56 +00:00
fix(zig): vendor tree-sitter-zig so npm i -g no longer warns on peers
Published overrides do not apply to dependents, so the Zig optionalDependency kept warning that tree-sitter@0.21.1 does not satisfy peerOptional ^0.22.1. Load it from vendor/ like Dart/Kotlin/Swift instead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c0c3fa18a9
commit
d307b0e274
47 changed files with 181382 additions and 147 deletions
|
|
@ -69,6 +69,7 @@ GRAMMARS: dict[str, tuple[str, str, str]] = {
|
|||
# Vendored parsers — kept here so the upstream coords for drift
|
||||
# detection are co-located with every other grammar's coords.
|
||||
"tree-sitter-proto": ("coder3101/tree-sitter-proto", "main", "src/parser.c"),
|
||||
"tree-sitter-zig": ("tree-sitter-grammars/tree-sitter-zig", "master", "src/parser.c"),
|
||||
}
|
||||
|
||||
# npm-installed grammars deliberately held below npm latest (surfaced so reviewers
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ which is deliberately dependency-free so it runs on any vanilla runner. Run with
|
|||
(pytest also discovers ``unittest.TestCase`` classes, so a future pytest CI job
|
||||
picks these up unchanged.)
|
||||
|
||||
These tests lock in the #858 fix: the 5 vendored grammars
|
||||
(c/swift/kotlin/dart/proto) are classified from the shared manifest
|
||||
These tests lock in the #858 fix: the 6 vendored grammars
|
||||
(c/swift/kotlin/dart/proto/zig) are classified from the shared manifest
|
||||
(.github/vendored-grammars.json), their ABI is read from gitnexus/vendor/<name>,
|
||||
and the report never renders a bare ``?`` placeholder. All network is mocked.
|
||||
"""
|
||||
|
|
@ -192,7 +192,7 @@ class AssertCurrent(TestCase):
|
|||
def test_assert_current_is_network_free_and_passes(self):
|
||||
report, code = self._run_assert_current() # raises if any urlopen fires
|
||||
self.assertEqual(code, 0)
|
||||
# All 5 vendored grammars are introspected from the repo (ABI 14), not skipped.
|
||||
# All 6 vendored grammars are introspected from the repo (ABI 14), not skipped.
|
||||
for name in readiness.VENDORED_NAMES:
|
||||
self.assertIn(f"{name}: vendored ABI", report)
|
||||
|
||||
|
|
@ -324,6 +324,7 @@ class ReportRendering(TestCase):
|
|||
# which is what removes the old "? (fetch failed)" for tree-sitter-proto.
|
||||
self.assertNotIn("tree-sitter-proto", _render_report.last_npm_calls)
|
||||
self.assertNotIn("tree-sitter-dart", _render_report.last_npm_calls)
|
||||
self.assertNotIn("@tree-sitter-grammars/tree-sitter-zig", _render_report.last_npm_calls)
|
||||
self.assertNotIn("Could not check", self.report)
|
||||
self.assertNotIn("fetch failed", self.report)
|
||||
|
||||
|
|
@ -343,11 +344,11 @@ class ReportRendering(TestCase):
|
|||
cells = [c.strip() for c in self._matrix_row("tree-sitter-swift").strip().strip("|").split("|")]
|
||||
self.assertEqual(cells[6], "n/a") # Upstream ABI column
|
||||
|
||||
def test_row_diff_regex_captures_all_fifteen_grammar_statuses(self):
|
||||
def test_row_diff_regex_captures_all_grammar_statuses(self):
|
||||
# The change-detection bot keys on this regex: group 1 = grammar name,
|
||||
# group 2 = the Status cell ONLY (not the whole tail). It must match every
|
||||
# row after the format change so status transitions keep being detected.
|
||||
self.assertEqual(len(self.rows), 15)
|
||||
self.assertEqual(len(self.rows), len(readiness.GRAMMARS))
|
||||
for name in readiness.VENDORED_NAMES:
|
||||
self.assertIn(name, self.rows)
|
||||
# group 2 is the Status cell — held c renders exactly "Vendored — held",
|
||||
|
|
|
|||
4
.github/vendored-grammars.json
vendored
4
.github/vendored-grammars.json
vendored
|
|
@ -22,6 +22,10 @@
|
|||
"proto": {
|
||||
"name": "tree-sitter-proto",
|
||||
"upstream": { "github": "coder3101/tree-sitter-proto" }
|
||||
},
|
||||
"zig": {
|
||||
"name": "tree-sitter-zig",
|
||||
"upstream": { "npm": "@tree-sitter-grammars/tree-sitter-zig" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ name: Build tree-sitter prebuilds
|
|||
# - tree-sitter-swift (vendored source; built from gitnexus/vendor/ — its
|
||||
# prebuilds were originally upstream-shipped, now
|
||||
# GitNexus-cross-built like the rest for uniformity)
|
||||
# - tree-sitter-zig (vendored source; built from gitnexus/vendor/ — moved
|
||||
# off npm optionalDependency so `npm i -g gitnexus`
|
||||
# no longer warns on peerOptional tree-sitter@^0.22.1.
|
||||
# Upstream linux-arm64 prebuild is a mispackaged
|
||||
# x86-64 binary; this workflow rebuilds all six.)
|
||||
#
|
||||
# Output: gitnexus/vendor/<grammar>/prebuilds/<platform-arch>/<grammar>.node for
|
||||
# all 6 targets ({linux,darwin,win32}-{x64,arm64}). tree-sitter grammars are
|
||||
|
|
@ -55,7 +60,7 @@ on:
|
|||
workflow_dispatch:
|
||||
inputs:
|
||||
grammars:
|
||||
description: 'Comma-separated grammar shortnames to build (c,dart,proto,kotlin,swift), or "all".'
|
||||
description: 'Comma-separated grammar shortnames to build (c,dart,proto,kotlin,swift,zig), or "all".'
|
||||
required: false
|
||||
type: string
|
||||
default: 'all'
|
||||
|
|
@ -86,7 +91,7 @@ on:
|
|||
- '!gitnexus/vendor/tree-sitter-*/prebuilds/**'
|
||||
# Self-test: re-run the guard if a future grammar pin is reintroduced in
|
||||
# the main package.json (optionalDependencies fallback). No-op otherwise —
|
||||
# all five grammars are now fully vendored (kotlin included).
|
||||
# all six grammars are now fully vendored (kotlin and zig included).
|
||||
- 'gitnexus/package.json'
|
||||
# Self-test: re-run the guard (normally a no-op) when the recipe changes.
|
||||
- '.github/workflows/build-tree-sitter-prebuilds.yml'
|
||||
|
|
@ -157,6 +162,11 @@ jobs:
|
|||
// so it builds from gitnexus/vendor/ like dart/proto. Its prebuilds
|
||||
// were originally upstream-shipped; rebuilding them here unifies it.
|
||||
swift: { name: 'tree-sitter-swift', kind: 'vendored' },
|
||||
// zig is vendored WITH its source (parser.c/binding.gyp). Moved off
|
||||
// the npm optionalDependency so published installs no longer warn
|
||||
// on peerOptional tree-sitter@^0.22.1. Upstream linux-arm64
|
||||
// prebuild is a mispackaged x86-64 binary; rebuild here.
|
||||
zig: { name: 'tree-sitter-zig', kind: 'vendored' },
|
||||
};
|
||||
const PLATFORMS = [
|
||||
{ platform_arch: 'linux-x64', os: 'ubuntu-24.04' },
|
||||
|
|
|
|||
20
.github/workflows/ci-tests.yml
vendored
20
.github/workflows/ci-tests.yml
vendored
|
|
@ -24,11 +24,11 @@ jobs:
|
|||
shard: ${{ fromJSON(needs.shard-plan.outputs.cov_shards) }}
|
||||
# Fail loudly (don't silently skip) if the FTS extension is unavailable, so
|
||||
# FTS-dependent lbug integration suites are guaranteed to run in CI.
|
||||
# Same contract for Zig's optionalDependency grammar: this runner is
|
||||
# linux-x64, which @tree-sitter-grammars/tree-sitter-zig publishes a
|
||||
# prebuild for, so an absent grammar here is a packaging regression and not
|
||||
# an unsupported platform. Without it every Zig suite skips and the job is
|
||||
# green having never executed the native Zig parser once.
|
||||
# Same contract for Zig's vendored grammar: this runner is linux-x64,
|
||||
# which vendor/tree-sitter-zig ships a prebuild for, so an absent grammar
|
||||
# here is a packaging regression and not an unsupported platform. Without
|
||||
# it every Zig suite skips and the job is green having never executed the
|
||||
# native Zig parser once.
|
||||
env:
|
||||
GITNEXUS_REQUIRE_FTS: '1'
|
||||
GITNEXUS_REQUIRE_ZIG: '1'
|
||||
|
|
@ -284,10 +284,12 @@ jobs:
|
|||
shell: bash
|
||||
run: python3 .github/scripts/check-tree-sitter-upgrade-readiness.py --assert-current
|
||||
|
||||
# GITNEXUS_REQUIRE_ZIG=1: every OS in this matrix has a published
|
||||
# tree-sitter-zig prebuild, so the smoke's "optional grammar may be
|
||||
# absent" exemption is revoked here and an ABI-broken Zig binding fails
|
||||
# the job instead of being accepted as a clean absence.
|
||||
# GITNEXUS_REQUIRE_ZIG=1: every OS in this matrix has a committed
|
||||
# vendored tree-sitter-zig prebuild (linux-arm64 is rebuilt by the
|
||||
# prebuild workflow; ubuntu/windows/macos latest are x64/arm64 with
|
||||
# shipped binaries), so the smoke's "optional grammar may be absent"
|
||||
# exemption is revoked here and an ABI-broken Zig binding fails the
|
||||
# job instead of being accepted as a clean absence.
|
||||
- name: Run parser-loader ABI load-smoke (dynamic)
|
||||
run: npx vitest run test/unit/parser-loader-abi.test.ts
|
||||
env:
|
||||
|
|
|
|||
|
|
@ -192,6 +192,6 @@ npx gitnexus serve # HTTP API on port 4747 (from any ind
|
|||
|
||||
### Gotchas
|
||||
|
||||
- `npm install` in `gitnexus/` triggers `prepare` (builds via `tsc`) and `postinstall` (materializes the vendored grammars into `node_modules/`, then prefers a committed prebuild per platform-arch and only source-builds when none matches). A C/C++ toolchain (`python3`, `make`, `g++`) is needed only for that source-build fallback.
|
||||
- The vendored grammars `tree-sitter-{c,dart,proto,swift,kotlin}` are handled uniformly: c is required; dart/proto/swift/kotlin are optional and skippable via `GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1`. Install warnings appear only when no prebuild matches the platform-arch and no toolchain is present, and are non-fatal — only that language's parsing is unavailable.
|
||||
- `npm install` in `gitnexus/` triggers `prepare` (builds via `tsc`) and `postinstall` (`build-tree-sitter-grammars.cjs` activates committed prebuilds in place under `vendor/`, and only source-builds when none matches). A C/C++ toolchain (`python3`, `make`, `g++`) is needed only for that source-build fallback.
|
||||
- The vendored grammars `tree-sitter-{c,dart,proto,swift,kotlin,zig}` are handled uniformly: c is required; dart/proto/swift/kotlin/zig are optional and skippable via `GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1`. Install warnings appear only when no prebuild matches the platform-arch and no toolchain is present, and are non-fatal — only that language's parsing is unavailable.
|
||||
- ESLint configured via `eslint.config.mjs` (TS, React Hooks, unused-imports). No `npm run lint` script; use `npx eslint .`. Prettier runs via lint-staged. CI checks both in `ci-quality.yml`.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ All notable changes to GitNexus will be documented in this file.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Zig grammar is vendored** — `npm i -g gitnexus` no longer warns about `@tree-sitter-grammars/tree-sitter-zig`'s `peerOptional tree-sitter@^0.22.1`. Zig loads from `vendor/tree-sitter-zig` like Dart/Kotlin/Swift. Upstream's `linux-arm64` prebuild is a mispackaged x86-64 binary and is omitted until the GitNexus prebuild workflow rebuilds it.
|
||||
|
||||
## [1.6.11] - 2026-09-04
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ results until you re-run `gitnexus analyze --repair-fts` from a shell where the
|
|||
|
||||
### Installation fails with native module errors
|
||||
|
||||
Some optional language grammars (Dart, Proto, Swift, Kotlin) require native compilation. If they fail, GitNexus still works — those languages will be skipped. To skip them intentionally (no C++ toolchain needed), set `GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1` before installing. Zig (`@tree-sitter-grammars/tree-sitter-zig`, an npm `optionalDependency`) behaves the same way: if its native binding fails to install, `.zig` files are skipped.
|
||||
Some optional language grammars (Dart, Proto, Swift, Kotlin, Zig) ship vendored native prebuilds. If a prebuild is missing and a source build is not possible, GitNexus still works — those languages will be skipped. To skip them intentionally (no C++ toolchain needed), set `GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1` before installing.
|
||||
|
||||
If `npm install -g gitnexus` fails on native modules:
|
||||
|
||||
|
|
|
|||
21
gitnexus/package-lock.json
generated
21
gitnexus/package-lock.json
generated
|
|
@ -75,7 +75,6 @@
|
|||
},
|
||||
"optionalDependencies": {
|
||||
"@huggingface/transformers": "^4.1.0",
|
||||
"@tree-sitter-grammars/tree-sitter-zig": "1.1.2",
|
||||
"onnxruntime-node": "^1.24.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -1761,26 +1760,6 @@
|
|||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tree-sitter-grammars/tree-sitter-zig": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@tree-sitter-grammars/tree-sitter-zig/-/tree-sitter-zig-1.1.2.tgz",
|
||||
"integrity": "sha512-J0L31HZ2isy3F5zb2g5QWQOv2r/pbruQNL9ADhuQv2pn5BQOzxt80WcEJaYXBeuJ8GHxVT42slpCna8k1c8LOw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-addon-api": "^8.3.0",
|
||||
"node-gyp-build": "^4.8.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tree-sitter": "^0.22.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"tree-sitter": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@
|
|||
},
|
||||
"optionalDependencies": {
|
||||
"@huggingface/transformers": "^4.1.0",
|
||||
"@tree-sitter-grammars/tree-sitter-zig": "1.1.2",
|
||||
"onnxruntime-node": "^1.24.0"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
|
|
@ -129,9 +128,6 @@
|
|||
"sharp": ">=0.35.0",
|
||||
"@huggingface/transformers": {
|
||||
"onnxruntime-node": "$onnxruntime-node"
|
||||
},
|
||||
"@tree-sitter-grammars/tree-sitter-zig": {
|
||||
"tree-sitter": "$tree-sitter"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* One registry-driven script replaces the former per-grammar
|
||||
* build-tree-sitter-<name>.cjs files (they were ~95% identical).
|
||||
*
|
||||
* The grammars (tree-sitter-c/dart/proto/swift/kotlin) are loaded from
|
||||
* The grammars (tree-sitter-c/dart/proto/swift/kotlin/zig) are loaded from
|
||||
* `vendor/<name>/` by absolute path at runtime (see
|
||||
* src/core/tree-sitter/vendored-grammars.ts) and are NEVER copied into
|
||||
* node_modules — an undeclared package under node_modules is "extraneous" to
|
||||
|
|
@ -44,6 +44,7 @@ const GRAMMARS = {
|
|||
proto: { required: false, display: 'Proto', ext: '.proto' },
|
||||
swift: { required: false, display: 'Swift', ext: '.swift' },
|
||||
kotlin: { required: false, display: 'Kotlin', ext: '.kt/.kts' },
|
||||
zig: { required: false, display: 'Zig', ext: '.zig' },
|
||||
};
|
||||
|
||||
const skipOptional = process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS === '1';
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
/**
|
||||
* Optional grammar availability check.
|
||||
*
|
||||
* tree-sitter-dart, -proto, -swift, and -kotlin are vendored under vendor/ and
|
||||
* loaded from there by absolute path (NEVER copied into node_modules — see
|
||||
* core/tree-sitter/vendored-grammars.ts / #2111). Each ships committed platform
|
||||
* prebuilds activated via node-gyp-build. All can be skipped via
|
||||
* GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or can silently
|
||||
* soft-fail when no prebuild matches the host platform (and a source build was
|
||||
* unavailable / not attempted). tree-sitter-zig is the one npm-installed
|
||||
* optionalDependency in the list; its `probe` overrides the vendored load.
|
||||
* tree-sitter-dart, -proto, -swift, -kotlin, and -zig are vendored under
|
||||
* vendor/ and loaded from there by absolute path (NEVER copied into
|
||||
* node_modules — see core/tree-sitter/vendored-grammars.ts / #2111). Each
|
||||
* ships committed platform prebuilds activated via node-gyp-build. All can
|
||||
* be skipped via GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or
|
||||
* can silently soft-fail when no prebuild matches the host platform (and a
|
||||
* source build was unavailable / not attempted).
|
||||
*
|
||||
* Either path produces the same observable: the .node binding is absent
|
||||
* at runtime. This helper detects that condition and surfaces a single
|
||||
|
|
@ -16,14 +15,11 @@
|
|||
* support is unavailable instead of silently getting a degraded index.
|
||||
*/
|
||||
|
||||
import { createRequire } from 'node:module';
|
||||
import { SupportedLanguages } from 'gitnexus-shared';
|
||||
import { isGrammarRuntimeSkipped } from '../core/tree-sitter/parser-loader.js';
|
||||
import { requireVendoredGrammar } from '../core/tree-sitter/vendored-grammars.js';
|
||||
import { cliWarn } from './cli-message.js';
|
||||
|
||||
const _require = createRequire(import.meta.url);
|
||||
|
||||
interface OptionalGrammar {
|
||||
/** Display name in warnings */
|
||||
name: string;
|
||||
|
|
@ -38,12 +34,6 @@ interface OptionalGrammar {
|
|||
* `.proto`, which is a gRPC-extractor concern, not a SupportedLanguages.
|
||||
*/
|
||||
language?: SupportedLanguages;
|
||||
/**
|
||||
* Availability probe. Defaults to `requireVendoredGrammar(pkg)`; grammars
|
||||
* that install from npm as an optionalDependency (zig) override it with a
|
||||
* plain `require` of the package.
|
||||
*/
|
||||
probe?: () => unknown;
|
||||
}
|
||||
|
||||
const OPTIONAL_GRAMMARS: OptionalGrammar[] = [
|
||||
|
|
@ -68,11 +58,9 @@ const OPTIONAL_GRAMMARS: OptionalGrammar[] = [
|
|||
},
|
||||
{
|
||||
name: 'tree-sitter-zig',
|
||||
pkg: '@tree-sitter-grammars/tree-sitter-zig',
|
||||
pkg: 'tree-sitter-zig',
|
||||
extensions: ['.zig'],
|
||||
language: SupportedLanguages.Zig,
|
||||
// npm optionalDependency, not vendored — probe via plain require.
|
||||
probe: () => _require('@tree-sitter-grammars/tree-sitter-zig'),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -123,11 +111,7 @@ export function detectMissingOptionalGrammars(): MissingGrammar[] {
|
|||
continue;
|
||||
}
|
||||
try {
|
||||
if (g.probe !== undefined) {
|
||||
g.probe();
|
||||
} else {
|
||||
requireVendoredGrammar(g.pkg);
|
||||
}
|
||||
requireVendoredGrammar(g.pkg);
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException | undefined)?.code;
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
import Parser from 'tree-sitter';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
const _require = createRequire(import.meta.url);
|
||||
import { requireVendoredGrammar } from '../../../tree-sitter/vendored-grammars.js';
|
||||
|
||||
/**
|
||||
* Zig scope-resolution query (RFC #909 Ring 3).
|
||||
*
|
||||
* The grammar is an optionalDependency (`@tree-sitter-grammars/tree-sitter-zig`),
|
||||
* so the language module is required lazily and `getZigParser` /
|
||||
* `getZigScopeQuery` throw only when actually invoked without the grammar
|
||||
* installed. That is safe: the parse pipeline filters `.zig` files through
|
||||
* `parser-loader.isLanguageAvailable` before any scope extraction runs.
|
||||
* The grammar is vendored (`vendor/tree-sitter-zig`) and may be absent on a
|
||||
* platform without a prebuild, so the language module is required lazily and
|
||||
* `getZigParser` / `getZigScopeQuery` throw only when actually invoked without
|
||||
* the grammar installed. That is safe: the parse pipeline filters `.zig` files
|
||||
* through `parser-loader.isLanguageAvailable` before any scope extraction runs.
|
||||
*
|
||||
* Zig specifics encoded here:
|
||||
* - Containers (struct/enum/union/opaque) are anonymous nodes bound by the
|
||||
|
|
@ -413,7 +411,7 @@ let _parser: Parser | null = null;
|
|||
let _query: Parser.Query | null = null;
|
||||
|
||||
function getZigLanguage(): Parameters<Parser['setLanguage']>[0] {
|
||||
return _require('@tree-sitter-grammars/tree-sitter-zig');
|
||||
return requireVendoredGrammar('tree-sitter-zig') as Parameters<Parser['setLanguage']>[0];
|
||||
}
|
||||
|
||||
export function getZigParser(): Parser {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { parentPort, threadId, workerData } from 'node:worker_threads';
|
||||
import { createRequire } from 'node:module';
|
||||
import {
|
||||
boundCallableStartPosition,
|
||||
localIdentity,
|
||||
|
|
@ -59,7 +58,7 @@ type TreeSitterLanguage = Parameters<typeof Parser.prototype.setLanguage>[0];
|
|||
// `isLanguageAvailable` must re-introduce the gate here. (The cleaner end-state
|
||||
// — routing this table through `parser-loader.getLanguageGrammar` so there is
|
||||
// one loader — is the deferred Tier-1 consolidation.)
|
||||
// Swift/Dart/Kotlin/C are vendored grammars loaded from `vendor/` by absolute
|
||||
// Swift/Dart/Kotlin/C/Zig are vendored grammars loaded from `vendor/` by absolute
|
||||
// path (NEVER copied into node_modules — see vendored-grammars.ts / #2111). Each
|
||||
// may be absent on a platform without a prebuild or a toolchain-less /
|
||||
// `--ignore-scripts` install, so every load is guarded so a missing binding
|
||||
|
|
@ -84,11 +83,9 @@ try {
|
|||
C = requireVendoredGrammar('tree-sitter-c') as TreeSitterLanguage;
|
||||
} catch {}
|
||||
|
||||
// @tree-sitter-grammars/tree-sitter-zig is an optionalDependency — may not be installed
|
||||
const _require = createRequire(import.meta.url);
|
||||
let Zig: TreeSitterLanguage | null = null;
|
||||
try {
|
||||
Zig = _require('@tree-sitter-grammars/tree-sitter-zig');
|
||||
Zig = requireVendoredGrammar('tree-sitter-zig') as TreeSitterLanguage;
|
||||
} catch {}
|
||||
import { getLanguageFromFilename } from 'gitnexus-shared';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ interface GrammarSource {
|
|||
/**
|
||||
* When true, this grammar may be disabled at runtime via
|
||||
* `GITNEXUS_SKIP_OPTIONAL_GRAMMARS`. Set ONLY on genuinely-optional grammars
|
||||
* (optionalDependencies / vendored — swift/dart/kotlin). Required dependencies
|
||||
* (optionalDependencies / vendored — swift/dart/kotlin/zig). Required dependencies
|
||||
* routed through the optional machinery for ABI safety (e.g. C, which is
|
||||
* `optional: true` + `severity: 'error'`) must NOT set this — opting out of a
|
||||
* required parser is always an install/platform problem, never a user choice.
|
||||
|
|
@ -177,22 +177,14 @@ const SOURCES: Record<string, GrammarSource> = {
|
|||
'Likely cause: no prebuilt `.node` for this platform/architecture. ' +
|
||||
`See ${ISSUES_URL}/2107.`,
|
||||
},
|
||||
// Zig grammar declares peerOptional `tree-sitter@^0.22.1` but its native
|
||||
// binding is ABI-compatible with the bundled `tree-sitter@0.21.x` runtime
|
||||
// (verified by load-time smoke test). The peer-dep mismatch is suppressed
|
||||
// via the `overrides` block in package.json. Listed as `optional: true`
|
||||
// because the package is in `optionalDependencies` — users on platforms
|
||||
// without a prebuild may not have it — and `userSkippable` because it is
|
||||
// a genuinely-optional grammar: `GITNEXUS_SKIP_OPTIONAL_GRAMMARS` must be
|
||||
// able to disable it at analyze time like swift/dart/kotlin.
|
||||
[SupportedLanguages.Zig]: {
|
||||
load: () => _require('@tree-sitter-grammars/tree-sitter-zig'),
|
||||
load: () => requireVendoredGrammar('tree-sitter-zig'),
|
||||
optional: true,
|
||||
userSkippable: true,
|
||||
unavailableNote:
|
||||
'Zig parsing disabled: `@tree-sitter-grammars/tree-sitter-zig` is an ' +
|
||||
'optionalDependency and is not installed (or its native binding failed ' +
|
||||
'to load on this platform).',
|
||||
'Zig parsing disabled: vendored `tree-sitter-zig` (under ' +
|
||||
'`gitnexus/vendor/tree-sitter-zig`) failed to load. ' +
|
||||
'Likely cause: no prebuilt `.node` for this platform/architecture.',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export const VENDORED_GRAMMAR_PACKAGES: ReadonlySet<string> = new Set([
|
|||
'tree-sitter-proto',
|
||||
'tree-sitter-swift',
|
||||
'tree-sitter-kotlin',
|
||||
'tree-sitter-zig',
|
||||
]);
|
||||
|
||||
/** Absolute directory of a vendored grammar package under `vendor/`. */
|
||||
|
|
@ -42,7 +43,7 @@ export const vendoredGrammarDir = (packageName: string): string =>
|
|||
/**
|
||||
* Load a vendored tree-sitter grammar by its absolute path under `vendor/`.
|
||||
*
|
||||
* GitNexus vendors five grammars (c/dart/proto/swift/kotlin) inside its own
|
||||
* GitNexus vendors six grammars (c/dart/proto/swift/kotlin/zig) inside its own
|
||||
* package under `vendor/`, each shipping committed per-platform prebuilds. They
|
||||
* are deliberately NOT npm dependencies and must NEVER be copied into
|
||||
* `node_modules`: an undeclared package under `node_modules` is "extraneous" to
|
||||
|
|
|
|||
|
|
@ -70,10 +70,8 @@ const GRAMMAR_PACKAGES: Partial<Record<SupportedLanguages, { pkg: string; subpat
|
|||
pkg: 'tree-sitter-typescript',
|
||||
subpaths: ['typescript/src/node-types.json', 'tsx/src/node-types.json'],
|
||||
},
|
||||
// optionalDependency — loadGrammarModel returns null when absent, so the
|
||||
// gate skips Zig literals ('unavailable', R9) instead of failing.
|
||||
[SupportedLanguages.Zig]: {
|
||||
pkg: '@tree-sitter-grammars/tree-sitter-zig',
|
||||
pkg: 'tree-sitter-zig',
|
||||
subpaths: ['src/node-types.json'],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ import { isLanguageAvailable } from '../../src/core/tree-sitter/parser-loader.js
|
|||
* a job it cannot satisfy.
|
||||
*/
|
||||
export const OPTIONAL_GRAMMAR_ENV: Readonly<Partial<Record<string, string>>> = {
|
||||
// @tree-sitter-grammars/tree-sitter-zig@1.1.2 publishes prebuilds for
|
||||
// {darwin,linux,win32}-{x64,arm64} — every OS in the CI matrix.
|
||||
// Vendored tree-sitter-zig ships prebuilds for the CI matrix OS/arch
|
||||
// tuples (linux-arm64 is rebuilt by the GitNexus prebuild workflow;
|
||||
// ubuntu/windows/macos latest in required jobs have a committed binary).
|
||||
[SupportedLanguages.Zig]: 'GITNEXUS_REQUIRE_ZIG',
|
||||
} satisfies Partial<Record<SupportedLanguages, string>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ import {
|
|||
import { SupportedLanguages } from '../../../src/config/supported-languages.js';
|
||||
import { describeGrammarPresence, optionalGrammarGate } from '../../helpers/optional-grammar.js';
|
||||
|
||||
// `@tree-sitter-grammars/tree-sitter-zig` is an optionalDependency: on a
|
||||
// platform without a prebuild the grammar is absent and the pipeline skips
|
||||
// `.zig` files by contract, so these suites skip too (Swift/Dart pattern).
|
||||
// Vendored `tree-sitter-zig`: on a platform without a prebuild the grammar
|
||||
// is absent and the pipeline skips `.zig` files by contract, so these
|
||||
// suites skip too (Swift/Dart pattern).
|
||||
// Under GITNEXUS_REQUIRE_ZIG=1 the skip is not acceptable — the presence
|
||||
// assertion below fails the job instead of letting Zig vanish from a green run.
|
||||
const zig = optionalGrammarGate(SupportedLanguages.Zig);
|
||||
|
|
|
|||
|
|
@ -160,8 +160,8 @@ const NON_BRIDGE_CORPUS = [
|
|||
] as const satisfies readonly CorpusEntry[];
|
||||
|
||||
/**
|
||||
* Same contract, for fixtures whose grammar is an npm optionalDependency and
|
||||
* may be absent on the runner. Gated per language rather than per case so a
|
||||
* Same contract, for fixtures whose grammar is optional (vendored prebuild
|
||||
* may be absent on the runner). Gated per language rather than per case so a
|
||||
* missing grammar SKIPS (the pipeline drops the files by contract, and an
|
||||
* empty emit would otherwise fail every sentinel for a reason that has
|
||||
* nothing to do with the schema).
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { SupportedLanguages, getLanguageFromFilename } from 'gitnexus-shared';
|
||||
import { getProvider } from '../../src/core/ingestion/languages/index.js';
|
||||
import Parser from 'tree-sitter';
|
||||
import { createRequire } from 'module';
|
||||
import { requireVendoredGrammar } from '../../src/core/tree-sitter/vendored-grammars.js';
|
||||
|
||||
const fixturesDir = path.resolve(__dirname, '..', 'fixtures', 'sample-code');
|
||||
|
||||
|
|
@ -693,7 +693,7 @@ describe('Tree-sitter multi-language parsing', () => {
|
|||
const zigPackageInstalled = (() => {
|
||||
if (isGrammarRuntimeSkipped(SupportedLanguages.Zig)) return false;
|
||||
try {
|
||||
createRequire(import.meta.url).resolve('@tree-sitter-grammars/tree-sitter-zig');
|
||||
requireVendoredGrammar('tree-sitter-zig');
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
|
|
@ -740,11 +740,10 @@ describe('Tree-sitter multi-language parsing', () => {
|
|||
// Exercise the loader's real absent-binding branch (the `source.load()`
|
||||
// catch in `loadGrammar`), not the `GITNEXUS_SKIP_OPTIONAL_GRAMMARS`
|
||||
// opt-out, which is a separate code path with its own test
|
||||
// (parser-loader-skip-optional.test.ts). The Zig row loads through the
|
||||
// module-scoped `createRequire(import.meta.url)`, so stand in for
|
||||
// `node:module` with a require that reports the package missing and
|
||||
// delegates everything else. A fresh module copy is needed because the
|
||||
// loader memoizes load results.
|
||||
// (parser-loader-skip-optional.test.ts). Zig loads through
|
||||
// `requireVendoredGrammar`, so stand in for that helper and report the
|
||||
// grammar missing. A fresh module copy is needed because the loader
|
||||
// memoizes load results.
|
||||
//
|
||||
// The fresh copy also re-reads `GITNEXUS_SKIP_OPTIONAL_GRAMMARS` (parsed
|
||||
// lazily once per module). Under `=zig` / `=all` — a supported way to
|
||||
|
|
@ -752,25 +751,21 @@ describe('Tree-sitter multi-language parsing', () => {
|
|||
// path below would never run, so the variable is cleared for this test
|
||||
// and restored afterwards. Clearing (not skipping) keeps the branch
|
||||
// exercised in every environment.
|
||||
const ZIG_PKG = '@tree-sitter-grammars/tree-sitter-zig';
|
||||
const SKIP_ENV = 'GITNEXUS_SKIP_OPTIONAL_GRAMMARS';
|
||||
const savedSkip = process.env[SKIP_ENV];
|
||||
delete process.env[SKIP_ENV];
|
||||
vi.doMock('node:module', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('node:module')>();
|
||||
vi.doMock('../../src/core/tree-sitter/vendored-grammars.js', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import('../../src/core/tree-sitter/vendored-grammars.js')>();
|
||||
return {
|
||||
...actual,
|
||||
createRequire: (url: string | URL) => {
|
||||
const real = actual.createRequire(url);
|
||||
const stub = ((id: string) => {
|
||||
if (id === ZIG_PKG) {
|
||||
const err = new Error(`Cannot find module '${id}'`) as NodeJS.ErrnoException;
|
||||
err.code = 'MODULE_NOT_FOUND';
|
||||
throw err;
|
||||
}
|
||||
return real(id);
|
||||
}) as unknown as NodeJS.Require;
|
||||
return Object.assign(stub, real);
|
||||
requireVendoredGrammar: (packageName: string) => {
|
||||
if (packageName === 'tree-sitter-zig') {
|
||||
const err = new Error(`Cannot find module '${packageName}'`) as NodeJS.ErrnoException;
|
||||
err.code = 'MODULE_NOT_FOUND';
|
||||
throw err;
|
||||
}
|
||||
return actual.requireVendoredGrammar(packageName);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -788,7 +783,7 @@ describe('Tree-sitter multi-language parsing', () => {
|
|||
} finally {
|
||||
if (savedSkip === undefined) delete process.env[SKIP_ENV];
|
||||
else process.env[SKIP_ENV] = savedSkip;
|
||||
vi.doUnmock('node:module');
|
||||
vi.doUnmock('../../src/core/tree-sitter/vendored-grammars.js');
|
||||
vi.resetModules();
|
||||
}
|
||||
});
|
||||
|
|
@ -1005,8 +1000,8 @@ describe('Tree-sitter multi-language parsing', () => {
|
|||
[SupportedLanguages.CSharp, 'simple.cs'],
|
||||
[SupportedLanguages.Rust, 'simple.rs'],
|
||||
[SupportedLanguages.PHP, 'simple.php'],
|
||||
// Dart and Swift (vendored optional grammars) and Zig (npm optionalDependency)
|
||||
// are excluded — none of the three is guaranteed to be installed
|
||||
// Dart, Swift, and Zig (vendored optional grammars) are excluded —
|
||||
// none of the three is guaranteed to be installed on every platform.
|
||||
];
|
||||
|
||||
for (const [lang, fixture, filePath] of langFixtures) {
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ describe('build-tree-sitter-grammars.cjs consolidated activation', () => {
|
|||
});
|
||||
|
||||
it('never exits non-zero across grammars and env permutations (postinstall hard invariant)', () => {
|
||||
for (const grammar of ['c', 'dart', 'proto', 'swift', 'kotlin']) {
|
||||
for (const grammar of ['c', 'dart', 'proto', 'swift', 'kotlin', 'zig']) {
|
||||
for (const overrides of [{ GITNEXUS_SKIP_OPTIONAL_GRAMMARS: '1' }, {}]) {
|
||||
const r = runBuild(grammar, overrides);
|
||||
expect(r.status, `${grammar} ${JSON.stringify(overrides)}`).toBe(0);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ describe('CLI commands', () => {
|
|||
expect(optional['tree-sitter-dart']).toBeUndefined();
|
||||
expect(optional['tree-sitter-proto']).toBeUndefined();
|
||||
expect(optional['tree-sitter-swift']).toBeUndefined();
|
||||
expect(optional['tree-sitter-zig']).toBeUndefined();
|
||||
expect(optional['@tree-sitter-grammars/tree-sitter-zig']).toBeUndefined();
|
||||
// #2111: the grammars MUST NOT be copied into node_modules at install — an
|
||||
// undeclared node_modules package is "extraneous" to every subsequent
|
||||
// npm/npx reify, which prunes/relocates it (Windows EPERM symlink + silent
|
||||
|
|
@ -174,6 +176,23 @@ describe('CLI commands', () => {
|
|||
expect(kotlinPkg.default.peerDependencies['tree-sitter']).toContain('^0.21');
|
||||
});
|
||||
|
||||
it('vendors tree-sitter-zig instead of an npm optionalDependency', async () => {
|
||||
const pkg = await import('../../package.json', { with: { type: 'json' } });
|
||||
const zigPkg = await import('../../vendor/tree-sitter-zig/package.json', {
|
||||
with: { type: 'json' },
|
||||
});
|
||||
const optional = pkg.default.optionalDependencies ?? {};
|
||||
expect(optional['@tree-sitter-grammars/tree-sitter-zig']).toBeUndefined();
|
||||
expect(Object.keys(pkg.default.overrides ?? {})).not.toContain(
|
||||
'@tree-sitter-grammars/tree-sitter-zig',
|
||||
);
|
||||
expect(pkg.default.scripts.postinstall).toContain('build-tree-sitter-grammars.cjs');
|
||||
expect(zigPkg.default.version).toBe('1.1.2');
|
||||
expect(zigPkg.default.scripts?.install).toBeUndefined();
|
||||
expect(zigPkg.default.dependencies).toBeUndefined();
|
||||
expect(zigPkg.default.peerDependencies['tree-sitter']).toContain('^0.21');
|
||||
});
|
||||
|
||||
it('vendors tree-sitter-c prebuild-only at the 0.21.4 ABI pin instead of an npm dependency (#2116/#1242)', async () => {
|
||||
const pkg = await import('../../package.json', { with: { type: 'json' } });
|
||||
const cPkg = await import('../../vendor/tree-sitter-c/package.json', {
|
||||
|
|
|
|||
|
|
@ -73,20 +73,28 @@ describe('COMPATIBLE_ABI gate', () => {
|
|||
});
|
||||
|
||||
describe('GRAMMARS registry', () => {
|
||||
it('covers all five grammars (swift/kotlin npm, dart/proto github, c npm)', () => {
|
||||
expect(Object.keys(mod.GRAMMARS).sort()).toEqual(['c', 'dart', 'kotlin', 'proto', 'swift']);
|
||||
it('covers all six grammars (swift/kotlin/zig npm, dart/proto github, c npm)', () => {
|
||||
expect(Object.keys(mod.GRAMMARS).sort()).toEqual([
|
||||
'c',
|
||||
'dart',
|
||||
'kotlin',
|
||||
'proto',
|
||||
'swift',
|
||||
'zig',
|
||||
]);
|
||||
expect(mod.GRAMMARS.swift.npm).toBe('tree-sitter-swift');
|
||||
expect(mod.GRAMMARS.dart.github).toContain('tree-sitter-dart');
|
||||
expect(mod.GRAMMARS.zig.npm).toBe('@tree-sitter-grammars/tree-sitter-zig');
|
||||
});
|
||||
|
||||
it('marks c and kotlin report-only (holds); swift/dart/proto are auto-updatable', () => {
|
||||
it('marks c and kotlin report-only (holds); swift/dart/proto/zig are auto-updatable', () => {
|
||||
expect(mod.GRAMMARS.c.npm).toBe('tree-sitter-c');
|
||||
expect(mod.GRAMMARS.c.hold).toBeTruthy(); // ABI-pinned: detected/reported, never auto-applied
|
||||
// kotlin is pinned to an unreleased fwcd main commit for `fun interface`
|
||||
// support (#169); npm latest (0.3.8) lacks it, so the strict-inequality
|
||||
// isNewer would auto-revert the pin without this hold.
|
||||
expect(mod.GRAMMARS.kotlin.hold).toBeTruthy();
|
||||
for (const k of ['swift', 'dart', 'proto']) {
|
||||
for (const k of ['swift', 'dart', 'proto', 'zig']) {
|
||||
expect(mod.GRAMMARS[k].hold).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,9 +39,8 @@ describe('parser-loader GITNEXUS_SKIP_OPTIONAL_GRAMMARS runtime gate', () => {
|
|||
expect(isLanguageAvailable(SupportedLanguages.Swift)).toBe(false);
|
||||
expect(isLanguageAvailable(SupportedLanguages.Dart)).toBe(false);
|
||||
expect(isLanguageAvailable(SupportedLanguages.Kotlin)).toBe(false);
|
||||
// Zig is an npm optionalDependency rather than a vendored grammar, but it
|
||||
// is just as genuinely optional: the documented opt-out must cover it too
|
||||
// (`optional-grammars.ts` lists it among the skippable grammars).
|
||||
// Zig is a vendored optional grammar: the documented opt-out must cover
|
||||
// it too (`optional-grammars.ts` lists it among the skippable grammars).
|
||||
expect(isLanguageAvailable(SupportedLanguages.Zig)).toBe(false);
|
||||
});
|
||||
|
||||
|
|
@ -58,6 +57,7 @@ describe('parser-loader GITNEXUS_SKIP_OPTIONAL_GRAMMARS runtime gate', () => {
|
|||
expect(isLanguageAvailable(SupportedLanguages.Swift), `value=${v}`).toBe(false);
|
||||
expect(isLanguageAvailable(SupportedLanguages.Dart), `value=${v}`).toBe(false);
|
||||
expect(isLanguageAvailable(SupportedLanguages.Kotlin), `value=${v}`).toBe(false);
|
||||
expect(isLanguageAvailable(SupportedLanguages.Zig), `value=${v}`).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
/**
|
||||
* Regression guard for #2111 / #1728.
|
||||
*
|
||||
* The five vendored tree-sitter grammars (c/dart/proto/swift/kotlin) MUST load
|
||||
* The six vendored tree-sitter grammars (c/dart/proto/swift/kotlin/zig) MUST load
|
||||
* from `vendor/` by absolute path and MUST NEVER be copied into / required from
|
||||
* `node_modules`. An undeclared package under node_modules is "extraneous" to
|
||||
* every subsequent npm/npx arborist reify, which prunes/relocates it — on
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
* from the PR review of the Zig provider — the assertion is the behavior that
|
||||
* was wrong, not merely that extraction runs.
|
||||
*
|
||||
* `@tree-sitter-grammars/tree-sitter-zig` is an optionalDependency: the whole
|
||||
* file skips cleanly when it is absent, mirroring the Dart/Kotlin suites.
|
||||
* Vendored `tree-sitter-zig` may be absent on a platform without a prebuild:
|
||||
* the whole file skips cleanly when it is, mirroring the Dart/Kotlin suites.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createRequire } from 'node:module';
|
||||
import Parser from 'tree-sitter';
|
||||
import { SupportedLanguages, type BindingRef, type SymbolDefinition } from 'gitnexus-shared';
|
||||
import { isOptionalGrammarRequired } from '../helpers/optional-grammar.js';
|
||||
import { requireVendoredGrammar } from '../../src/core/tree-sitter/vendored-grammars.js';
|
||||
import type { SyntaxNode } from '../../src/core/ingestion/utils/ast-helpers.js';
|
||||
import { zigExportChecker } from '../../src/core/ingestion/export-detection.js';
|
||||
import { createMethodExtractor } from '../../src/core/ingestion/method-extractors/generic.js';
|
||||
|
|
@ -50,10 +50,9 @@ import { createSemanticModel } from '../../src/core/ingestion/model/semantic-mod
|
|||
import { extract as extractScopes } from '../../src/core/ingestion/scope-extractor.js';
|
||||
import { populateClassOwnedMembers } from '../../src/core/ingestion/scope-resolution/scope/walkers.js';
|
||||
|
||||
const _require = createRequire(import.meta.url);
|
||||
let Zig: unknown = null;
|
||||
try {
|
||||
Zig = _require('@tree-sitter-grammars/tree-sitter-zig');
|
||||
Zig = requireVendoredGrammar('tree-sitter-zig');
|
||||
} catch {
|
||||
// optional grammar absent on this platform — suite skips below
|
||||
}
|
||||
|
|
@ -71,7 +70,7 @@ describe.skipIf(!isOptionalGrammarRequired(SupportedLanguages.Zig))(
|
|||
expect(
|
||||
Zig,
|
||||
'GITNEXUS_REQUIRE_ZIG=1 declares the Zig grammar mandatory on this runner, but ' +
|
||||
"require('@tree-sitter-grammars/tree-sitter-zig') failed — every case below would " +
|
||||
"requireVendoredGrammar('tree-sitter-zig') failed — every case below would " +
|
||||
'have skipped and the job would still be green.',
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
|
|
|||
21
gitnexus/vendor/tree-sitter-zig/LICENSE
vendored
Normal file
21
gitnexus/vendor/tree-sitter-zig/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2024 Amaan Qureshi <amaanq12@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
25
gitnexus/vendor/tree-sitter-zig/README.md
vendored
Normal file
25
gitnexus/vendor/tree-sitter-zig/README.md
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
## GitNexus vendor notice
|
||||
|
||||
This directory is a GitNexus-managed vendored copy of
|
||||
`@tree-sitter-grammars/tree-sitter-zig@1.1.2`. GitNexus keeps the top-level
|
||||
`tree-sitter` dependency pinned to `0.21.1` until the broader parser runtime
|
||||
upgrade is handled separately (#858). The upstream package declares
|
||||
`peerOptional tree-sitter@^0.22.1`; that peer is ABI-compatible with 0.21.x
|
||||
but npm still warns on `npm i -g gitnexus` because a published package's
|
||||
`overrides` are ignored by dependents.
|
||||
|
||||
Unified with the Dart/Proto/Kotlin/Swift/C vendored grammars, this copy
|
||||
vendors the grammar **source** — `binding.gyp`, `bindings/node/binding.cc`,
|
||||
`src/parser.c` (ABI 14), and `src/tree_sitter/` — so
|
||||
`gitnexus/scripts/build-tree-sitter-grammars.cjs` can source-build the native
|
||||
binding on a toolchain host when no committed prebuild matches. The native
|
||||
`prebuilds/` are loaded in place by `node-gyp-build`. Upstream's published
|
||||
`linux-arm64` `.node` is a mispackaged x86-64 binary and is not shipped;
|
||||
`.github/workflows/build-tree-sitter-prebuilds.yml` rebuilds all six tuples.
|
||||
|
||||
When updating this vendor package, replace it from the official
|
||||
`@tree-sitter-grammars/tree-sitter-zig` npm release: refresh
|
||||
`src/parser.c`/`src/tree_sitter/`/`binding.gyp`/`bindings/node/`, bump
|
||||
`version` in `package.json` to retrigger the prebuild workflow, update the
|
||||
`_vendoredBy` provenance, and verify the packed GitNexus tarball can both
|
||||
load a committed prebuild and source-build `tree-sitter-zig`.
|
||||
29
gitnexus/vendor/tree-sitter-zig/binding.gyp
vendored
Normal file
29
gitnexus/vendor/tree-sitter-zig/binding.gyp
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_zig_binding",
|
||||
"dependencies": [
|
||||
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
|
||||
],
|
||||
"include_dirs": [
|
||||
"src",
|
||||
],
|
||||
"sources": [
|
||||
"bindings/node/binding.cc",
|
||||
"src/parser.c",
|
||||
],
|
||||
"conditions": [
|
||||
["OS!='win'", {
|
||||
"cflags_c": [
|
||||
"-std=c11",
|
||||
],
|
||||
}, { # OS == "win"
|
||||
"cflags_c": [
|
||||
"/std:c11",
|
||||
"/utf-8",
|
||||
],
|
||||
}],
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
20
gitnexus/vendor/tree-sitter-zig/bindings/node/binding.cc
vendored
Normal file
20
gitnexus/vendor/tree-sitter-zig/bindings/node/binding.cc
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <napi.h>
|
||||
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
|
||||
extern "C" TSLanguage *tree_sitter_zig();
|
||||
|
||||
// "tree-sitter", "language" hashed with BLAKE2
|
||||
const napi_type_tag LANGUAGE_TYPE_TAG = {
|
||||
0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
|
||||
};
|
||||
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
exports["name"] = Napi::String::New(env, "zig");
|
||||
auto language = Napi::External<TSLanguage>::New(env, tree_sitter_zig());
|
||||
language.TypeTag(&LANGUAGE_TYPE_TAG);
|
||||
exports["language"] = language;
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(tree_sitter_zig_binding, Init)
|
||||
28
gitnexus/vendor/tree-sitter-zig/bindings/node/index.d.ts
vendored
Normal file
28
gitnexus/vendor/tree-sitter-zig/bindings/node/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
type BaseNode = {
|
||||
type: string;
|
||||
named: boolean;
|
||||
};
|
||||
|
||||
type ChildNode = {
|
||||
multiple: boolean;
|
||||
required: boolean;
|
||||
types: BaseNode[];
|
||||
};
|
||||
|
||||
type NodeInfo =
|
||||
| (BaseNode & {
|
||||
subtypes: BaseNode[];
|
||||
})
|
||||
| (BaseNode & {
|
||||
fields: { [name: string]: ChildNode };
|
||||
children: ChildNode[];
|
||||
});
|
||||
|
||||
type Language = {
|
||||
name: string;
|
||||
language: unknown;
|
||||
nodeTypeInfo: NodeInfo[];
|
||||
};
|
||||
|
||||
declare const language: Language;
|
||||
export = language;
|
||||
11
gitnexus/vendor/tree-sitter-zig/bindings/node/index.js
vendored
Normal file
11
gitnexus/vendor/tree-sitter-zig/bindings/node/index.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
const root = require("path").join(__dirname, "..", "..");
|
||||
|
||||
module.exports =
|
||||
typeof process.versions.bun === "string"
|
||||
// Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
|
||||
? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-zig.node`)
|
||||
: require("node-gyp-build")(root);
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||
} catch (_) {}
|
||||
900
gitnexus/vendor/tree-sitter-zig/grammar.js
vendored
Normal file
900
gitnexus/vendor/tree-sitter-zig/grammar.js
vendored
Normal file
|
|
@ -0,0 +1,900 @@
|
|||
/**
|
||||
* @file Zig grammar for tree-sitter
|
||||
* @author Amaan Qureshi <amaanq12@gmail.com>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/// <reference types="tree-sitter-cli/dsl" />
|
||||
// @ts-check
|
||||
|
||||
const PREC = {
|
||||
PAREN_DECLARATOR: -10,
|
||||
CONDITIONAL: -1,
|
||||
DEFAULT: 0,
|
||||
LOGICAL_OR: 1,
|
||||
LOGICAL_AND: 2,
|
||||
EQUAL: 3,
|
||||
BITWISE: 4,
|
||||
SHIFT: 5,
|
||||
ADD: 6,
|
||||
MULTIPLY: 7,
|
||||
UNARY: 8,
|
||||
STRUCT: 9,
|
||||
MEMBER: 10,
|
||||
};
|
||||
|
||||
const builtinTypes = [
|
||||
'bool',
|
||||
'f16',
|
||||
'f32',
|
||||
'f64',
|
||||
'f128',
|
||||
'void',
|
||||
'type',
|
||||
'anyerror',
|
||||
'anyopaque',
|
||||
'anytype',
|
||||
'noreturn',
|
||||
'isize',
|
||||
'usize',
|
||||
'comptime_int',
|
||||
'comptime_float',
|
||||
'c_short',
|
||||
'c_ushort',
|
||||
'c_int',
|
||||
'c_uint',
|
||||
'c_long',
|
||||
'c_ulong',
|
||||
'c_longlong',
|
||||
'c_ulonglong',
|
||||
'c_longdouble',
|
||||
/(i|u)[1-9][0-9]*/,
|
||||
];
|
||||
|
||||
module.exports = grammar({
|
||||
name: 'zig',
|
||||
|
||||
conflicts: $ => [
|
||||
[$.for_expression],
|
||||
[$.while_expression],
|
||||
|
||||
[$.expression, $._function_prototype],
|
||||
[$.expression, $.if_type_expression],
|
||||
|
||||
[$.comptime_type_expression, $.expression],
|
||||
[$.comptime_type_expression, $.parameter],
|
||||
],
|
||||
|
||||
extras: $ => [
|
||||
$.comment,
|
||||
/\s/,
|
||||
],
|
||||
|
||||
inline: $ => [
|
||||
$._reserved_identifier,
|
||||
],
|
||||
|
||||
precedences: $ => [
|
||||
[$.container_field, $.type_expression],
|
||||
],
|
||||
|
||||
supertypes: $ => [
|
||||
$.statement,
|
||||
$.expression,
|
||||
$.type_expression,
|
||||
$.primary_type_expression,
|
||||
],
|
||||
|
||||
word: $ => $._identifier,
|
||||
|
||||
rules: {
|
||||
source_file: $ => optional($._container_members),
|
||||
|
||||
_container_members: $ => choice(
|
||||
seq(
|
||||
repeat1(choice(
|
||||
$.test_declaration,
|
||||
$.comptime_declaration,
|
||||
$.variable_declaration,
|
||||
$.function_declaration,
|
||||
$.using_namespace_declaration,
|
||||
seq($.container_field, ','),
|
||||
)),
|
||||
optional($.container_field),
|
||||
),
|
||||
$.container_field,
|
||||
),
|
||||
|
||||
test_declaration: $ => seq(
|
||||
optional('pub'),
|
||||
'test',
|
||||
optional(choice($.string, $.identifier)),
|
||||
$.block,
|
||||
),
|
||||
|
||||
comptime_declaration: $ => prec(1, seq(
|
||||
optional('pub'),
|
||||
'comptime',
|
||||
$.block,
|
||||
)),
|
||||
|
||||
container_field: $ => prec.right(prec.dynamic(1, seq(
|
||||
optional('comptime'),
|
||||
choice(
|
||||
seq(
|
||||
field('name', choice($.identifier, $._reserved_identifier, alias($.builtin_type, $.identifier))),
|
||||
':',
|
||||
field('type', choice($.primary_type_expression, $.if_type_expression, $.comptime_type_expression)),
|
||||
),
|
||||
field('name', choice($.primary_type_expression, $.if_type_expression, $.comptime_type_expression)),
|
||||
),
|
||||
optional($.byte_alignment),
|
||||
optional(seq('=', $.expression)),
|
||||
))),
|
||||
|
||||
variable_declaration: $ => seq(
|
||||
optional('pub'),
|
||||
optional(choice(
|
||||
'export',
|
||||
seq('extern', optional($.string)),
|
||||
)),
|
||||
optional('threadlocal'),
|
||||
$._variable_declaration_header,
|
||||
optional(seq('=', $.expression)),
|
||||
';',
|
||||
),
|
||||
|
||||
_variable_declaration_expression_statement: $ => choice(
|
||||
seq(
|
||||
$._variable_declaration_header,
|
||||
repeat(prec(1, seq(',', choice($._variable_declaration_header, $.expression)))),
|
||||
'=',
|
||||
$.expression,
|
||||
';',
|
||||
),
|
||||
seq(
|
||||
$.expression,
|
||||
choice(
|
||||
seq(
|
||||
choice(
|
||||
'=', '*=', '*%=', '*|=', '/=', '%=',
|
||||
'+=', '+%=', '+|=', '-=', '-%=', '-|=',
|
||||
'<<=', '<<|=', '>>=', '&=', '^=', '|=',
|
||||
),
|
||||
$.expression,
|
||||
),
|
||||
seq(
|
||||
repeat1(prec(1, seq(',', choice($._variable_declaration_header, $.expression)))),
|
||||
'=',
|
||||
$.expression,
|
||||
),
|
||||
),
|
||||
';',
|
||||
),
|
||||
),
|
||||
|
||||
_variable_declaration_header: $ => prec(1, seq(
|
||||
choice('const', 'var'),
|
||||
$.identifier,
|
||||
optional(seq(
|
||||
':',
|
||||
field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
|
||||
)),
|
||||
optional($.byte_alignment),
|
||||
optional($.address_space),
|
||||
optional($.link_section),
|
||||
)),
|
||||
|
||||
function_declaration: $ => seq(
|
||||
optional('pub'),
|
||||
optional(choice(
|
||||
'export',
|
||||
seq('extern', optional($.string)),
|
||||
'inline',
|
||||
'noinline',
|
||||
)),
|
||||
$._function_prototype,
|
||||
choice(
|
||||
';',
|
||||
field('body', $.block),
|
||||
),
|
||||
),
|
||||
|
||||
_function_prototype: $ => seq(
|
||||
'fn',
|
||||
optional(field('name', $.identifier)),
|
||||
$.parameters,
|
||||
optional($.byte_alignment),
|
||||
optional($.address_space),
|
||||
optional($.link_section),
|
||||
optional($.calling_convention),
|
||||
field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
|
||||
),
|
||||
|
||||
parameters: $ => seq('(', optionalCommaSep($.parameter), ')'),
|
||||
|
||||
parameter: $ => choice(
|
||||
seq(
|
||||
optional(choice('noalias', 'comptime')),
|
||||
optional(seq(
|
||||
field('name', choice($.identifier, alias($.builtin_type, $.identifier))),
|
||||
':',
|
||||
)),
|
||||
field('type', choice($.type_expression, $.if_type_expression, $.comptime_type_expression)),
|
||||
),
|
||||
'...',
|
||||
),
|
||||
|
||||
using_namespace_declaration: $ => seq(
|
||||
optional('pub'),
|
||||
'usingnamespace',
|
||||
$.expression,
|
||||
';',
|
||||
),
|
||||
|
||||
block: $ => seq(
|
||||
'{',
|
||||
repeat($.statement),
|
||||
'}',
|
||||
),
|
||||
|
||||
struct_declaration: $ => seq(
|
||||
optional(choice('extern', 'packed')),
|
||||
'struct',
|
||||
optional(seq('(', $.expression, ')')),
|
||||
'{',
|
||||
$._container_members,
|
||||
'}',
|
||||
),
|
||||
|
||||
opaque_declaration: $ => seq(
|
||||
optional(choice('extern', 'packed')),
|
||||
'opaque',
|
||||
'{',
|
||||
$._container_members,
|
||||
'}',
|
||||
),
|
||||
|
||||
enum_declaration: $ => seq(
|
||||
optional(choice('extern', 'packed')),
|
||||
'enum',
|
||||
optional(seq('(', $.expression, ')')),
|
||||
'{',
|
||||
$._container_members,
|
||||
'}',
|
||||
),
|
||||
|
||||
union_declaration: $ => seq(
|
||||
optional(choice('extern', 'packed')),
|
||||
'union',
|
||||
optional(seq(
|
||||
'(',
|
||||
choice(
|
||||
seq('enum', optional(seq('(', $.expression, ')'))),
|
||||
$.expression,
|
||||
),
|
||||
')',
|
||||
)),
|
||||
'{',
|
||||
$._container_members,
|
||||
'}',
|
||||
),
|
||||
|
||||
error_set_declaration: $ => seq(
|
||||
'error',
|
||||
'{',
|
||||
optionalCommaSep($.identifier),
|
||||
'}',
|
||||
),
|
||||
|
||||
statement: $ => choice(
|
||||
$.comptime_statement,
|
||||
$.nosuspend_statement,
|
||||
$.suspend_statement,
|
||||
$.defer_statement,
|
||||
$.errdefer_statement,
|
||||
$.expression_statement,
|
||||
alias($._variable_declaration_expression_statement, $.variable_declaration),
|
||||
$.if_statement,
|
||||
$.for_statement,
|
||||
$.while_statement,
|
||||
$.labeled_statement,
|
||||
prec(1, $.switch_expression),
|
||||
),
|
||||
|
||||
comptime_statement: $ => seq(
|
||||
'comptime',
|
||||
choice(
|
||||
$._block_expr_statement,
|
||||
alias($._variable_declaration_expression_statement, $.variable_declaration),
|
||||
),
|
||||
),
|
||||
|
||||
nosuspend_statement: $ => seq('nosuspend', $._block_expr_statement),
|
||||
|
||||
suspend_statement: $ => seq('suspend', $._block_expr_statement),
|
||||
|
||||
defer_statement: $ => seq('defer', $._block_expr_statement),
|
||||
|
||||
errdefer_statement: $ => seq('errdefer', optional($.payload), $._block_expr_statement),
|
||||
|
||||
_block_expr_statement: $ => prec(1, choice(
|
||||
seq(optional($.block_label), $.block),
|
||||
$.expression_statement,
|
||||
)),
|
||||
|
||||
block_expression: $ => prec(1, seq(optional($.block_label), $.block)),
|
||||
|
||||
labeled_statement: $ => prec(1, seq(
|
||||
optional($.block_label),
|
||||
choice($.block, $.for_statement, $.while_statement),
|
||||
)),
|
||||
|
||||
expression_statement: $ => seq($.expression, ';'),
|
||||
|
||||
if_statement: $ => seq(
|
||||
$._if_prefix,
|
||||
$._conditional_body,
|
||||
),
|
||||
|
||||
_if_prefix: $ => seq(
|
||||
'if',
|
||||
'(',
|
||||
field('condition', $.expression),
|
||||
')',
|
||||
optional($.payload),
|
||||
),
|
||||
|
||||
else_clause: $ => seq(
|
||||
'else',
|
||||
optional($.payload),
|
||||
field('alternative', $.statement),
|
||||
),
|
||||
|
||||
for_statement: $ => seq(
|
||||
optional('inline'),
|
||||
$._for_prefix,
|
||||
$._conditional_body,
|
||||
),
|
||||
|
||||
_for_prefix: $ => seq(
|
||||
'for',
|
||||
'(',
|
||||
optionalCommaSep(seq(
|
||||
$.expression,
|
||||
optional(seq('..', $.expression)),
|
||||
)),
|
||||
')',
|
||||
$.payload,
|
||||
),
|
||||
|
||||
while_statement: $ => seq(
|
||||
optional('inline'),
|
||||
$._while_prefix,
|
||||
$._conditional_body,
|
||||
),
|
||||
|
||||
_while_prefix: $ => seq(
|
||||
'while',
|
||||
'(',
|
||||
field('condition', $.expression),
|
||||
')',
|
||||
optional($.payload),
|
||||
optional(seq(':', '(', $.expression, ')')),
|
||||
),
|
||||
|
||||
_conditional_body: $ => choice(
|
||||
seq(
|
||||
field('body', $.block_expression),
|
||||
optional($.else_clause),
|
||||
),
|
||||
seq(
|
||||
field('body', $.expression),
|
||||
choice(';', $.else_clause),
|
||||
),
|
||||
),
|
||||
|
||||
payload: $ => seq('|', optionalCommaSep1(seq(optional('*'), $.identifier)), '|'),
|
||||
|
||||
byte_alignment: $ => seq('align', '(', $.expression, ')'),
|
||||
|
||||
address_space: $ => seq('addrspace', '(', $.expression, ')'),
|
||||
|
||||
link_section: $ => seq('linksection', '(', $.expression, ')'),
|
||||
|
||||
calling_convention: $ => seq('callconv', '(', $.expression, ')'),
|
||||
|
||||
expression: $ => prec.right(choice(
|
||||
$.asm_expression,
|
||||
$.if_expression,
|
||||
$.for_expression,
|
||||
$.while_expression,
|
||||
$.assignment_expression,
|
||||
$.unary_expression,
|
||||
$.binary_expression,
|
||||
$.comptime_expression,
|
||||
$.async_expression,
|
||||
$.await_expression,
|
||||
$.nosuspend_expression,
|
||||
$.continue_expression,
|
||||
$.resume_expression,
|
||||
$.return_expression,
|
||||
$.break_expression,
|
||||
$.try_expression,
|
||||
$.catch_expression,
|
||||
$.type_expression,
|
||||
$.block,
|
||||
)),
|
||||
|
||||
asm_expression: $ => seq(
|
||||
'asm',
|
||||
optional('volatile'),
|
||||
'(',
|
||||
$.expression,
|
||||
optional($.asm_output),
|
||||
')',
|
||||
),
|
||||
asm_output: $ => seq(':', optionalCommaSep($.asm_output_item), optional($.asm_input)),
|
||||
asm_output_item: $ => seq(
|
||||
'[',
|
||||
$.identifier,
|
||||
']',
|
||||
choice($.string, $.multiline_string),
|
||||
'(',
|
||||
choice(seq('->', $.type_expression), $.identifier),
|
||||
')',
|
||||
),
|
||||
asm_input: $ => seq(':', optionalCommaSep($.asm_input_item), optional($.asm_clobbers)),
|
||||
asm_input_item: $ => seq(
|
||||
'[',
|
||||
$.identifier,
|
||||
']',
|
||||
choice($.string, $.multiline_string),
|
||||
'(',
|
||||
$.expression,
|
||||
')',
|
||||
),
|
||||
asm_clobbers: $ => seq(':', optionalCommaSep(choice($.string, $.multiline_string))),
|
||||
|
||||
if_expression: $ => prec.right(seq(
|
||||
$._if_prefix,
|
||||
$.expression,
|
||||
optional(seq('else', optional($.payload), $.expression)),
|
||||
)),
|
||||
|
||||
for_expression: $ => prec.right(seq(
|
||||
optional($.block_label),
|
||||
optional('inline'),
|
||||
$._for_prefix,
|
||||
$.expression,
|
||||
optional(seq('else', $.expression)),
|
||||
)),
|
||||
|
||||
while_expression: $ => prec.right(seq(
|
||||
optional($.block_label),
|
||||
optional('inline'),
|
||||
$._while_prefix,
|
||||
$.expression,
|
||||
optional(seq('else', optional($.payload), $.expression)),
|
||||
)),
|
||||
|
||||
assignment_expression: $ => prec.right(seq(
|
||||
field('left', $.expression),
|
||||
field('operator', choice(
|
||||
'=', '*=', '*%=', '*|=', '/=', '%=',
|
||||
'+=', '+%=', '+|=', '-=', '-%=', '-|=',
|
||||
'<<=', '<<|=', '>>=', '&=', '^=', '|=',
|
||||
)),
|
||||
field('right', $.expression),
|
||||
)),
|
||||
|
||||
unary_expression: $ => prec.left(PREC.UNARY, seq(
|
||||
field('operator', choice('!', '~', '-', '-%', '&')),
|
||||
field('argument', $.expression),
|
||||
)),
|
||||
|
||||
binary_expression: $ => {
|
||||
const table = [
|
||||
['or', PREC.LOGICAL_OR],
|
||||
['and', PREC.LOGICAL_AND],
|
||||
['==', PREC.EQUAL],
|
||||
['!=', PREC.EQUAL],
|
||||
['>', PREC.EQUAL],
|
||||
['>=', PREC.EQUAL],
|
||||
['<=', PREC.EQUAL],
|
||||
['<', PREC.EQUAL],
|
||||
['&', PREC.BITWISE],
|
||||
['^', PREC.BITWISE],
|
||||
['|', PREC.BITWISE],
|
||||
['orelse', PREC.BITWISE],
|
||||
['<<', PREC.SHIFT],
|
||||
['>>', PREC.SHIFT],
|
||||
['<<|', PREC.SHIFT],
|
||||
['+', PREC.ADD],
|
||||
['-', PREC.ADD],
|
||||
['++', PREC.ADD],
|
||||
['+%', PREC.ADD],
|
||||
['-%', PREC.ADD],
|
||||
['+|', PREC.ADD],
|
||||
['-|', PREC.ADD],
|
||||
['*', PREC.MULTIPLY],
|
||||
['/', PREC.MULTIPLY],
|
||||
['%', PREC.MULTIPLY],
|
||||
['**', PREC.MULTIPLY],
|
||||
['*%', PREC.MULTIPLY],
|
||||
['*|', PREC.MULTIPLY],
|
||||
['||', PREC.MULTIPLY],
|
||||
];
|
||||
|
||||
return choice(...table.map(([operator, precedence]) => {
|
||||
return prec.left(precedence, seq(
|
||||
field('left', $.expression),
|
||||
// @ts-ignore
|
||||
field('operator', operator),
|
||||
field('right', $.expression),
|
||||
));
|
||||
}));
|
||||
},
|
||||
|
||||
comptime_expression: $ => prec.right(seq('comptime', $.expression)),
|
||||
|
||||
async_expression: $ => prec.right(seq('async', $.expression)),
|
||||
|
||||
await_expression: $ => prec.right(seq('await', $.expression)),
|
||||
|
||||
nosuspend_expression: $ => prec.right(seq('nosuspend', $.expression)),
|
||||
|
||||
continue_expression: $ => prec.right(seq(
|
||||
'continue',
|
||||
optional($.break_label),
|
||||
optional($.expression),
|
||||
)),
|
||||
|
||||
resume_expression: $ => prec.right(seq('resume', $.expression)),
|
||||
|
||||
return_expression: $ => prec.right(seq('return', optional($.expression))),
|
||||
|
||||
break_expression: $ => prec.right(seq(
|
||||
'break',
|
||||
optional($.break_label),
|
||||
optional($.expression),
|
||||
)),
|
||||
|
||||
try_expression: $ => prec.right(PREC.BITWISE, seq('try', $.expression)),
|
||||
|
||||
catch_expression: $ => prec.right(PREC.BITWISE, seq(
|
||||
$.expression,
|
||||
'catch',
|
||||
optional($.payload),
|
||||
$.expression,
|
||||
)),
|
||||
|
||||
switch_expression: $ => seq(
|
||||
optional($.block_label),
|
||||
'switch',
|
||||
'(', $.expression, ')',
|
||||
'{',
|
||||
optionalCommaSep($.switch_case),
|
||||
'}',
|
||||
),
|
||||
switch_case: $ => seq(
|
||||
$._switch_case_exp,
|
||||
'=>',
|
||||
optional($.payload),
|
||||
choice($.expression),
|
||||
),
|
||||
_switch_case_exp: $ => seq(
|
||||
optional('inline'),
|
||||
choice(
|
||||
optionalCommaSep1(seq($.expression, optional(seq('...', $.expression)))),
|
||||
'else',
|
||||
),
|
||||
),
|
||||
|
||||
type_expression: $ => prec.right(choice(
|
||||
$.anonymous_struct_initializer,
|
||||
$.struct_initializer,
|
||||
$.labeled_type_expression,
|
||||
$.error_set_declaration,
|
||||
$.parenthesized_expression,
|
||||
$.primary_type_expression,
|
||||
)),
|
||||
|
||||
primary_type_expression: $ => choice(
|
||||
$.nullable_type,
|
||||
$.anyframe_type,
|
||||
$.slice_type,
|
||||
$.pointer_type,
|
||||
$.array_type,
|
||||
$.error_union_type,
|
||||
$.builtin_function,
|
||||
$.character,
|
||||
$.field_expression,
|
||||
$.index_expression,
|
||||
$.dereference_expression,
|
||||
$.null_coercion_expression,
|
||||
$.range_expression,
|
||||
$.call_expression,
|
||||
prec.right(alias($._function_prototype, $.function_signature)),
|
||||
$.identifier,
|
||||
$.float,
|
||||
$.integer,
|
||||
$.boolean,
|
||||
$.error_type,
|
||||
'anyframe',
|
||||
'unreachable',
|
||||
'undefined',
|
||||
'null',
|
||||
$.string,
|
||||
$.multiline_string,
|
||||
$.builtin_type,
|
||||
$.struct_declaration,
|
||||
$.opaque_declaration,
|
||||
$.enum_declaration,
|
||||
$.union_declaration,
|
||||
$.switch_expression,
|
||||
),
|
||||
|
||||
nullable_type: $ => prec(1, seq(
|
||||
'?',
|
||||
choice($.type_expression, $.if_type_expression, $.comptime_type_expression),
|
||||
)),
|
||||
|
||||
anyframe_type: $ => prec(1, seq(
|
||||
'anyframe',
|
||||
'->',
|
||||
$.type_expression,
|
||||
)),
|
||||
|
||||
slice_type: $ => prec.right(1, seq(
|
||||
'[',
|
||||
optional(seq(
|
||||
':',
|
||||
field('sentinel', $.expression),
|
||||
)),
|
||||
']',
|
||||
repeat(choice(
|
||||
$.byte_alignment,
|
||||
$.address_space,
|
||||
'const',
|
||||
'volatile',
|
||||
'allowzero',
|
||||
)),
|
||||
$.type_expression,
|
||||
)),
|
||||
|
||||
pointer_type: $ => prec.right(1, seq(
|
||||
choice(
|
||||
'*',
|
||||
seq(
|
||||
'[',
|
||||
'*',
|
||||
optional(choice('c', seq(':', $.expression))),
|
||||
']',
|
||||
),
|
||||
),
|
||||
repeat(choice(
|
||||
$.address_space,
|
||||
seq(
|
||||
'align',
|
||||
'(',
|
||||
$.expression,
|
||||
optional(seq(':', $.expression, ':', $.expression)),
|
||||
')',
|
||||
),
|
||||
'const',
|
||||
'volatile',
|
||||
'allowzero',
|
||||
)),
|
||||
$.type_expression,
|
||||
)),
|
||||
|
||||
array_type: $ => prec(1, seq(
|
||||
'[',
|
||||
$.expression,
|
||||
optional(seq(':', $.expression)),
|
||||
']',
|
||||
$.type_expression,
|
||||
)),
|
||||
|
||||
error_union_type: $ => prec.right(2, seq(
|
||||
optional(field('error', $.type_expression)),
|
||||
'!',
|
||||
field('ok', $.type_expression),
|
||||
)),
|
||||
|
||||
field_expression: $ => prec(PREC.MEMBER, seq(
|
||||
optional(field('object', $.expression)),
|
||||
'.',
|
||||
field('member', $.identifier),
|
||||
)),
|
||||
|
||||
index_expression: $ => prec(PREC.MEMBER, seq(
|
||||
field('object', $.expression),
|
||||
'[',
|
||||
field('index', $.expression),
|
||||
optional(seq(':', field('sentinel', $.expression))),
|
||||
']',
|
||||
)),
|
||||
|
||||
dereference_expression: $ => prec(PREC.MEMBER, seq($.expression, '.*')),
|
||||
|
||||
null_coercion_expression: $ => prec(PREC.MEMBER, seq($.expression, '.?')),
|
||||
|
||||
range_expression: $ => prec.right(PREC.MEMBER, seq(
|
||||
field('left', $.expression),
|
||||
'..',
|
||||
optional(field('right', $.expression)),
|
||||
)),
|
||||
|
||||
call_expression: $ => prec(PREC.MEMBER, seq(
|
||||
field('function', $.expression),
|
||||
'(',
|
||||
optionalCommaSep($.expression),
|
||||
')',
|
||||
)),
|
||||
|
||||
anonymous_struct_initializer: $ => seq('.', $.initializer_list),
|
||||
|
||||
struct_initializer: $ => prec(-1, seq($.primary_type_expression, $.initializer_list)),
|
||||
|
||||
initializer_list: $ => seq(
|
||||
'{',
|
||||
choice(
|
||||
optionalCommaSep($.field_initializer),
|
||||
optionalCommaSep($.expression),
|
||||
),
|
||||
'}',
|
||||
),
|
||||
|
||||
field_initializer: $ => seq(
|
||||
'.',
|
||||
$.identifier,
|
||||
'=',
|
||||
$.expression,
|
||||
),
|
||||
|
||||
labeled_type_expression: $ => seq($.block_label, $.block),
|
||||
|
||||
comptime_type_expression: $ => seq('comptime', $.type_expression),
|
||||
|
||||
if_type_expression: $ => prec.right(seq(
|
||||
$._if_prefix,
|
||||
$.type_expression,
|
||||
optional(seq('else', optional($.payload), $.type_expression)),
|
||||
)),
|
||||
|
||||
parenthesized_expression: $ => seq('(', $.expression, ')'),
|
||||
|
||||
block_label: $ => prec(-1, seq(
|
||||
choice($.identifier, alias($.builtin_type, $.identifier)),
|
||||
':',
|
||||
)),
|
||||
break_label: $ => seq(':', $.identifier),
|
||||
|
||||
arguments: $ => seq('(', optionalCommaSep($.expression), ')'),
|
||||
|
||||
builtin_function: $ => seq(
|
||||
$.builtin_identifier,
|
||||
$.arguments,
|
||||
),
|
||||
|
||||
string: $ => seq(
|
||||
'"',
|
||||
repeat(choice(
|
||||
alias(token.immediate(prec(1, /[^\\"\n]+/)), $.string_content),
|
||||
$.escape_sequence,
|
||||
)),
|
||||
'"',
|
||||
),
|
||||
|
||||
multiline_string: _ => prec.right(repeat1(token(seq('\\\\', /[^\n]*/)))),
|
||||
|
||||
escape_sequence: _ => token(prec(1, seq(
|
||||
'\\',
|
||||
choice(
|
||||
/[^xuU]/,
|
||||
/\d{2,3}/,
|
||||
/x[0-9a-fA-F]{2,}/,
|
||||
/u\{[0-9a-fA-F]{1,6}\}/,
|
||||
),
|
||||
))),
|
||||
|
||||
character: $ => seq(
|
||||
'\'',
|
||||
choice(
|
||||
alias(/[^'\n]/, $.character_content),
|
||||
$.escape_sequence,
|
||||
),
|
||||
'\'',
|
||||
),
|
||||
|
||||
integer: _ => {
|
||||
const separator = '_';
|
||||
const hex = /[0-9A-Fa-f]/;
|
||||
const oct = /[0-7]/;
|
||||
const bin = /[0-1]/;
|
||||
const decimal = /[0-9]/;
|
||||
const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
|
||||
const octDigits = seq(repeat1(oct), repeat(seq(separator, repeat1(oct))));
|
||||
const binDigits = seq(repeat1(bin), repeat(seq(separator, repeat1(bin))));
|
||||
const decimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
|
||||
|
||||
return token(choice(
|
||||
seq('0x', hexDigits),
|
||||
seq('0o', octDigits),
|
||||
seq('0b', binDigits),
|
||||
decimalDigits,
|
||||
));
|
||||
},
|
||||
|
||||
float: _ => {
|
||||
const separator = '_';
|
||||
const hex = /[0-9A-Fa-f]/;
|
||||
const decimal = /[0-9]/;
|
||||
const hexDigits = seq(repeat1(hex), repeat(seq(separator, repeat1(hex))));
|
||||
const decimalDigits = seq(repeat1(decimal), repeat(seq(separator, repeat1(decimal))));
|
||||
|
||||
return token(choice(
|
||||
seq('0x', hexDigits, '.', hexDigits, optional(seq(/[pP][+-]?/, decimalDigits))),
|
||||
seq(decimalDigits, '.', decimalDigits, optional(seq(/[eE][+-]?/, decimalDigits))),
|
||||
seq('0x', hexDigits, /[pP][+-]?/, decimalDigits),
|
||||
seq(decimalDigits, /[eE][+-]?/, decimalDigits),
|
||||
));
|
||||
},
|
||||
|
||||
boolean: _ => choice('true', 'false'),
|
||||
|
||||
builtin_type: _ => choice(...builtinTypes),
|
||||
|
||||
error_type: $ => seq('error', '.', $.identifier),
|
||||
|
||||
builtin_identifier: _ => /@[A-Za-z_][A-Za-z0-9_]*/,
|
||||
|
||||
identifier: $ => choice($._identifier, seq('@', $.string)),
|
||||
_identifier: _ => /[A-Za-z_][A-Za-z0-9_]*/,
|
||||
_reserved_identifier: _ => choice(
|
||||
'undefined',
|
||||
'null',
|
||||
'true',
|
||||
'false',
|
||||
),
|
||||
|
||||
comment: _ => token(seq('//', /.*/)),
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a rule to match optionally match one or more of the rules
|
||||
* separated by a comma and optionally ending with a comma
|
||||
*
|
||||
* @param {RuleOrLiteral} rule
|
||||
*
|
||||
* @returns {ChoiceRule}
|
||||
*/
|
||||
function optionalCommaSep(rule) {
|
||||
return optional(optionalCommaSep1(rule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a rule to match one or more of the rules separated by a comma
|
||||
* and optionally ending with a comma
|
||||
*
|
||||
* @param {RuleOrLiteral} rule
|
||||
*
|
||||
* @returns {SeqRule}
|
||||
*/
|
||||
function optionalCommaSep1(rule) {
|
||||
return seq(commaSep1(rule), optional(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a rule to match one or more of the rules separated by a comma
|
||||
*
|
||||
* @param {RuleOrLiteral} rule
|
||||
*
|
||||
* @returns {SeqRule}
|
||||
*/
|
||||
function commaSep1(rule) {
|
||||
return seq(rule, repeat(seq(',', rule)));
|
||||
}
|
||||
18
gitnexus/vendor/tree-sitter-zig/package.json
vendored
Normal file
18
gitnexus/vendor/tree-sitter-zig/package.json
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "tree-sitter-zig",
|
||||
"version": "1.1.2",
|
||||
"description": "Zig grammar for tree-sitter",
|
||||
"repository": "https://github.com/tree-sitter-grammars/tree-sitter-zig",
|
||||
"license": "MIT",
|
||||
"main": "bindings/node/index.js",
|
||||
"types": "bindings/node/index.d.ts",
|
||||
"_vendoredBy": "gitnexus - runtime package derived from @tree-sitter-grammars/tree-sitter-zig@1.1.2 (ABI 14). Vendored so `npm i -g gitnexus` no longer hits peerOptional tree-sitter@^0.22.1 against the bundled tree-sitter@0.21.1 (npm overrides on a published package are ignored by dependents). Loaded from vendor/ by absolute path at runtime (vendored-grammars.ts) — NEVER copied to node_modules (#2111). No scripts/dependencies here (#836/#1728). Upstream linux-arm64 prebuild is a mispackaged x86-64 binary and is omitted; GitNexus-cross-built prebuilds come from .github/workflows/build-tree-sitter-prebuilds.yml (regenerated whenever this `version` changes). To re-pin: bump `version`, refresh src/ + bindings/node/ from the new npm tarball, update this note, and let the prebuild workflow rebuild the binaries.",
|
||||
"peerDependencies": {
|
||||
"tree-sitter": "^0.21.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"tree-sitter": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
5
gitnexus/vendor/tree-sitter-zig/prebuilds/SHA256SUMS
vendored
Normal file
5
gitnexus/vendor/tree-sitter-zig/prebuilds/SHA256SUMS
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
2a4b19adc1f720cded08f46c88c59c38e69e617c6eb9451ae9afde4b693fdfd1 ./darwin-arm64/tree-sitter-zig.node
|
||||
937fe3253813330321f3d8465eede29bbf502d35778be373ef20022f17c1bc26 ./darwin-x64/tree-sitter-zig.node
|
||||
f9083793d6958123cae11e074f2950f922826aea5bdbda5e98772eb73fd83d97 ./linux-x64/tree-sitter-zig.node
|
||||
861974d072d2fc4dfdb42d56da9fd72c798bafcde541c8a7df3e0a013ca2e99e ./win32-arm64/tree-sitter-zig.node
|
||||
6a6575e039ff0043f4c0ba5567444ac1c602082ad7546d54595105bc33555145 ./win32-x64/tree-sitter-zig.node
|
||||
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/darwin-arm64/tree-sitter-zig.node
vendored
Normal file
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/darwin-arm64/tree-sitter-zig.node
vendored
Normal file
Binary file not shown.
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/darwin-x64/tree-sitter-zig.node
vendored
Normal file
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/darwin-x64/tree-sitter-zig.node
vendored
Normal file
Binary file not shown.
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/linux-x64/tree-sitter-zig.node
vendored
Normal file
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/linux-x64/tree-sitter-zig.node
vendored
Normal file
Binary file not shown.
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/win32-arm64/tree-sitter-zig.node
vendored
Normal file
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/win32-arm64/tree-sitter-zig.node
vendored
Normal file
Binary file not shown.
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/win32-x64/tree-sitter-zig.node
vendored
Normal file
BIN
gitnexus/vendor/tree-sitter-zig/prebuilds/win32-x64/tree-sitter-zig.node
vendored
Normal file
Binary file not shown.
6570
gitnexus/vendor/tree-sitter-zig/src/grammar.json
vendored
Normal file
6570
gitnexus/vendor/tree-sitter-zig/src/grammar.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
3178
gitnexus/vendor/tree-sitter-zig/src/node-types.json
vendored
Normal file
3178
gitnexus/vendor/tree-sitter-zig/src/node-types.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
169829
gitnexus/vendor/tree-sitter-zig/src/parser.c
vendored
Normal file
169829
gitnexus/vendor/tree-sitter-zig/src/parser.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
54
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/alloc.h
vendored
Normal file
54
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/alloc.h
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef TREE_SITTER_ALLOC_H_
|
||||
#define TREE_SITTER_ALLOC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Allow clients to override allocation functions
|
||||
#ifdef TREE_SITTER_REUSE_ALLOCATOR
|
||||
|
||||
extern void *(*ts_current_malloc)(size_t size);
|
||||
extern void *(*ts_current_calloc)(size_t count, size_t size);
|
||||
extern void *(*ts_current_realloc)(void *ptr, size_t size);
|
||||
extern void (*ts_current_free)(void *ptr);
|
||||
|
||||
#ifndef ts_malloc
|
||||
#define ts_malloc ts_current_malloc
|
||||
#endif
|
||||
#ifndef ts_calloc
|
||||
#define ts_calloc ts_current_calloc
|
||||
#endif
|
||||
#ifndef ts_realloc
|
||||
#define ts_realloc ts_current_realloc
|
||||
#endif
|
||||
#ifndef ts_free
|
||||
#define ts_free ts_current_free
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef ts_malloc
|
||||
#define ts_malloc malloc
|
||||
#endif
|
||||
#ifndef ts_calloc
|
||||
#define ts_calloc calloc
|
||||
#endif
|
||||
#ifndef ts_realloc
|
||||
#define ts_realloc realloc
|
||||
#endif
|
||||
#ifndef ts_free
|
||||
#define ts_free free
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_ALLOC_H_
|
||||
291
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/array.h
vendored
Normal file
291
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/array.h
vendored
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
#ifndef TREE_SITTER_ARRAY_H_
|
||||
#define TREE_SITTER_ARRAY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "./alloc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4101)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
|
||||
#define Array(T) \
|
||||
struct { \
|
||||
T *contents; \
|
||||
uint32_t size; \
|
||||
uint32_t capacity; \
|
||||
}
|
||||
|
||||
/// Initialize an array.
|
||||
#define array_init(self) \
|
||||
((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
|
||||
|
||||
/// Create an empty array.
|
||||
#define array_new() \
|
||||
{ NULL, 0, 0 }
|
||||
|
||||
/// Get a pointer to the element at a given `index` in the array.
|
||||
#define array_get(self, _index) \
|
||||
(assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])
|
||||
|
||||
/// Get a pointer to the first element in the array.
|
||||
#define array_front(self) array_get(self, 0)
|
||||
|
||||
/// Get a pointer to the last element in the array.
|
||||
#define array_back(self) array_get(self, (self)->size - 1)
|
||||
|
||||
/// Clear the array, setting its size to zero. Note that this does not free any
|
||||
/// memory allocated for the array's contents.
|
||||
#define array_clear(self) ((self)->size = 0)
|
||||
|
||||
/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
|
||||
/// less than the array's current capacity, this function has no effect.
|
||||
#define array_reserve(self, new_capacity) \
|
||||
_array__reserve((Array *)(self), array_elem_size(self), new_capacity)
|
||||
|
||||
/// Free any memory allocated for this array. Note that this does not free any
|
||||
/// memory allocated for the array's contents.
|
||||
#define array_delete(self) _array__delete((Array *)(self))
|
||||
|
||||
/// Push a new `element` onto the end of the array.
|
||||
#define array_push(self, element) \
|
||||
(_array__grow((Array *)(self), 1, array_elem_size(self)), \
|
||||
(self)->contents[(self)->size++] = (element))
|
||||
|
||||
/// Increase the array's size by `count` elements.
|
||||
/// New elements are zero-initialized.
|
||||
#define array_grow_by(self, count) \
|
||||
do { \
|
||||
if ((count) == 0) break; \
|
||||
_array__grow((Array *)(self), count, array_elem_size(self)); \
|
||||
memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
|
||||
(self)->size += (count); \
|
||||
} while (0)
|
||||
|
||||
/// Append all elements from one array to the end of another.
|
||||
#define array_push_all(self, other) \
|
||||
array_extend((self), (other)->size, (other)->contents)
|
||||
|
||||
/// Append `count` elements to the end of the array, reading their values from the
|
||||
/// `contents` pointer.
|
||||
#define array_extend(self, count, contents) \
|
||||
_array__splice( \
|
||||
(Array *)(self), array_elem_size(self), (self)->size, \
|
||||
0, count, contents \
|
||||
)
|
||||
|
||||
/// Remove `old_count` elements from the array starting at the given `index`. At
|
||||
/// the same index, insert `new_count` new elements, reading their values from the
|
||||
/// `new_contents` pointer.
|
||||
#define array_splice(self, _index, old_count, new_count, new_contents) \
|
||||
_array__splice( \
|
||||
(Array *)(self), array_elem_size(self), _index, \
|
||||
old_count, new_count, new_contents \
|
||||
)
|
||||
|
||||
/// Insert one `element` into the array at the given `index`.
|
||||
#define array_insert(self, _index, element) \
|
||||
_array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
|
||||
|
||||
/// Remove one element from the array at the given `index`.
|
||||
#define array_erase(self, _index) \
|
||||
_array__erase((Array *)(self), array_elem_size(self), _index)
|
||||
|
||||
/// Pop the last element off the array, returning the element by value.
|
||||
#define array_pop(self) ((self)->contents[--(self)->size])
|
||||
|
||||
/// Assign the contents of one array to another, reallocating if necessary.
|
||||
#define array_assign(self, other) \
|
||||
_array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
|
||||
|
||||
/// Swap one array with another
|
||||
#define array_swap(self, other) \
|
||||
_array__swap((Array *)(self), (Array *)(other))
|
||||
|
||||
/// Get the size of the array contents
|
||||
#define array_elem_size(self) (sizeof *(self)->contents)
|
||||
|
||||
/// Search a sorted array for a given `needle` value, using the given `compare`
|
||||
/// callback to determine the order.
|
||||
///
|
||||
/// If an existing element is found to be equal to `needle`, then the `index`
|
||||
/// out-parameter is set to the existing value's index, and the `exists`
|
||||
/// out-parameter is set to true. Otherwise, `index` is set to an index where
|
||||
/// `needle` should be inserted in order to preserve the sorting, and `exists`
|
||||
/// is set to false.
|
||||
#define array_search_sorted_with(self, compare, needle, _index, _exists) \
|
||||
_array__search_sorted(self, 0, compare, , needle, _index, _exists)
|
||||
|
||||
/// Search a sorted array for a given `needle` value, using integer comparisons
|
||||
/// of a given struct field (specified with a leading dot) to determine the order.
|
||||
///
|
||||
/// See also `array_search_sorted_with`.
|
||||
#define array_search_sorted_by(self, field, needle, _index, _exists) \
|
||||
_array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)
|
||||
|
||||
/// Insert a given `value` into a sorted array, using the given `compare`
|
||||
/// callback to determine the order.
|
||||
#define array_insert_sorted_with(self, compare, value) \
|
||||
do { \
|
||||
unsigned _index, _exists; \
|
||||
array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
|
||||
if (!_exists) array_insert(self, _index, value); \
|
||||
} while (0)
|
||||
|
||||
/// Insert a given `value` into a sorted array, using integer comparisons of
|
||||
/// a given struct field (specified with a leading dot) to determine the order.
|
||||
///
|
||||
/// See also `array_search_sorted_by`.
|
||||
#define array_insert_sorted_by(self, field, value) \
|
||||
do { \
|
||||
unsigned _index, _exists; \
|
||||
array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
|
||||
if (!_exists) array_insert(self, _index, value); \
|
||||
} while (0)
|
||||
|
||||
// Private
|
||||
|
||||
typedef Array(void) Array;
|
||||
|
||||
/// This is not what you're looking for, see `array_delete`.
|
||||
static inline void _array__delete(Array *self) {
|
||||
if (self->contents) {
|
||||
ts_free(self->contents);
|
||||
self->contents = NULL;
|
||||
self->size = 0;
|
||||
self->capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_erase`.
|
||||
static inline void _array__erase(Array *self, size_t element_size,
|
||||
uint32_t index) {
|
||||
assert(index < self->size);
|
||||
char *contents = (char *)self->contents;
|
||||
memmove(contents + index * element_size, contents + (index + 1) * element_size,
|
||||
(self->size - index - 1) * element_size);
|
||||
self->size--;
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_reserve`.
|
||||
static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
|
||||
if (new_capacity > self->capacity) {
|
||||
if (self->contents) {
|
||||
self->contents = ts_realloc(self->contents, new_capacity * element_size);
|
||||
} else {
|
||||
self->contents = ts_malloc(new_capacity * element_size);
|
||||
}
|
||||
self->capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_assign`.
|
||||
static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
|
||||
_array__reserve(self, element_size, other->size);
|
||||
self->size = other->size;
|
||||
memcpy(self->contents, other->contents, self->size * element_size);
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_swap`.
|
||||
static inline void _array__swap(Array *self, Array *other) {
|
||||
Array swap = *other;
|
||||
*other = *self;
|
||||
*self = swap;
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_push` or `array_grow_by`.
|
||||
static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
|
||||
uint32_t new_size = self->size + count;
|
||||
if (new_size > self->capacity) {
|
||||
uint32_t new_capacity = self->capacity * 2;
|
||||
if (new_capacity < 8) new_capacity = 8;
|
||||
if (new_capacity < new_size) new_capacity = new_size;
|
||||
_array__reserve(self, element_size, new_capacity);
|
||||
}
|
||||
}
|
||||
|
||||
/// This is not what you're looking for, see `array_splice`.
|
||||
static inline void _array__splice(Array *self, size_t element_size,
|
||||
uint32_t index, uint32_t old_count,
|
||||
uint32_t new_count, const void *elements) {
|
||||
uint32_t new_size = self->size + new_count - old_count;
|
||||
uint32_t old_end = index + old_count;
|
||||
uint32_t new_end = index + new_count;
|
||||
assert(old_end <= self->size);
|
||||
|
||||
_array__reserve(self, element_size, new_size);
|
||||
|
||||
char *contents = (char *)self->contents;
|
||||
if (self->size > old_end) {
|
||||
memmove(
|
||||
contents + new_end * element_size,
|
||||
contents + old_end * element_size,
|
||||
(self->size - old_end) * element_size
|
||||
);
|
||||
}
|
||||
if (new_count > 0) {
|
||||
if (elements) {
|
||||
memcpy(
|
||||
(contents + index * element_size),
|
||||
elements,
|
||||
new_count * element_size
|
||||
);
|
||||
} else {
|
||||
memset(
|
||||
(contents + index * element_size),
|
||||
0,
|
||||
new_count * element_size
|
||||
);
|
||||
}
|
||||
}
|
||||
self->size += new_count - old_count;
|
||||
}
|
||||
|
||||
/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
|
||||
/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
|
||||
#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
|
||||
do { \
|
||||
*(_index) = start; \
|
||||
*(_exists) = false; \
|
||||
uint32_t size = (self)->size - *(_index); \
|
||||
if (size == 0) break; \
|
||||
int comparison; \
|
||||
while (size > 1) { \
|
||||
uint32_t half_size = size / 2; \
|
||||
uint32_t mid_index = *(_index) + half_size; \
|
||||
comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
|
||||
if (comparison <= 0) *(_index) = mid_index; \
|
||||
size -= half_size; \
|
||||
} \
|
||||
comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
|
||||
if (comparison == 0) *(_exists) = true; \
|
||||
else if (comparison < 0) *(_index) += 1; \
|
||||
} while (0)
|
||||
|
||||
/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
|
||||
/// parameter by reference in order to work with the generic sorting function above.
|
||||
#define _compare_int(a, b) ((int)*(a) - (int)(b))
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_ARRAY_H_
|
||||
266
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/parser.h
vendored
Normal file
266
gitnexus/vendor/tree-sitter-zig/src/tree_sitter/parser.h
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
#ifndef TREE_SITTER_PARSER_H_
|
||||
#define TREE_SITTER_PARSER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||
#define ts_builtin_sym_end 0
|
||||
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||
|
||||
#ifndef TREE_SITTER_API_H_
|
||||
typedef uint16_t TSStateId;
|
||||
typedef uint16_t TSSymbol;
|
||||
typedef uint16_t TSFieldId;
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TSFieldId field_id;
|
||||
uint8_t child_index;
|
||||
bool inherited;
|
||||
} TSFieldMapEntry;
|
||||
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} TSFieldMapSlice;
|
||||
|
||||
typedef struct {
|
||||
bool visible;
|
||||
bool named;
|
||||
bool supertype;
|
||||
} TSSymbolMetadata;
|
||||
|
||||
typedef struct TSLexer TSLexer;
|
||||
|
||||
struct TSLexer {
|
||||
int32_t lookahead;
|
||||
TSSymbol result_symbol;
|
||||
void (*advance)(TSLexer *, bool);
|
||||
void (*mark_end)(TSLexer *);
|
||||
uint32_t (*get_column)(TSLexer *);
|
||||
bool (*is_at_included_range_start)(const TSLexer *);
|
||||
bool (*eof)(const TSLexer *);
|
||||
void (*log)(const TSLexer *, const char *, ...);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TSParseActionTypeShift,
|
||||
TSParseActionTypeReduce,
|
||||
TSParseActionTypeAccept,
|
||||
TSParseActionTypeRecover,
|
||||
} TSParseActionType;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t type;
|
||||
TSStateId state;
|
||||
bool extra;
|
||||
bool repetition;
|
||||
} shift;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t child_count;
|
||||
TSSymbol symbol;
|
||||
int16_t dynamic_precedence;
|
||||
uint16_t production_id;
|
||||
} reduce;
|
||||
uint8_t type;
|
||||
} TSParseAction;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lex_state;
|
||||
uint16_t external_lex_state;
|
||||
} TSLexMode;
|
||||
|
||||
typedef union {
|
||||
TSParseAction action;
|
||||
struct {
|
||||
uint8_t count;
|
||||
bool reusable;
|
||||
} entry;
|
||||
} TSParseActionEntry;
|
||||
|
||||
typedef struct {
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
} TSCharacterRange;
|
||||
|
||||
struct TSLanguage {
|
||||
uint32_t version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
uint32_t external_token_count;
|
||||
uint32_t state_count;
|
||||
uint32_t large_state_count;
|
||||
uint32_t production_id_count;
|
||||
uint32_t field_count;
|
||||
uint16_t max_alias_sequence_length;
|
||||
const uint16_t *parse_table;
|
||||
const uint16_t *small_parse_table;
|
||||
const uint32_t *small_parse_table_map;
|
||||
const TSParseActionEntry *parse_actions;
|
||||
const char * const *symbol_names;
|
||||
const char * const *field_names;
|
||||
const TSFieldMapSlice *field_map_slices;
|
||||
const TSFieldMapEntry *field_map_entries;
|
||||
const TSSymbolMetadata *symbol_metadata;
|
||||
const TSSymbol *public_symbol_map;
|
||||
const uint16_t *alias_map;
|
||||
const TSSymbol *alias_sequences;
|
||||
const TSLexMode *lex_modes;
|
||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||
TSSymbol keyword_capture_token;
|
||||
struct {
|
||||
const bool *states;
|
||||
const TSSymbol *symbol_map;
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *);
|
||||
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
||||
unsigned (*serialize)(void *, char *);
|
||||
void (*deserialize)(void *, const char *, unsigned);
|
||||
} external_scanner;
|
||||
const TSStateId *primary_state_ids;
|
||||
};
|
||||
|
||||
static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
|
||||
uint32_t index = 0;
|
||||
uint32_t size = len - index;
|
||||
while (size > 1) {
|
||||
uint32_t half_size = size / 2;
|
||||
uint32_t mid_index = index + half_size;
|
||||
TSCharacterRange *range = &ranges[mid_index];
|
||||
if (lookahead >= range->start && lookahead <= range->end) {
|
||||
return true;
|
||||
} else if (lookahead > range->end) {
|
||||
index = mid_index;
|
||||
}
|
||||
size -= half_size;
|
||||
}
|
||||
TSCharacterRange *range = &ranges[index];
|
||||
return (lookahead >= range->start && lookahead <= range->end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lexer Macros
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define UNUSED __pragma(warning(suppress : 4101))
|
||||
#else
|
||||
#define UNUSED __attribute__((unused))
|
||||
#endif
|
||||
|
||||
#define START_LEXER() \
|
||||
bool result = false; \
|
||||
bool skip = false; \
|
||||
UNUSED \
|
||||
bool eof = false; \
|
||||
int32_t lookahead; \
|
||||
goto start; \
|
||||
next_state: \
|
||||
lexer->advance(lexer, skip); \
|
||||
start: \
|
||||
skip = false; \
|
||||
lookahead = lexer->lookahead;
|
||||
|
||||
#define ADVANCE(state_value) \
|
||||
{ \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ADVANCE_MAP(...) \
|
||||
{ \
|
||||
static const uint16_t map[] = { __VA_ARGS__ }; \
|
||||
for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \
|
||||
if (map[i] == lookahead) { \
|
||||
state = map[i + 1]; \
|
||||
goto next_state; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SKIP(state_value) \
|
||||
{ \
|
||||
skip = true; \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ACCEPT_TOKEN(symbol_value) \
|
||||
result = true; \
|
||||
lexer->result_symbol = symbol_value; \
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
#define END_STATE() return result;
|
||||
|
||||
/*
|
||||
* Parse Table Macros
|
||||
*/
|
||||
|
||||
#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)
|
||||
|
||||
#define STATE(id) id
|
||||
|
||||
#define ACTIONS(id) id
|
||||
|
||||
#define SHIFT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = (state_value) \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_REPEAT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = (state_value), \
|
||||
.repetition = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_EXTRA() \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.extra = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define REDUCE(symbol_name, children, precedence, prod_id) \
|
||||
{{ \
|
||||
.reduce = { \
|
||||
.type = TSParseActionTypeReduce, \
|
||||
.symbol = symbol_name, \
|
||||
.child_count = children, \
|
||||
.dynamic_precedence = precedence, \
|
||||
.production_id = prod_id \
|
||||
}, \
|
||||
}}
|
||||
|
||||
#define RECOVER() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeRecover \
|
||||
}}
|
||||
|
||||
#define ACCEPT_INPUT() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeAccept \
|
||||
}}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_PARSER_H_
|
||||
Loading…
Add table
Reference in a new issue