npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dekobon/tree-sitter-groovy

v0.2.2

Published

Apache Groovy grammar for tree-sitter (dekobon fork)

Downloads

367

Readme

tree-sitter-groovy

CI CodeQL npm crates.io PyPI

Tree-sitter grammar for Apache Groovy — the JVM scripting language used in Jenkins pipelines, Gradle build files, and Spock test specifications.

Published as: @dekobon/tree-sitter-groovy on npm, dekobon-tree-sitter-groovy on crates.io and PyPI, github.com/dekobon/tree-sitter-groovy as a Go module / Swift package. The unscoped name belongs to the upstream comparison grammar linked below; the C library (no naming conflict) still ships as libtree-sitter-groovy.

This grammar is purpose-built for Groovy (it does not extend the tree-sitter-java grammar). It synthesises the best ideas from the two existing community grammars while closing every operator and statement gap they left open:

  • amaanq/tree-sitter-groovy — clean precedence table and shebang handling, but mis-shapes Groovy-specific syntax (Elvis ?:, safe navigation ?., spread operators, regex =~ / ==~, traits, exclusive ranges, identity === / !==, spaceship <=>, etc.) as Java-shaped parse trees.
  • murtaza64/tree-sitter-groovy — purpose-built for Groovy, broad operator coverage and slashy strings, but has open bugs around empty block comments, multi-catch, multi-assignment, enums, switch-arrow, and a pipeline-at-EOF constraint.

The full design is in SPECIFICATION.md.

Status

Fully functional Groovy 2.x--4.x parser with complete operator coverage, GString interpolation, generics, closures, command chains, and six language bindings. See Known limitations for deferred items.

Operator coverage

Every Groovy operator emits a distinct named node so downstream tooling can identify each by node kind alone — no MISSING-child inspection, no tree-shape heuristics. This is the contract that closes dekobon/big-code-analysis#246 (Elvis short-circuit counting) and dekobon/big-code-analysis#247 (all Groovy-specific operator gaps).

| Category | Operators | |---|---| | Arithmetic | + - * / % ** ++ -- | | Relational | < <= > >= == != <=> (spaceship) | | Identity | === !== | | Regex | =~ (find) ==~ (match) | | Logical | && \|\| ! ==> (implication) | | Bitwise | & \| ^ ~ << >> >>> | | Conditional | ? : (ternary) ?: (Elvis) | | Assignment | = += -= *= /= %= **= <<= >>= >>>= &= ^= \|= ?= (Elvis assign) | | Range | .. ..< <.. <..< | | Member access | . ?. ??. (safe chain dot) *. (spread-dot) .& (method pointer) .@ (direct field) :: (method reference) | | Subscript | [] ?[] (safe index) | | Spread | *args *: (spread-map) | | Membership | in !in instanceof !instanceof | | Coercion | as |

Editor support

Tree-sitter queries (queries/groovy/highlights.scm, folds.scm, indents.scm, injections.scm) are provided for editor integration. Slashy and dollar-slashy string bodies inject as regex for nested regex highlighting.

Recognized file extensions: .groovy, .gradle, .gvy, .gy, and Jenkinsfile.

Filetype detection

The repo ships ftdetect/groovy.lua and ftplugin/groovy.lua for Neovim. Neovim's built-in filetype detection already maps *.groovy, *.gradle, and the bare filename Jenkinsfile to filetype groovy; the shipped ftdetect/groovy.lua fills the gaps by mapping:

  • *.gvy and *.gy — declared in tree-sitter.json but not in Neovim's defaults.
  • *.jenkinsfile — uncommon (the canonical name is Jenkinsfile) but declared in tree-sitter.json and used by some teams as an editor-detection hook.
  • Jenkinsfile.* variants (Jenkinsfile.ci, Jenkinsfile.release, …) — common in repos with multiple pipelines, not handled by Neovim's built-in detection.

The existing ftplugin/groovy.lua then calls vim.treesitter.start(). Highlighting only renders once the parser binary and queries/groovy/highlights.scm are registered with nvim-treesitter (or equivalent) — without that, the start() call is a no-op and the buffer falls back to non-treesitter highlighting.

For files that don't match any of those (e.g. a hand-named build-pipeline with no extension), opt in with one of:

  • Modeline at the top of the file: // vim: set filetype=groovy :

  • Per-project autocmd in .nvim.lua (sourced after :cd into the project via Neovim's 'exrc'). Note vim.fn.getcwd() is evaluated when the autocmd is defined, so this snippet belongs in a per-project config, not a global init.lua:

    vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
      pattern = vim.fn.getcwd() .. "/jenkins/*",
      callback = function() vim.bo.filetype = "groovy" end,
    })

Other editors follow the same pattern: rely on built-in detection for the common extensions and override per-directory or via a header comment for the rest.

Building

npm install
make build
make test

Bindings

Available bindings: C, Go, Node.js, Python, Rust, Swift. See bindings/ for binding-specific READMEs and tests.

For Rust consumers:

[dependencies]
dekobon-tree-sitter-groovy = "0.1"
tree-sitter = "0.25"
let mut parser = tree_sitter::Parser::new();
let language = dekobon_tree_sitter_groovy::LANGUAGE;
parser.set_language(&language.into()).expect("Error loading Groovy parser");
let tree = parser.parse(source, None).unwrap();

Known limitations

These are documented in detail in docs/divergences-from-spec.md.

  • Groovy 5 contextual keywords (val, async, await, defer) are not yet exposed as keyword tokens. They parse as plain identifiers, matching Groovy 2.x--4.x compiler behavior.
  • Typed local declarations require an initializer -- String x is ambiguous with String(x) (method call). Use String x = ... or def x instead.
  • Leading-operator line continuation -- a\n+ b greedily joins as a + b rather than splitting into two statements. Idiomatic Groovy places continuation operators at the end of the previous line.

Contributing

See CONTRIBUTING.md for how to build, test, and submit changes. AGENTS.md covers project conventions (commit messages, versioning, validation gates) and SPECIFICATION.md is the authoritative grammar design document.

Acknowledgements

We are grateful for the work done in the murtaza64/tree-sitter-groovy and amaanq/tree-sitter-groovy. These projects served as inspiration for some of the approaches in this project

License

Dual-licensed under Apache License 2.0 or MIT.