Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The core runtime headers in `internal/cbm/vendored/common/tree_sitter/`

## Tree-sitter Grammars

159 pre-generated parsers are vendored in `internal/cbm/vendored/grammars/<lang>/`
160 pre-generated parsers are vendored in `internal/cbm/vendored/grammars/<lang>/`
(generated `parser.c` plus `scanner.c` where applicable, compiled statically).
Each grammar is the work of its upstream authors and each grammar directory
contains the upstream `LICENSE` file.
Expand Down
1 change: 1 addition & 0 deletions internal/cbm/cbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ typedef enum {
CBM_LANG_CFSCRIPT, // CFML script dialect (.cfc components — Lucee/ColdFusion)
CBM_LANG_CFML, // CFML tag dialect (.cfm templates — Lucee/ColdFusion)
CBM_LANG_MOJO, // Mojo
CBM_LANG_PLSQL, // Oracle PL/SQL
CBM_LANG_COUNT
} CBMLanguage;

Expand Down
29 changes: 29 additions & 0 deletions internal/cbm/extract_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,32 @@ static char *extract_ada_callee(CBMArena *a, TSNode node, const char *source, co
return NULL;
}

/* PL/SQL: ref_call → referenced_element. Package-qualified calls use
* ref_name_parent.ref_name (e.g. UTIL_PKG.CALC_SALARY); bare calls use
* ref_name alone. */
static char *extract_plsql_callee(CBMArena *a, TSNode node, const char *source, const char *nk) {
if (strcmp(nk, "ref_call") != 0) {
return NULL;
}
TSNode ref = cbm_find_child_by_kind(node, "referenced_element");
if (ts_node_is_null(ref)) {
return NULL;
}
TSNode parent = ts_node_child_by_field_name(ref, TS_FIELD("ref_name_parent"));
TSNode name = ts_node_child_by_field_name(ref, TS_FIELD("ref_name"));
if (!ts_node_is_null(parent) && !ts_node_is_null(name)) {
char *p = cbm_node_text(a, parent, source);
char *n = cbm_node_text(a, name, source);
if (p && n && p[0] && n[0]) {
return cbm_arena_sprintf(a, "%s.%s", p, n);
}
}
if (!ts_node_is_null(name)) {
return cbm_node_text(a, name, source);
}
return cbm_node_text(a, ref, source);
}

// Solidity: a call_expression's callee is on the `function` field, wrapped in an
// `expression` node (call_expression -> function:expression -> identifier). Descend
// left-most through expression wrappers until we reach the identifier/member.
Expand Down Expand Up @@ -1073,6 +1099,9 @@ static char *extract_callee_lang_specific(CBMArena *a, TSNode node, const char *
if (lang == CBM_LANG_ADA) {
return extract_ada_callee(a, node, source, nk);
}
if (lang == CBM_LANG_PLSQL) {
return extract_plsql_callee(a, node, source, nk);
}
if (lang == CBM_LANG_SOLIDITY) {
return extract_solidity_callee(a, node, source, nk);
}
Expand Down
22 changes: 22 additions & 0 deletions internal/cbm/extract_defs.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,18 @@ TSNode cbm_resolve_func_name(TSNode node, CBMLanguage lang) {
}
}

/* PL/SQL: create_function / create_procedure / function_* / procedure_*
* carry fnc_name / prc_name, not the generic name field. */
if (lang == CBM_LANG_PLSQL) {
TSNode nm = ts_node_child_by_field_name(node, TS_FIELD("fnc_name"));
if (ts_node_is_null(nm)) {
nm = ts_node_child_by_field_name(node, TS_FIELD("prc_name"));
}
if (!ts_node_is_null(nm)) {
return nm;
}
}

/* Smali (no `name` field): method_definition > method_signature >
* method_identifier holds the method name. */
if (lang == CBM_LANG_SMALI && strcmp(kind, "method_definition") == 0) {
Expand Down Expand Up @@ -3634,6 +3646,16 @@ static void extract_class_def(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec
name_node = ts_node_child_by_field_name(node, TS_FIELD("type"));
}
}
// PL/SQL: package / type / trigger names use dedicated fields, not `name`.
if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_PLSQL) {
name_node = ts_node_child_by_field_name(node, TS_FIELD("package_name"));
if (ts_node_is_null(name_node)) {
name_node = ts_node_child_by_field_name(node, TS_FIELD("type_name"));
}
if (ts_node_is_null(name_node)) {
name_node = ts_node_child_by_field_name(node, TS_FIELD("trigger_name"));
}
}
// Verilog/SystemVerilog (FIELD_COUNT 0): module/class/interface/package use a
// nested simple_identifier (first descendant); type_declaration must use the
// DIRECT-child simple_identifier (member/enum idents precede the typedef name).
Expand Down
3 changes: 3 additions & 0 deletions internal/cbm/grammar_plsql.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Vendored tree-sitter grammar: plsql
// Each grammar compiled as separate unit (conflicting static symbols).
#include "vendored/grammars/plsql/parser.c"
29 changes: 29 additions & 0 deletions internal/cbm/lang_specs.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ extern const TSLanguage *tree_sitter_soql(void);
extern const TSLanguage *tree_sitter_sosl(void);
extern const TSLanguage *tree_sitter_pine(void);
extern const TSLanguage *tree_sitter_mojo(void);
extern const TSLanguage *tree_sitter_plsql(void);

// -- Empty sentinel --
static const char *empty_types[] = {NULL};
Expand Down Expand Up @@ -1612,6 +1613,28 @@ static const char *mojo_branch_types[] = {"if_statement",
NULL};
static const char *mojo_var_types[] = {"assignment", NULL};
static const char *mojo_assign_types[] = {"assignment", "augmented_assignment", NULL};
// ==================== PL/SQL ====================
// Node names verified against AndreasMaierDe/tree-sitter-plsql grammar.js.
static const char *plsql_func_types[] = {"create_function",
"create_procedure",
"function_definition",
"procedure_definition",
"function_declaration",
"procedure_declaration",
NULL};
static const char *plsql_class_types[] = {"create_package", "create_package_body", "create_type",
"create_type_body", "create_trigger", NULL};
static const char *plsql_module_types[] = {"source_file", NULL};
static const char *plsql_call_types[] = {"ref_call", NULL};
static const char *plsql_branch_types[] = {"if_statement",
"case_statement",
"basic_loop_statement",
"for_loop_statement",
"while_loop_statement",
"exception_handler",
NULL};
static const char *plsql_assign_types[] = {"assignment_statement", NULL};
static const char *plsql_throw_types[] = {"raise_statement", NULL};
// ==================== SPEC TABLE ====================

static const CBMLangSpec lang_specs[CBM_LANG_COUNT] = {
Expand Down Expand Up @@ -2593,6 +2616,12 @@ static const CBMLangSpec lang_specs[CBM_LANG_COUNT] = {
mojo_branch_types, mojo_var_types, mojo_assign_types, empty_types, NULL,
empty_types, NULL, NULL, tree_sitter_mojo, NULL},

// CBM_LANG_PLSQL — Oracle PL/SQL. AndreasMaierDe/tree-sitter-plsql (MIT).
[CBM_LANG_PLSQL] = {CBM_LANG_PLSQL, plsql_func_types, plsql_class_types, empty_types,
plsql_module_types, plsql_call_types, empty_types, empty_types,
plsql_branch_types, empty_types, plsql_assign_types, plsql_throw_types,
NULL, empty_types, NULL, NULL, tree_sitter_plsql, NULL},

};

_Static_assert(sizeof(lang_specs) / sizeof(lang_specs[0]) == CBM_LANG_COUNT,
Expand Down
10 changes: 7 additions & 3 deletions internal/cbm/vendored/grammars/MANIFEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ The grammars were originally vendored as bare `parser.c`+`scanner.c` with **no r

## Summary

- Grammars: **159** — vendored-from-upstream: **142**, first-party/self-maintained: **12**, registry-disagreement: **5** (nim removed 2026-06-12; objectscript_udl + objectscript_routine added 2026-06-24; mojo added 2026-07-01 — see notes below)
- ABI distribution: **7×** ABI-13 **85×** ABI-14 **64×** ABI-15 (runtime ceiling is ABI 15; never vendor ABI 16 without a runtime upgrade)
- Grammars: **160** — vendored-from-upstream: **143**, first-party/self-maintained: **12**, registry-disagreement: **5** (nim removed 2026-06-12; objectscript_udl + objectscript_routine added 2026-06-24; mojo added 2026-07-01; plsql added 2026-07-11 — see notes below)
- ABI distribution: **7×** ABI-13 **86×** ABI-14 **64×** ABI-15 (runtime ceiling is ABI 15; never vendor ABI 16 without a runtime upgrade)
- Vendored copies missing LICENSE: **0** — all upstream LICENSE files restored 2026-06-11 (first-party grammars carry the project MIT license; `move` uses the Helix-listed upstream tzakian/tree-sitter-move MIT text, `zsh` uses georgeharker/tree-sitter-zsh MIT)
- `verdict`: VERIFIED-BOTH = our source matches *both* registries; VERIFIED-NVIM/HELIX = matches one; registry-disagreement = registries name a different repo (listed separately); `vendor-maintained` = the language vendor's own grammar, not in nvim/Helix.
- **objectscript_udl / objectscript_routine** (added 2026-06-24): vendored from [intersystems/tree-sitter-objectscript](https://github.com/intersystems/tree-sitter-objectscript) @ `a7ffcdf` — MIT, the InterSystems-official grammars (a niche vendor language, hence `vendor-maintained`, not in nvim-treesitter/Helix). **Re-vendor note:** each `scanner.c`'s upstream `#include "../../common/scanner.h"` is repointed to a per-directory `objectscript_common.h` (a verbatim copy of upstream `common/scanner.h`), because this repo's shared `vendored/common/scanner.h` belongs to the cfml/fsharp grammars and differs. The generated `parser.c`/`scanner.c` are otherwise byte-for-byte upstream — on re-vendor, re-apply only that single include rename.
- **mojo** (added 2026-07-01): vendored from [lsh/tree-sitter-mojo](https://github.com/lsh/tree-sitter-mojo) @ `33193a99afe6` — MIT, ABI 15. Helix tracks `lsh/tree-sitter-mojo` as its Mojo grammar source, but the Helix-pinned commit (`3d7c53b8038f`) no longer resolves in the upstream repository after a force-push, so this vendor uses current upstream `main` rather than the stale registry SHA. Security review covered only the vendored C surface (`parser.c`, `scanner.c`, `tree_sitter/*.h`) plus upstream license/provenance metadata; no package manager hooks, workflow files, prompt/agent instruction files, or generated lockfiles were vendored.
- **plsql** (added 2026-07-11): vendored from [AndreasMaierDe/tree-sitter-plsql](https://github.com/AndreasMaierDe/tree-sitter-plsql) @ `28aebef209be` — MIT, ABI 14, no external scanner. Not listed in nvim-treesitter/Helix (`vendor-maintained` niche). Known limitation: `CREATE TYPE ... AS OBJECT` currently yields ERROR nodes in this grammar.

> ⚠️ **Pinned commit = the revision nvim-treesitter/Helix vendor** (battle-tested, canonical source), not bleeding-edge HEAD. When re-vendoring, update the pinned commit here.

Expand Down Expand Up @@ -45,6 +46,7 @@ Guarded by the `contract_all_grammars_in_graph` graph-breadth test in
| ispc | added to the C-family declarator-name gate (extends tree-sitter-c) |
| odin | `resolve_func_name`: `procedure_declaration` → `identifier` child |
| pascal | `resolve_func_name`: `defProc` → `header` (`declProc`) child's `name` field |
| plsql | `resolve_func_name`: `fnc_name`/`prc_name`; `extract_class_def`: `package_name`/`type_name`/`trigger_name`; `extract_plsql_callee`: `ref_call` → package-qualified `ref_name_parent.ref_name` |
| racket | `extract_lisp_def`: `(define …)` head-symbol forms in `list` |
| rescript | `resolve_func_name`: `function` (arrow) → enclosing `let_binding`'s `pattern` field |
| scheme | `extract_lisp_def`: `(define …)` head-symbol forms in `list` |
Expand All @@ -53,7 +55,7 @@ Guarded by the `contract_all_grammars_in_graph` graph-breadth test in

## Local source patches (applied atop pinned upstream)

The grammars below carry a small local patch to their vendored `scanner.c`, on
The grammars below carry a small local patch to their vendored sources, on
top of the pinned upstream commit recorded in the vendoring table below.
Re-vendoring from upstream must re-apply these.

Expand All @@ -62,6 +64,7 @@ Re-vendoring from upstream must re-apply these.
| crystal | `crystal/scanner.c`, serialize | guard `memcpy(&buffer[offset], state->literals.contents, literal_content_size)` with `if (literal_content_size > 0)` | UBSan: zero-length `memcpy` with a NULL/0-size source on the empty-state serialize round-trip (formal UB, harmless) |
| rescript | `rescript/scanner.c`, deserialize | guard `memcpy(state, buffer, n_bytes)` with `if (n_bytes > 0)` | UBSan: zero-length `memcpy` with a NULL `buffer` / `n_bytes == 0` on empty-state deserialize (formal UB, harmless). The sibling serialize copies a fixed `sizeof(ScannerState)` (always > 0, non-NULL src) and needs no guard. |
| purescript | `purescript/scanner.c`, serialize | guard `memcpy(buffer, indents->data, to_copy)` with `if (to_copy > 0)` | UBSan: zero-length `memcpy` with a NULL/0-size source when the indent vector is empty (formal UB, harmless) |
| plsql | `plsql/parser.c`, include | `#include <tree_sitter/parser.h>` → `#include "tree_sitter/parser.h"` | Older ABI-14 generator emits angle brackets; our grammar compile units resolve the per-grammar `tree_sitter/` headers via quoted-include search from the including file's directory |

## Vendored from verified upstream

Expand Down Expand Up @@ -157,6 +160,7 @@ Re-vendoring from upstream must re-apply these.
| perl | 14 | tree-sitter-perl/tree-sitter-perl | `ea9667dc65a8` | VERIFIED-BOTH | ✅ |
| php | 15 | tree-sitter/tree-sitter-php | `3f2465c217d0` | VERIFIED-BOTH | ✅ |
| pkl | 15 | apple/tree-sitter-pkl | `f5beed1da8e5` | VERIFIED-BOTH | ✅ |
| plsql | 14 | AndreasMaierDe/tree-sitter-plsql | `28aebef209be` | vendor-maintained | ✅ |
| po | 14 | tree-sitter-grammars/tree-sitter-po | `bd860a0f57f6` | VERIFIED-NVIM | ✅ |
| pony | 14 | tree-sitter-grammars/tree-sitter-pony | `73ff874ae4c9` | VERIFIED-NVIM | ✅ |
| powershell | 15 | airbus-cert/tree-sitter-powershell | `73800ecc8bdd` | VERIFIED-BOTH | ✅ |
Expand Down
21 changes: 21 additions & 0 deletions internal/cbm/vendored/grammars/plsql/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 AndreasMaierDe

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.
Loading
Loading