Use tree-sitter-ruby from crates.io

pull/795/head
Wilfred Hughes 2024-12-19 22:49:30 +07:00
parent 79bdf87c97
commit a9ed8bf5a1
51 changed files with 16 additions and 469393 deletions

11
Cargo.lock generated

@ -251,6 +251,7 @@ dependencies = [
"tree-sitter",
"tree-sitter-haskell",
"tree-sitter-language",
"tree-sitter-ruby",
"tree_magic_mini",
"typed-arena",
"unicode-width",
@ -1018,6 +1019,16 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c199356c799a8945965bb5f2c55b2ad9d9aa7c4b4f6e587fe9dea0bc715e5f9c"
[[package]]
name = "tree-sitter-ruby"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be0484ea4ef6bb9c575b4fdabde7e31340a8d2dbc7d52b321ac83da703249f95"
dependencies = [
"cc",
"tree-sitter-language",
]
[[package]]
name = "tree_magic_mini"
version = "3.1.5"

@ -79,6 +79,7 @@ smallvec = "1.13.2"
tree-sitter-language = "0.1.3"
streaming-iterator = "0.1.9"
tree-sitter-haskell = "0.23.1"
tree-sitter-ruby = "0.23.1"
[dev-dependencies]
# assert_cmd 2.0.10 requires predicates 3.

@ -293,11 +293,6 @@ fn main() {
src_dir: "vendored_parsers/tree-sitter-racket-src",
extra_files: vec!["scanner.c"],
},
TreeSitterParser {
name: "tree-sitter-ruby",
src_dir: "vendored_parsers/tree-sitter-ruby-src",
extra_files: vec!["scanner.cc"],
},
TreeSitterParser {
name: "tree-sitter-rust",
src_dir: "vendored_parsers/tree-sitter-rust-src",

@ -106,7 +106,6 @@ extern "C" {
fn tree_sitter_qmljs() -> ts::Language;
fn tree_sitter_r() -> ts::Language;
fn tree_sitter_racket() -> ts::Language;
fn tree_sitter_ruby() -> ts::Language;
fn tree_sitter_rust() -> ts::Language;
fn tree_sitter_scala() -> ts::Language;
fn tree_sitter_scheme() -> ts::Language;
@ -944,7 +943,8 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
}
}
Ruby => {
let language = unsafe { tree_sitter_ruby() };
let language_fn = tree_sitter_ruby::LANGUAGE;
let language = tree_sitter::Language::new(language_fn);
TreeSitterConfig {
language: language.clone(),
atom_nodes: vec!["string", "heredoc_body", "regex"]
@ -959,11 +959,8 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
("begin", "end"),
("class", "end"),
],
highlight_query: ts::Query::new(
&language,
include_str!("../../vendored_parsers/highlights/ruby.scm"),
)
.unwrap(),
highlight_query: ts::Query::new(&language, tree_sitter_ruby::HIGHLIGHTS_QUERY)
.unwrap(),
sub_languages: vec![],
}
}

@ -1 +0,0 @@
../tree-sitter-ruby/queries/highlights.scm

@ -1 +0,0 @@
tree-sitter-ruby/src

@ -1,2 +0,0 @@
/src/** linguist-vendored

@ -1,8 +0,0 @@
Checklist:
- [ ] All tests pass in CI.
- [ ] There are sufficient tests for the new fix/feature.
- [ ] Grammar rules have not been renamed unless absolutely necessary.
- [ ] The conflicts section hasn't grown too much.
- [ ] The parser size hasn't grown too much (check the value of STATE_COUNT in src/parser.c).

@ -1,31 +0,0 @@
name: Build/test
on:
push:
branches:
- "**"
pull_request:
branches:
- master
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16
- run: npm install
- run: npm test
test_windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16
- run: npm install
- run: npm run-script test-windows

@ -1,13 +0,0 @@
Cargo.lock
node_modules
build
*.log
package-lock.json
test.rb
examples/ruby_spec
/target/
*.a
*.dylib
*.so
*.o
bindings/c/*.h

@ -1,5 +0,0 @@
test
build
script
examples
target

@ -1,31 +0,0 @@
[package]
name = "tree-sitter-ruby"
description = "Ruby grammar for the tree-sitter parsing library"
version = "0.19.0"
authors = [
"Douglas Creager <dcreager@dcreager.net>",
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
]
license = "MIT"
readme = "bindings/rust/README.md"
keywords = ["incremental", "parsing", "ruby"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-ruby"
edition = "2018"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = ">= 0.19, < 0.21"
[build-dependencies]
cc = "1.0"

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 Rob Rix
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.

@ -1,114 +0,0 @@
VERSION := 0.19.0
# Repository
SRC_DIR := src
PARSER_REPO_URL := $(shell git -C $(SRC_DIR) remote get-url origin )
ifeq (, $(PARSER_NAME))
PARSER_NAME := $(shell basename $(PARSER_REPO_URL))
PARSER_NAME := $(subst tree-sitter-,,$(PARSER_NAME))
PARSER_NAME := $(subst .git,,$(PARSER_NAME))
endif
ifeq (, $(PARSER_URL))
PARSER_URL := $(subst :,/,$(PARSER_REPO_URL))
PARSER_URL := $(subst git@,https://,$(PARSER_URL))
PARSER_URL := $(subst .git,,$(PARSER_URL))
endif
UPPER_PARSER_NAME := $(shell echo $(PARSER_NAME) | tr a-z A-Z )
# install directory layout
PREFIX ?= /usr/local
INCLUDEDIR ?= $(PREFIX)/include
LIBDIR ?= $(PREFIX)/lib
PCLIBDIR ?= $(LIBDIR)/pkgconfig
# collect C++ sources, and link if necessary
CPPSRC := $(wildcard $(SRC_DIR)/*.cc)
ifeq (, $(CPPSRC))
ADDITIONALLIBS :=
else
ADDITIONALLIBS := -lc++
endif
# collect sources
SRC := $(wildcard $(SRC_DIR)/*.c)
SRC += $(CPPSRC)
OBJ := $(addsuffix .o,$(basename $(SRC)))
# ABI versioning
SONAME_MAJOR := 0
SONAME_MINOR := 0
CFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
CXXFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
override CFLAGS += -std=gnu99 -fPIC
override CXXFLAGS += -fPIC
# OS-specific bits
ifeq ($(shell uname),Darwin)
SOEXT = dylib
SOEXTVER_MAJOR = $(SONAME_MAJOR).dylib
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).dylib
LINKSHARED := $(LINKSHARED)-dynamiclib -Wl,
ifneq ($(ADDITIONALLIBS),)
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS),
endif
LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/libtree-sitter-$(PARSER_NAME).$(SONAME_MAJOR).dylib,-rpath,@executable_path/../Frameworks
else
SOEXT = so
SOEXTVER_MAJOR = so.$(SONAME_MAJOR)
SOEXTVER = so.$(SONAME_MAJOR).$(SONAME_MINOR)
LINKSHARED := $(LINKSHARED)-shared -Wl,
ifneq ($(ADDITIONALLIBS),)
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS)
endif
LINKSHARED := $(LINKSHARED)-soname,libtree-sitter-$(PARSER_NAME).so.$(SONAME_MAJOR)
endif
ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly))
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
endif
all: libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXTVER) bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
libtree-sitter-$(PARSER_NAME).a: $(OBJ)
$(AR) rcs $@ $^
libtree-sitter-$(PARSER_NAME).$(SOEXTVER): $(OBJ)
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXT)
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
bindings/c/$(PARSER_NAME).h:
sed -e 's|@UPPER_PARSERNAME@|$(UPPER_PARSER_NAME)|' \
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
bindings/c/tree-sitter.h.in > $@
bindings/c/tree-sitter-$(PARSER_NAME).pc:
sed -e 's|@LIBDIR@|$(LIBDIR)|;s|@INCLUDEDIR@|$(INCLUDEDIR)|;s|@VERSION@|$(VERSION)|' \
-e 's|=$(PREFIX)|=$${prefix}|' \
-e 's|@PREFIX@|$(PREFIX)|' \
-e 's|@ADDITIONALLIBS@|$(ADDITIONALLIBS)|' \
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
-e 's|@PARSERURL@|$(PARSER_URL)|' \
bindings/c/tree-sitter.pc.in > $@
install: all
install -d '$(DESTDIR)$(LIBDIR)'
install -m755 libtree-sitter-$(PARSER_NAME).a '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).a
install -m755 libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXT)
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter
install -m644 bindings/c/$(PARSER_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/
install -d '$(DESTDIR)$(PCLIBDIR)'
install -m644 bindings/c/tree-sitter-$(PARSER_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/
clean:
rm -f $(OBJ) libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXT) libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR) libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
rm -f bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
.PHONY: all install clean

@ -1,10 +0,0 @@
tree-sitter-ruby
================
[![build](https://github.com/tree-sitter/tree-sitter-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/tree-sitter/tree-sitter-ruby/actions/workflows/ci.yml)
Ruby grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
#### References
* [AST Format of the Whitequark parser](https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md)

@ -1,19 +0,0 @@
{
"targets": [
{
"target_name": "tree_sitter_ruby_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"src/parser.c",
"bindings/node/binding.cc",
"src/scanner.cc"
],
"cflags_c": [
"-std=c99",
]
}
]
}

@ -1,16 +0,0 @@
#ifndef TREE_SITTER_@UPPER_PARSERNAME@_H_
#define TREE_SITTER_@UPPER_PARSERNAME@_H_
#include <tree_sitter/parser.h>
#ifdef __cplusplus
extern "C" {
#endif
extern TSLanguage *tree_sitter_@PARSERNAME@();
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_@UPPER_PARSERNAME@_H_

@ -1,11 +0,0 @@
prefix=@PREFIX@
libdir=@LIBDIR@
includedir=@INCLUDEDIR@
additionallibs=@ADDITIONALLIBS@
Name: tree-sitter-@PARSERNAME@
Description: A tree-sitter grammar for the @PARSERNAME@ programming language.
URL: @PARSERURL@
Version: @VERSION@
Libs: -L${libdir} ${additionallibs} -ltree-sitter-@PARSERNAME@
Cflags: -I${includedir}

@ -1,28 +0,0 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_ruby();
namespace {
NAN_METHOD(New) {}
void Init(Local<Object> exports, Local<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_ruby());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("ruby").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_ruby_binding, Init)
} // namespace

@ -1,19 +0,0 @@
try {
module.exports = require("../../build/Release/tree_sitter_ruby_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_ruby_binding");
} catch (error2) {
if (error2.code !== 'MODULE_NOT_FOUND') {
throw error2;
}
throw error1
}
}
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

@ -1,37 +0,0 @@
# tree-sitter-ruby
This crate provides a Ruby grammar for the [tree-sitter][] parsing library.
To use this crate, add it to the `[dependencies]` section of your `Cargo.toml`
file. (Note that you will probably also need to depend on the
[`tree-sitter`][tree-sitter crate] crate to use the parsed result in any useful
way.)
``` toml
[dependencies]
tree-sitter = "0.17"
tree-sitter-ruby = "0.16"
```
Typically, you will use the [language][language func] function to add this
grammar to a tree-sitter [Parser][], and then use the parser to parse some code:
``` rust
let code = r#"
def double(x)
x * 2
end
"#;
let mut parser = Parser::new();
parser.set_language(tree_sitter_ruby::language()).expect("Error loading Ruby grammar");
let parsed = parser.parse(code, None);
```
If you have any questions, please reach out to us in the [tree-sitter
discussions] page.
[Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
[language func]: https://docs.rs/tree-sitter-ruby/*/tree_sitter_ruby/fn.language.html
[Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
[tree-sitter]: https://tree-sitter.github.io/
[tree-sitter crate]: https://crates.io/crates/tree-sitter
[tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions

@ -1,34 +0,0 @@
use std::env;
use std::path::Path;
extern crate cc;
fn main() {
let src_dir = Path::new("src");
let mut c_config = cc::Build::new();
c_config.include(&src_dir);
c_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
c_config.compile("parser");
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
if env::var("TARGET").unwrap() == "wasm32-wasi" {
cpp_config.flag_if_supported("-fno-exceptions");
}
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
cpp_config.compile("scanner");
}

@ -1,72 +0,0 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2020, tree-sitter-ruby authors.
// See the LICENSE file in this repo for license details.
// ------------------------------------------------------------------------------------------------
//! This crate provides a Ruby grammar for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this grammar to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! use tree_sitter::Parser;
//!
//! let code = r#"
//! def double(x)
//! x * 2
//! end
//! "#;
//! let mut parser = Parser::new();
//! parser.set_language(tree_sitter_ruby::language()).expect("Error loading Ruby grammar");
//! let parsed = parser.parse(code, None);
//! # let parsed = parsed.unwrap();
//! # let root = parsed.root_node();
//! # assert!(!root.has_error());
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter::Language;
extern "C" {
fn tree_sitter_ruby() -> Language;
}
/// Returns the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
unsafe { tree_sitter_ruby() }
}
/// The source of the Ruby tree-sitter grammar description.
pub const GRAMMAR: &'static str = include_str!("../../grammar.js");
/// The syntax highlighting query for this language.
pub const HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights.scm");
/// The local-variable syntax highlighting query for this language.
pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
/// The symbol tagging query for this language.
pub const TAGGING_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading Ruby grammar");
}
}

File diff suppressed because it is too large Load Diff

@ -1,37 +0,0 @@
{
"name": "tree-sitter-ruby",
"version": "0.19.0",
"description": "Ruby grammar for tree-sitter",
"main": "bindings/node",
"keywords": [
"parser",
"lexer"
],
"author": "Rob Rix",
"license": "MIT",
"dependencies": {
"nan": "^2.14.1",
"prebuild-install": "^5.0.0"
},
"devDependencies": {
"prebuild": "^10.0.1",
"tree-sitter-cli": "^0.20.6"
},
"scripts": {
"install": "prebuild-install || node-gyp rebuild",
"prebuild": "prebuild -r electron -t 3.0.0 -t 4.0.0 -t 4.0.4 -t 5.0.0 --strip && prebuild -t 8.16.0 -t 10.12.0 --strip",
"prebuild:upload": "prebuild --upload-all",
"test": "tree-sitter test && script/parse-examples",
"test-windows": "tree-sitter test"
},
"repository": "https://github.com/tree-sitter/tree-sitter-ruby",
"tree-sitter": [
{
"scope": "source.ruby",
"file-types": [
"rb"
],
"injection-regex": "ruby"
}
]
}

@ -1,154 +0,0 @@
; Keywords
[
"alias"
"and"
"begin"
"break"
"case"
"class"
"def"
"do"
"else"
"elsif"
"end"
"ensure"
"for"
"if"
"in"
"module"
"next"
"or"
"rescue"
"retry"
"return"
"then"
"unless"
"until"
"when"
"while"
"yield"
] @keyword
((identifier) @keyword
(#match? @keyword "^(private|protected|public)$"))
; Function calls
((identifier) @function.method.builtin
(#eq? @function.method.builtin "require"))
"defined?" @function.method.builtin
(call
method: [(identifier) (constant)] @function.method)
; Function definitions
(alias (identifier) @function.method)
(setter (identifier) @function.method)
(method name: [(identifier) (constant)] @function.method)
(singleton_method name: [(identifier) (constant)] @function.method)
; Identifiers
[
(class_variable)
(instance_variable)
] @property
((identifier) @constant.builtin
(#match? @constant.builtin "^__(FILE|LINE|ENCODING)__$"))
(file) @constant.builtin
(line) @constant.builtin
(encoding) @constant.builtin
(hash_splat_nil
"**" @operator
) @constant.builtin
((constant) @constant
(#match? @constant "^[A-Z\\d_]+$"))
(constant) @constructor
(self) @variable.builtin
(super) @variable.builtin
(block_parameter (identifier) @variable.parameter)
(block_parameters (identifier) @variable.parameter)
(destructured_parameter (identifier) @variable.parameter)
(hash_splat_parameter (identifier) @variable.parameter)
(lambda_parameters (identifier) @variable.parameter)
(method_parameters (identifier) @variable.parameter)
(splat_parameter (identifier) @variable.parameter)
(keyword_parameter name: (identifier) @variable.parameter)
(optional_parameter name: (identifier) @variable.parameter)
((identifier) @function.method
(#is-not? local))
(identifier) @variable
; Literals
[
(string)
(bare_string)
(subshell)
(heredoc_body)
(heredoc_beginning)
] @string
[
(simple_symbol)
(delimited_symbol)
(hash_key_symbol)
(bare_symbol)
] @string.special.symbol
(regex) @string.special.regex
(escape_sequence) @escape
[
(integer)
(float)
] @number
[
(nil)
(true)
(false)
]@constant.builtin
(interpolation
"#{" @punctuation.special
"}" @punctuation.special) @embedded
(comment) @comment
; Operators
[
"="
"=>"
"->"
] @operator
[
","
";"
"."
] @punctuation.delimiter
[
"("
")"
"["
"]"
"{"
"}"
"%w("
"%i("
] @punctuation.bracket

@ -1,27 +0,0 @@
((method) @local.scope
(#set! local.scope-inherits false))
[
(lambda)
(block)
(do_block)
] @local.scope
(block_parameter (identifier) @local.definition)
(block_parameters (identifier) @local.definition)
(destructured_parameter (identifier) @local.definition)
(hash_splat_parameter (identifier) @local.definition)
(lambda_parameters (identifier) @local.definition)
(method_parameters (identifier) @local.definition)
(splat_parameter (identifier) @local.definition)
(keyword_parameter name: (identifier) @local.definition)
(optional_parameter name: (identifier) @local.definition)
(identifier) @local.reference
(assignment left: (identifier) @local.definition)
(operator_assignment left: (identifier) @local.definition)
(left_assignment_list (identifier) @local.definition)
(rest_assignment (identifier) @local.definition)
(destructured_left_assignment (identifier) @local.definition)

@ -1,64 +0,0 @@
; Method definitions
(
(comment)* @doc
.
[
(method
name: (_) @name) @definition.method
(singleton_method
name: (_) @name) @definition.method
]
(#strip! @doc "^#\\s*")
(#select-adjacent! @doc @definition.method)
)
(alias
name: (_) @name) @definition.method
(setter
(identifier) @ignore)
; Class definitions
(
(comment)* @doc
.
[
(class
name: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.class
(singleton_class
value: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.class
]
(#strip! @doc "^#\\s*")
(#select-adjacent! @doc @definition.class)
)
; Module definitions
(
(module
name: [
(constant) @name
(scope_resolution
name: (_) @name)
]) @definition.module
)
; Calls
(call method: (identifier) @name) @reference.call
(
[(identifier) (constant)] @name @reference.call
(#is-not? local)
(#not-match? @name "^(lambda|load|require|require_relative|__FILE__|__LINE__)$")
)

@ -1,9 +0,0 @@
examples/ruby_spec/command_line/fixtures/bad_syntax.rb
examples/ruby_spec/command_line/fixtures/freeze_flag_required_diff_enc.rb
examples/ruby_spec/core/enumerable/shared/inject.rb
examples/ruby_spec/language/fixtures/freeze_magic_comment_required_diff_enc.rb
examples/ruby_spec/language/string_spec.rb
examples/ruby_spec/core/proc/ruby2_keywords_spec.rb
examples/ruby_spec/language/fixtures/utf16-be-nobom.rb
examples/ruby_spec/language/fixtures/utf16-le-nobom.rb
examples/ruby_spec/language/lambda_spec.rb

@ -1,41 +0,0 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
function checkout_at() {
repo=$1; url=$2; sha=$3
if [ ! -d "$repo" ]; then
git clone "https://github.com/$url" "$repo"
fi
pushd "$repo"
git fetch && git reset --hard "$sha"
popd
}
checkout_at "examples/ruby_spec" "ruby/spec" "aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e"
# TODO: Fix these known issues:
# - [ ] String literals delimited with `=`, e.g. `%=hi=`
# - [ ] Issue with << operator mistaken for heredocs, e.g. `send(@method){|r,i| r<<i}`
# - [ ] defined as local var, e.g. `defn.send(@method, defined)`
# - [ ] Unicode character in symbols, variables, etc, e.g. `:êad`
# - [ ] Unicode characters in constants, e.g. `CS_CONSTλ = :const_unicode`
# - [ ] Keyword arguments in lambda `-> a: { }`
# - [ ] Lambda with call as default argument `-> a=a() { a }`
known_failures="$(cat script/known_failures.txt)"
node_modules/tree-sitter-cli/cli.js parse -q \
'examples/**/*.rb' \
$(for file in $known_failures; do echo "!${file}"; done)
example_count=$(find examples -name '*.rb' | wc -l)
failure_count=$(wc -w <<< "$known_failures")
success_count=$(( $example_count - $failure_count ))
success_percent=$(bc -l <<< "100*${success_count}/${example_count}")
printf \
"Successfully parsed %d of %d example files (%.1f%%)\n" \
$success_count $example_count $success_percent

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,224 +0,0 @@
#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
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
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 *);
};
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;
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;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
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 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_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -1,94 +0,0 @@
========
comments
========
# anything else here should be ignored
---
(program (comment))
===================
empty block comment
===================
=begin
=end
---
(program (comment))
======================
one-line block comment
======================
=begin
whatever
=end
---
(program (comment))
======================================
block comment with comment after begin
======================================
=begin rdoc
=end
---
(program (comment))
======================================
block comment with comment after end
======================================
=begin
=end rdoc
---
(program (comment))
=========================
multi-line block comments
=========================
=begin
whatever
multiple lines of whatever
=end
---
(program (comment))
=========================
multi-line block comments followed by standard comment
=========================
=begin
whatever
multiple lines of whatever
=end
# Another comment
---
(program (comment) (comment))
=========================
multi-line block comments with almost end
=========================
=begin
=e
=en
=end
---
(program (comment))

@ -1,691 +0,0 @@
=====================
empty while statement
=====================
while foo do
end
---
(program (while
condition: (identifier)
body: (do)))
================
while without do
================
while foo
end
---
(program (while
condition: (identifier)
body: (do)))
=========================
while statement with body
=========================
while foo do
bar
end
---
(program (while
condition: (identifier)
body: (do (identifier))))
=====================
empty until statement
=====================
until foo bar do
end
---
(program (until
condition: (call
method: (identifier)
arguments: (argument_list (identifier)))
body: (do)))
=========================
until statement with body
=========================
until foo do
bar
end
---
(program (until
(identifier)
(do (identifier))))
==================
empty if statement
==================
if foo
end
---
(program (if
condition: (identifier)))
=======================
empty if/else statement
=======================
if foo then
else
end
if true then ;; 123; end
---
(program
(if
condition: (identifier)
consequence: (then)
alternative: (else))
(if
condition: (true)
consequence: (then
(empty_statement)
(empty_statement)
(integer))))
==================================
single-line if then else statement
==================================
if foo then bar else quux end
---
(program (if (identifier) (then (identifier)) (else (identifier))))
========
if elsif
========
if foo
bar
elsif quux
baz
end
---
(program
(if (identifier) (then (identifier))
(elsif (identifier) (then (identifier)))))
=============
if elsif else
=============
if foo
bar
elsif quux
baz
else
bat
end
---
(program
(if (identifier)
(then (identifier))
(elsif
(identifier)
(then (identifier))
(else (identifier)))))
======================
empty unless statement
======================
unless foo
end
---
(program (unless (identifier)))
================================
empty unless statement with then
================================
unless foo then
hi
end
---
(program
(unless
condition: (identifier)
consequence: (then
(identifier))))
================================
empty unless statement with else
================================
unless foo
else
end
---
(program
(unless
condition: (identifier)
alternative: (else)))
===
for
===
for x in y do
f
end
for x, in y
f
end
for x, *y in z do
f
end
for (k, v) in y do
f
end
---
(program
(for
pattern: (identifier)
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(identifier))
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(identifier)
(rest_assignment (identifier)))
value: (in (identifier))
body: (do (identifier)))
(for
pattern: (left_assignment_list
(destructured_left_assignment
(identifier)
(identifier)))
value: (in (identifier))
body: (do (identifier))))
==============
for without do
==============
for x in y
f
end
---
(program (for
pattern: (identifier)
value: (in (identifier))
body: (do (identifier))))
==============
next
==============
for x in y
next
end
---
(program (for (identifier) (in (identifier)) (do (next))))
==============
retry
==============
for x in y
retry
end
---
(program (for
pattern: (identifier)
value: (in (identifier))
body: (do (retry))))
==============
break
==============
while b
break
end
---
(program (while (identifier) (do (break))))
==============
redo
==============
while b
redo
end
---
(program (while (identifier) (do (redo))))
===========
empty begin
===========
begin
end
---
(program (begin))
===============
begin with body
===============
begin
foo
end
---
(program (begin (identifier)))
===============
begin with else
===============
begin
foo
else
bar
end
---
(program
(begin (identifier)
(else (identifier))))
===============
begin with ensure
===============
begin
foo
ensure
bar
end
---
(program
(begin (identifier)
(ensure (identifier))))
=======================
begin with empty rescue
=======================
begin
rescue
end
begin
rescue then
end
begin
rescue
bar
end
---
(program
(begin (rescue))
(begin (rescue (then)))
(begin (rescue (then (identifier)))))
===========================
begin with rescue with args
===========================
begin
rescue x
end
begin
rescue x then
end
begin
rescue x
bar
end
begin
rescue => x
bar
end
begin
rescue x, y
bar
end
begin
rescue Error => x
end
begin
rescue Error => x
bar
end
---
(program
(begin (rescue (exceptions (identifier))))
(begin (rescue (exceptions (identifier)) (then)))
(begin (rescue (exceptions (identifier)) (then (identifier))))
(begin (rescue (exception_variable (identifier)) (then (identifier))))
(begin (rescue (exceptions (identifier) (identifier)) (then (identifier))))
(begin (rescue (exceptions (constant)) (exception_variable (identifier))))
(begin (rescue (exceptions (constant)) (exception_variable (identifier)) (then (identifier)))))
===========================
begin with rescue with splat args
===========================
begin
rescue *args
end
---
(program (begin (rescue (exceptions (splat_argument (identifier))))))
=================
rescue modifier
=================
foo rescue nil
if foo rescue nil
elsif bar rescue nil
end
unless foo rescue nil
end
---
(program
(rescue_modifier (identifier) (nil))
(if (rescue_modifier (identifier) (nil)) (elsif (rescue_modifier (identifier) (nil))))
(unless (rescue_modifier (identifier) (nil))))
=================
rescue modifier in assignments
=================
x = foo rescue 1
x += foo rescue 1
x, y = foo rescue 1
x = bar, foo rescue 1
x = foo 1 rescue 2
x += foo 1 rescue 2
---
(program
(assignment
left: (identifier)
right: (rescue_modifier
body: (identifier)
handler: (integer)))
(operator_assignment
left: (identifier)
right: (rescue_modifier
body: (identifier)
handler: (integer)))
(assignment
left: (left_assignment_list
(identifier)
(identifier))
right: (rescue_modifier
body: (identifier)
handler: (integer)))
(rescue_modifier
body: (assignment
left: (identifier)
right: (right_assignment_list
(identifier)
(identifier)))
handler: (integer))
(assignment
left: (identifier)
right: (rescue_modifier
body: (call
method: (identifier)
arguments: (argument_list
(integer)))
handler: (integer)))
(operator_assignment
left: (identifier)
right: (rescue_modifier
body: (call
method: (identifier)
arguments: (argument_list
(integer)))
handler: (integer))))
============================
begin with all the trimmings
============================
begin
foo
rescue x
retry
else
quux
ensure
baz
end
---
(program
(begin (identifier)
(rescue (exceptions (identifier)) (then (retry)))
(else (identifier))
(ensure (identifier))))
======
return
======
return foo
---
(program (return (argument_list (identifier))))
====================
return without value
====================
return
---
(program (return))
====
case
====
case foo
when bar
end
---
(program
(case (identifier)
(when (pattern (identifier)))))
==============
case with else
==============
case foo
when bar
else
end
case key
when bar
else; leaf
end
---
(program
(case
(identifier)
(when (pattern (identifier)))
(else))
(case
(identifier)
(when (pattern (identifier)))
(else (identifier))))
==============================
case with multiple when blocks
==============================
case a
when b
c
when d
e
else
f
end
---
(program
(case (identifier)
(when (pattern (identifier)) (then (identifier)))
(when (pattern (identifier)) (then (identifier)))
(else (identifier))))
==============================
case without line break
==============================
case a when b
c end
---
(program
(case (identifier)
(when
(pattern
(identifier))
(then
(identifier)))))
==============================
case with splat parameter in when
==============================
case a
when *foo
c
end
---
(program
(case
(identifier)
(when
(pattern (splat_argument (identifier)))
(then (identifier)))))
==============
case with assignment
==============
x = case foo
when bar
else
end
---
(program (assignment (identifier)
(case (identifier)
(when (pattern (identifier)))
(else))))
==============
case with expression
==============
x = case foo = bar | baz
when bar
else
end
---
(program (assignment (identifier)
(case (assignment (identifier) (binary (identifier) (identifier)))
(when (pattern (identifier)))
(else))))

@ -1,629 +0,0 @@
============
empty method
============
def foo
end
def foo?
end
def foo!
end
---
(program
(method (identifier))
(method (identifier))
(method (identifier)))
=====================
method with body
=====================
def foo
bar
end
---
(program (method (identifier) (identifier)))
=====================
"end"-less method
=====================
def foo = bar
def foo() = bar
def foo(x) = bar
def Object.foo = bar
def Object.foo (x) = bar
def foo() = bar rescue (print "error")
---
(program
(method (identifier) (identifier))
(method (identifier) (method_parameters) (identifier))
(method (identifier) (method_parameters (identifier)) (identifier))
(singleton_method (constant) (identifier) (identifier))
(singleton_method (constant) (identifier) (method_parameters (identifier)) (identifier))
(method (identifier) (method_parameters)
(rescue_modifier
(identifier)
(parenthesized_statements (call (identifier) (argument_list (string (string_content)))))
)
)
)
===========================
method as attribute setter
===========================
def foo=
end
---
(program (method (setter (identifier))))
==============================
method definition of operators
==============================
def `(a)
"`"
end
def -@(a)
end
def %(a)
end
def ..(a)
end
def !~(a)
end
---
(program
(method (operator) (method_parameters (identifier)) (string (string_content)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier))))
===================================================
method with forward slash name and regex ambiguity
===================================================
puts /(/
def /(name)
end
def / name
end
---
(program
(call (identifier) (argument_list (regex (string_content))))
(method (operator) (method_parameters (identifier)))
(method (operator) (method_parameters (identifier))))
===========================
method with call to super
===========================
def foo
super
end
def foo
bar.baz { super }
end
def foo
super.bar a, b
end
---
(program
(method (identifier) (super))
(method
(identifier)
(call (identifier) (identifier) (block (super))))
(method
(identifier)
(call (super) (identifier) (argument_list (identifier) (identifier)))))
===========================
method with args
===========================
def foo(bar)
end
def foo(bar); end
def foo(bar) end
---
(program
(method (identifier) (method_parameters (identifier)))
(method (identifier) (method_parameters (identifier)))
(method (identifier) (method_parameters (identifier))))
================================
method with unparenthesized args
================================
def foo bar
end
---
(program (method (identifier) (method_parameters (identifier))))
=========================
method with multiple args
=========================
def foo(bar, quux)
end
---
(program (method (identifier) (method_parameters (identifier) (identifier))))
=========================================
method with multiple unparenthesized args
=========================================
def foo bar, quux
end
---
(program (method (identifier) (method_parameters (identifier) (identifier))))
=========================================
method with keyword parameters
=========================================
def foo(bar: nil, baz:)
end
---
(program
(method (identifier)
(method_parameters
(keyword_parameter (identifier) (nil))
(keyword_parameter (identifier)))))
=========================================
method with default parameters
=========================================
def foo(bar = nil)
end
def foo(bar=nil)
end
---
(program
(method (identifier)
(method_parameters (optional_parameter (identifier) (nil))))
(method (identifier)
(method_parameters (optional_parameter (identifier) (nil)))))
=========================================
method with interesting params
=========================================
def foo(*options)
end
def foo(x, *options)
end
def foo(x, *options, y)
end
def foo(**options)
end
def foo(name:, **)
end
def foo(x, **nil)
end
def foo(&block)
end
def foo(&)
end
def foo(...)
super(...)
end
def foo(a, b, ...)
bar(b, ...)
end
---
(program
(method (identifier) (method_parameters (splat_parameter (identifier))))
(method (identifier) (method_parameters (identifier) (splat_parameter (identifier))))
(method (identifier) (method_parameters (identifier) (splat_parameter (identifier)) (identifier)))
(method (identifier) (method_parameters (hash_splat_parameter (identifier))))
(method (identifier) (method_parameters (keyword_parameter (identifier)) (hash_splat_parameter)))
(method (identifier) (method_parameters (identifier) (hash_splat_nil)))
(method (identifier) (method_parameters (block_parameter (identifier))))
(method (identifier) (method_parameters (block_parameter)))
(method (identifier) (method_parameters (forward_parameter))
(call (super) (argument_list (forward_argument)))
)
(method (identifier) (method_parameters (identifier) (identifier) (forward_parameter))
(call (identifier) (argument_list (identifier) (forward_argument)))
)
)
=========================================
singleton method
=========================================
def self.foo
end
---
(program (singleton_method (self) (identifier)))
=========================================
singleton method with body
=========================================
def self.foo
bar
end
---
(program (singleton_method (self) (identifier) (identifier)))
=========================================
singleton method with arg
=========================================
def self.foo(bar)
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier))))
=========================================
singleton method with un-parenthesized arg
=========================================
def self.foo bar
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier))))
=========================================
singleton method with args
=========================================
def self.foo(bar, baz)
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier))))
=========================================
singleton method with un-parenthesized args
=========================================
def self.foo bar, baz
end
---
(program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier))))
===========
empty class
===========
class Foo
end
class Foo; end
class Foo::Bar
end
class ::Foo::Bar
end
class Cß
end
---
(program
(class (constant))
(class (constant))
(class (scope_resolution (constant) (constant)))
(class (scope_resolution (scope_resolution (constant)) (constant)))
(class (constant)))
==============
empty subclass
==============
class Foo < Bar
end
---
(program (class (constant) (superclass (constant))))
==================================
empty subclass of namespaced class
==================================
class Foo < Bar::Quux
end
class Foo < ::Bar
end
class Foo < Bar::Baz.new(foo)
end
---
(program
(class
(constant)
(superclass (scope_resolution (constant) (constant))))
(class
(constant)
(superclass (scope_resolution (constant))))
(class
(constant)
(superclass (call (scope_resolution (constant) (constant)) (identifier) (argument_list (identifier))))))
=======================================
unparenthesized call as superclass
=======================================
class A < B.new \
:c,
:d
end
---
(program (class
name: (constant)
superclass: (superclass (call
receiver: (constant)
method: (identifier)
arguments: (argument_list
(simple_symbol)
(simple_symbol))))))
===============
class with body
===============
class Foo
def bar
end
end
---
(program (class (constant) (method (identifier))))
=========================================
class within dynamically-computed module
=========================================
class foo()::Bar
end
---
(program (class (scope_resolution (call (identifier) (argument_list)) (constant))))
===============
singleton class
===============
class << self
end
class <<self
end
class << Foo
end
class << Foo::Bar
end
---
(program
(singleton_class (self))
(singleton_class (self))
(singleton_class (constant))
(singleton_class (scope_resolution (constant) (constant))))
============
empty module
============
module Foo
end
module Foo::Bar
end
---
(program
(module (constant))
(module (scope_resolution (constant) (constant))))
================
module with body
================
module Foo
def bar
end
end
---
(program (module (constant) (method (identifier))))
========================
module without semicolon
========================
module Foo end
---
(program (module (constant)))
=======
__END__
=======
word
__END__
word
x
ab
d
---
(program (identifier) (uninterpreted))
==============================
module with class with methods
==============================
module A
class B < C
include D::E.f.g
attr_reader :h
# i
def j
k
end
def self.l
end
end
end
---
(program (module (constant)
(class (constant) (superclass (constant))
(call (identifier) (argument_list
(call
(call
(scope_resolution (constant) (constant))
(identifier))
(identifier))))
(call (identifier) (argument_list (simple_symbol)))
(comment)
(method (identifier) (identifier))
(singleton_method (self) (identifier)))))
===========
empty BEGIN block
===========
BEGIN {
}
---
(program (begin_block))
===========
BEGIN block
===========
baz
BEGIN {
foo
}
bar
---
(program (identifier) (begin_block (identifier)) (identifier))
===========
empty END block
===========
END {
}
---
(program (end_block))
===========
END block
===========
baz
END {
foo
}
bar
---
(program (identifier) (end_block (identifier)) (identifier))

@ -1,42 +0,0 @@
==========================
Heredocs with errors
==========================
joins(<<~SQL(
b
SQL
c
---
(program
(call
method: (identifier)
(ERROR (heredoc_beginning))
arguments: (argument_list
(heredoc_body (heredoc_content) (heredoc_end))
(identifier)
(MISSING ")"))))
====================================
Heredocs
====================================
joins(<<-SQL
b
SQL
)
------------------------------------
(program
(call
method: (identifier)
arguments: (argument_list
(heredoc_beginning)
(heredoc_body (heredoc_content) (heredoc_end))
)
)
)

File diff suppressed because it is too large Load Diff

@ -1,23 +0,0 @@
=================
CRLF line endings
=================
puts 'hi'
x = foo()
---
(program
(call (identifier) (argument_list (string (string_content))))
(assignment (identifier) (call (identifier) (argument_list))))
=======================
CRLF multiline comments
=======================
=begin
=end
---
(program (comment))

File diff suppressed because it is too large Load Diff

@ -1,343 +0,0 @@
================
pattern matching
================
case expr
in 5 then true
else false
end
case expr
in x unless x < 0
then true
in x if x < 0
then true
else false
end
case expr
in 5
in 5,
in 1, 2
in 1, 2,
in 1, 2, 3
in 1, 2, 3,
in 1, 2, 3, *
in 1, *x, 3
in *
in *, 3, 4
in *, 3, *
in *a, 3, *b
in a:
in a: 5
in a: 5,
in a: 5, b:, **
in a: 5, b:, **map
in a: 5, b:, **nil
in **nil
in [5]
in [5,]
in [1, 2]
in [1, 2,]
in [1, 2, 3]
in [1, 2, 3,]
in [1, 2, 3, *]
in [1, *x, 3]
in [*]
in [*, 3, 4]
in [*, 3, *]
in [*a, 3, *b]
in {a:}
in {a: 5}
in {a: 5,}
in {a: 5, b:, **}
in {a: 5, b:, **map}
in {a: 5, b:, **nil}
in {**nil}
in {}
in []
end
-----
(program
(case_match (identifier)
(in_clause
(integer)
(then (true))
)
(else (false)))
(case_match (identifier)
(in_clause
(identifier)
(unless_guard (binary (identifier) (integer)))
(then (true))
)
(in_clause
(identifier)
(if_guard (binary (identifier) (integer)))
(then (true))
)
(else (false))
)
(case_match (identifier)
(in_clause (integer))
(in_clause (array_pattern (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer)))
(in_clause (array_pattern (splat_parameter)))
(in_clause (array_pattern (splat_parameter) (integer) (integer)))
(in_clause (find_pattern (splat_parameter) (integer) (splat_parameter)))
(in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter)))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil)))
(in_clause (hash_pattern (hash_splat_nil)))
(in_clause (array_pattern (integer)))
(in_clause (array_pattern (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer) (integer)))
(in_clause (array_pattern (integer) (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (integer) (integer) (splat_parameter)))
(in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer)))
(in_clause (array_pattern (splat_parameter)))
(in_clause (array_pattern (splat_parameter) (integer) (integer)))
(in_clause (find_pattern (splat_parameter) (integer) (splat_parameter)))
(in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter)))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier))))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil)))
(in_clause (hash_pattern (hash_splat_nil)))
(in_clause (hash_pattern))
(in_clause (array_pattern))
)
)
=====================
more pattern matching
=====================
case expr
in 5
in ^foo
in ^$foo
in ^@foo
in ^@@foo
in ^(1+1)
in ^(foo)
in ^(Foo::Bar)
in var
in "string"
in %w(foo bar)
in %i(foo bar)
in /.*abc[0-9]/
in 5 .. 10
in .. 10
in 5 ..
in 5 => x
in 5 | ^foo | var | "string"
in Foo
in Foo::Bar
in ::Foo::Bar
in (nil | self | true | false | __LINE__ | __FILE__ | __ENCODING__)
in -> x { x == 10 }
in :foo
in :"foo bar"
in -5 | +10
end
--------
(program
(case_match (identifier)
(in_clause (integer))
(in_clause (variable_reference_pattern (identifier)))
(in_clause (variable_reference_pattern (global_variable)))
(in_clause (variable_reference_pattern (instance_variable)))
(in_clause (variable_reference_pattern (class_variable)))
(in_clause (expression_reference_pattern (binary (integer) (integer))))
(in_clause (expression_reference_pattern (identifier)))
(in_clause (expression_reference_pattern (scope_resolution (constant) (constant))))
(in_clause (identifier))
(in_clause (string (string_content)))
(in_clause (string_array (bare_string (string_content)) (bare_string (string_content))))
(in_clause (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content))))
(in_clause (regex (string_content)))
(in_clause (range (integer) (integer)))
(in_clause (range (integer)))
(in_clause (range (integer)))
(in_clause (as_pattern (integer) (identifier)))
(in_clause
(alternative_pattern
(integer)
(variable_reference_pattern (identifier))
(identifier)
(string (string_content))
)
)
(in_clause (constant))
(in_clause (scope_resolution (constant) (constant)))
(in_clause (scope_resolution (scope_resolution (constant)) (constant)))
(in_clause
(parenthesized_pattern
(alternative_pattern
(nil)
(self)
(true)
(false)
(line)
(file)
(encoding)
)
)
)
(in_clause (lambda (lambda_parameters (identifier)) (block (binary (identifier) (integer)))))
(in_clause (simple_symbol))
(in_clause (delimited_symbol (string_content)))
(in_clause
(alternative_pattern
(unary (integer))
(unary (integer))
)
)
)
)
==============
array patterns
==============
case expr
in [];
in [x];
in [x, ];
in Foo::Bar[];
in Foo();
in Bar(*);
in Bar(a, b, *c, d, e);
end
--------------
(program
(case_match (identifier)
(in_clause (array_pattern))
(in_clause (array_pattern (identifier)))
(in_clause (array_pattern (identifier) (splat_parameter)))
(in_clause (array_pattern (scope_resolution (constant) (constant))))
(in_clause (array_pattern (constant)))
(in_clause (array_pattern (constant) (splat_parameter)))
(in_clause
(array_pattern
(constant)
(identifier)
(identifier)
(splat_parameter (identifier))
(identifier)
(identifier)
)
)
)
)
=============
find patterns
=============
case expr
in [*, x, *];
in [*x, 1, 2, *y];
in Foo::Bar[*, 1, *];
in Foo(*, Bar, *);
end
-------------
(program
(case_match (identifier)
(in_clause (find_pattern (splat_parameter) (identifier) (splat_parameter)))
(in_clause (find_pattern (splat_parameter (identifier)) (integer) (integer) (splat_parameter (identifier))))
(in_clause (find_pattern
(scope_resolution (constant) (constant))
(splat_parameter)
(integer)
(splat_parameter))
)
(in_clause (find_pattern (constant) (splat_parameter) (constant) (splat_parameter)))
)
)
=============
hash patterns
=============
case expr
in {};
in {x:};
in Foo::Bar[ x:1 ];
in Foo::Bar[ x:1, a:, **rest ];
in Foo( y:);
in Bar( ** );
in Bar( a: 1, **nil);
end
-------------
(program (case_match (identifier)
(in_clause (hash_pattern))
(in_clause (hash_pattern (keyword_pattern (hash_key_symbol))))
(in_clause (hash_pattern
(scope_resolution (constant) (constant))
(keyword_pattern (hash_key_symbol) (integer))
))
(in_clause (hash_pattern
(scope_resolution (constant) (constant))
(keyword_pattern (hash_key_symbol) (integer))
(keyword_pattern (hash_key_symbol))
(hash_splat_parameter (identifier))
))
(in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol))))
(in_clause (hash_pattern (constant) (hash_splat_parameter)))
(in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol) (integer)) (hash_splat_nil)))
)
)
=====================
pattern matching with fancy string literals
=====================
case expr
in "string";
in `ls`;
in <<"DOC" then end
some text
DOC
---
(program
(case_match
value: (identifier)
clauses: (in_clause
pattern: (string
(string_content)))
clauses: (in_clause
pattern: (subshell
(string_content)))
clauses: (in_clause
pattern: (heredoc_beginning)
body: (then)))
(heredoc_body
(heredoc_content)
(heredoc_end)))

@ -1,9 +0,0 @@
==================================
Single CR characters as whitespace
==================================
puts "hi"
---
(program (call (identifier) (argument_list (string (string_content)))))

@ -1,92 +0,0 @@
====================
conditional modifier
====================
foo if bar
return if false
return true if foo bar
return nil if foo
---
(program
(if_modifier
(identifier)
(identifier))
(if_modifier
(return)
(false))
(if_modifier
(return (argument_list (true)))
(call (identifier) (argument_list (identifier))))
(if_modifier
(return (argument_list (nil)))
(identifier)))
==============
while modifier
==============
foo while bar
---
(program (while_modifier
body: (identifier)
condition: (identifier)))
===============
unless modifier
===============
foo unless bar
---
(program (unless_modifier
body: (identifier)
condition: (identifier)))
==============
until modifier
==============
foo until bar
---
(program (until_modifier (identifier) (identifier)))
========
alias
========
alias :foo :bar
alias foo bar
alias $FOO $&
alias foo +
---
(program
(alias (simple_symbol) (simple_symbol))
(alias (identifier) (identifier))
(alias (global_variable) (global_variable))
(alias (identifier) (operator)))
========
undef
========
undef :foo
undef foo
undef +
undef :foo, :bar
---
(program
(undef (simple_symbol))
(undef (identifier))
(undef (operator))
(undef (simple_symbol) (simple_symbol)))

@ -1,33 +0,0 @@
require "a"
# ^ function.method.builtin
class Car < Vehicle
# <- keyword
# ^ constructor
def init(id)
# <- keyword
# ^ function.method
@id = id
# <- property
# ^ variable.parameter
yield
# <- keyword
return
# <- keyword
next
# <- keyword
end
private
# ^ keyword
public
# ^ keyword
protected
# ^ keyword
end
# <- keyword

@ -1,24 +0,0 @@
class MyClass
# ^ constructor
ELEMENT8 = 8
# ^ constant
ELEMENT16 = 16
# ^ constant
def OtherClass
# ^ function.method
@other.OtherClass(Something.new).inspect
# ^ property
# ^ function.method
# ^ constructor
# ^ function.method
# ^ function.method
end
end
if __FILE__ == $0
# ^ constant.builtin
end

@ -1,36 +0,0 @@
"hello"
# ^ string
%(hello)
# ^ string
%w(hello goodbye)
# ^ string
# ^ string
:hello
# ^ string.special.symbol
%s(hello)
# ^ string.special.symbol
%I(hello goodbye)
# ^ string.special.symbol
# ^ string.special.symbol
/hello/
# ^ string.special.regex
%r(hello)
# ^ string.special.regex
12345
# ^ number
12.345
# ^ number
nil
# ^ constant.builtin
true
# ^ constant.builtin
TRUE
# ^ constant
false
# ^ constant.builtin
FALSE
# ^ constant

@ -1,18 +0,0 @@
expr = [false | __LINE__ | __FILE__ | __ENCODING__]
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
case expr
in {a: 5, b:, **nil}
# ^ operator
# ^ constant.builtin
in [false | __LINE__ | __FILE__ | __ENCODING__]
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
# ^ constant.builtin
else
end

@ -1,48 +0,0 @@
one = 1
# <- variable
def two()
three = one
# ^ variable
# ^ function.method
four = three
# ^ variable
# ^ variable
four.each do |i|
puts i, three, five
# ^ variable.parameter
# ^ variable (because blocks are closures)
# ^ function.method
end
four.each do |(a, b), c: d, e = f|
# ^ variable.parameter
# ^ variable.parameter
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ function.method
puts a, b, c, d, e, f
# ^ variable.parameter
# ^ variable.parameter
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ function.method
end
five ||= 1
# ^ variable
six -> (seven) { eight(seven, five) }
# ^ function.method
# ^ variable.parameter
# ^ function.method
# ^ variable.parameter
# ^ variable
seven
# ^ function.method (because the `seven` above was in the scope of the lambda)
end