811 Commits

Author SHA1 Message Date
Kevin Newton
af4a1ca021 Use slices instead of locations
In the C API, we want to use slices instead of locations in the
AST. In this case a "slice" is effectively the same thing as the
location, expect it is represented using a 32-bit offset and a
32-bit length. This will cut down on half of the space of all of
the locations in the AST.

Note that from the Ruby/Java/JavaScript side, this is effectively
an invisible change. This only impacts the C/Rust side.
2026-01-27 15:30:45 -05:00
Kevin Newton
68902e3593 [ruby/prism] Add Prism::Node#find_all
https://github.com/ruby/prism/commit/51df90ef04
2026-01-27 20:17:12 +00:00
Kevin Newton
c983b7aee6 [ruby/prism] Rename line_to_byte_offset -> byte_offset
Also, include the column in here. Hopefully we can do some additional
optimizations later.

https://github.com/ruby/prism/commit/7759acdd26
2026-01-27 20:06:22 +00:00
Earlopain
5d769228c1 [ruby/prism] Remove Prism.lex_ripper
Since `on_sp` is emitted, it doesn't do a whole lot anymore.

This leaves one incompatibility for code like `"x#$%"`

Ripper confuses this for bare interpolation with a global, but `$%` is not a valid global name. Still,
it emits two string tokens in such a case. It doesn't make sense for prism to work around this bug,
so the affected files are added as excludes.

Since the only usage of this method makes sense for testing in prism itself,
the method is removed instead of deprecated.

https://github.com/ruby/prism/commit/31be379f98
2026-01-27 14:43:51 +00:00
Earlopain
5f25420918 [ruby/prism] Fix on_words_sep for ripper translator with newlines
Ripper emits a token each per line.

https://github.com/ruby/prism/commit/4b5c9f5437
2026-01-26 11:34:49 +00:00
Earlopain
8aedb89681 [ruby/prism] Also handle BasicObject as a return value
We should touch these as little as possible and just pass them along

https://github.com/ruby/prism/commit/52c4fa785e
2026-01-21 13:21:37 +00:00
Benoit Daloze
913ffcd1dd [ruby/prism] Check using Prism nodes if a command call has any arguments in Ripper translator
* We don't know what `on_*` events might return so we cannot assume it's an Array.
* See https://github.com/ruby/prism/issues/3838#issuecomment-3774702396

https://github.com/ruby/prism/commit/bed4271ce2
2026-01-21 13:21:37 +00:00
Earlopain
9ad8dd00b1 [ruby/prism] Fix on_* return value of ripper translator
You're supposed to return the first argument.
```rb
# Before
[[:stmts_new], [:rescue_mod, nil, nil], [:stmts_add, nil, nil], [:program, nil]]
# After
[[:stmts_new], [:rescue_mod, "1", "2"], [:stmts_add, nil, "1"], [:program, nil]]
```

The correct result would be:
`[[:rescue_mod, "1", "2"], [:stmts_new], [:stmts_add, nil, "1"], [:program, nil]]`

But the order depends on the prism AST so it seems very difficult to match.

https://github.com/ruby/prism/commit/94e0107729
2026-01-20 20:23:18 +00:00
Earlopain
2842e61c92 Reapply "[ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper"
This reverts commit 58f1127b51cf4fbb1f334f8701a041f40701dca2.
2026-01-20 14:18:30 +01:00
Hiroshi SHIBATA
58f1127b51
Revert "[ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper"
This reverts commit 35a7b5159f39de2cac848c072674e5350cc41aa4.

This broke syntax_suggest.

https://github.com/ruby/ruby/actions/runs/21167011751/job/60874111912
2026-01-20 19:10:16 +09:00
Benoit Daloze
35a7b5159f [ruby/prism] Add Ripper :on_sp events for Prism.lex_compat and Prism::Translation::Ripper
* Handle line continuations.
* Handle space at the end of file in LexCompat.

https://github.com/ruby/prism/commit/32bd13eb7d

Co-authored-by: Earlopain <14981592+Earlopain@users.noreply.github.com>
2026-01-20 09:53:08 +00:00
Benoit Daloze
859920dfd2 [ruby/prism] Add Prism::Source#line_to_byte_offset and replace direct accesses to offsets
https://github.com/ruby/prism/commit/ff81a29ba5
2026-01-19 12:03:33 +00:00
Earlopain
3c9ca23ba4 [ruby/prism] Remove duplicate lex tests
`RipperTest` already does this (added in https://github.com/ruby/prism/pull/3849)
Since it doesn't use the token classes, it also lists out all the excludes instead of just claiming some are passing.

https://github.com/ruby/prism/commit/e86a28263c
2026-01-19 07:46:48 +00:00
Earlopain
d1dc4bdb2f [ruby/prism] Fix ripper translator for __END__
https://github.com/ruby/prism/commit/2792ac78ca
2026-01-18 14:07:06 +00:00
Earlopain
87147ba5e9 [ruby/prism] Make the ripper shim work with rdoc
The filter class is a 1:1 copy of ruby.

rdoc has 32 test failures. It seems to expect `on_sp` in some cases to render code as written.

https://github.com/ruby/prism/commit/74bb12c825
2026-01-16 20:19:26 +00:00
Earlopain
074a23ab77 [ruby/prism] Add Ripper.tokenize to translation layer
It's public API and trivial to implement.

https://github.com/ruby/prism/commit/e77545f8b5
2026-01-16 12:07:41 +00:00
Earlopain
c34c7def5a [ruby/prism] Fix locations for invalid syntax when using expect1_opening
Followup to https://github.com/ruby/prism/pull/3827

It sets the start to the opening but it should instead just
continue on as usual.
Fixes https://github.com/ruby/prism/issues/3851

Notice how the AST actually contains "123" in both the body and end keyword.

https://github.com/ruby/prism/commit/8f69c5af08
2026-01-15 21:15:34 +00:00
Earlopain
15939e3c30 [ruby/prism] Make irb work with the ripper shim
This is everything that `irb` uses. It works in their test-suite, but there are 20 failures when using the shim that I haven't looked into at all.

`parse` is not used by `irb`. `scan` is, and it's basically `parse` but also including errors. `irb` doesn't seem to care about the errors, so I didn't implement that.

https://github.com/ruby/prism/commit/2c5826b39f
2026-01-15 21:03:55 +00:00
Earlopain
ee1aa78bee [ruby/prism] Correctly expose ripper state
It is for example used by `irb`, `rdoc`, `syntax_suggest`

https://github.com/ruby/prism/commit/255aeb2485
2026-01-12 22:08:25 +00:00
Earlopain
a1ba9f5733 [ruby/prism] Use one file for versioned parser classes
One per version seems excessive.

Do note that `rubocop-ast` used to require individual parser files. I wouldn't consider that to be part of the API since everything is autoloaded.
From a GitHub code search, I didn't find anyone else doing it like that.

https://github.com/ruby/prism/commit/458f622c34
2026-01-12 16:13:08 +00:00
Nobuyoshi Nakada
8baaece6d9
[ruby/prism] [Bug #21831] Fix denominator of rational float literal
Denominators can contain underscores in fraction part as well as other
numeric literals.

[Bug #21831]: https://bugs.ruby-lang.org/issues/21831

https://github.com/ruby/prism/commit/e247cb58c7
2026-01-11 22:53:12 +09:00
Earlopain
16863f2ec1 [ruby/prism] Decouple ripper translator from ripper library
Ripper exposes Ripper::Lexer:State in its output, which is a bit of a problem. To make this work, I basically copy-pasted the implementation.

I'm unsure if that is acceptable and added a test to make sure that these values never go out of sync.
I don't imagine them changing often, prism maps them 1:1 for its own usage.

This also fixed the shim by accident. `Ripper.lex` went to `Translation::Ripper.lex` when it should have been the original. Removing the need for the original resolves that issue.

https://github.com/ruby/prism/commit/2c0bea076d
2026-01-08 18:35:26 +00:00
Earlopain
fc66de3e6b [ruby/prism] Remove unneeded ripper requires
Ripper is either not used or loaded where it is actually needed

https://github.com/ruby/prism/commit/a73a4fb00c
2026-01-08 18:35:25 +00:00
Thomas Marshall
14fbcf0e6e [ruby/prism] Report missing end errors at opening token
This commit adds an `expect1_opening` function that expects a token and
attaches the error to the opening token location rather than the current
position. This is useful for errors about missing closing tokens, where
we want to point to the line with the opening token rather than the end
of the file.

For example:

```ruby
def foo
def bar
def baz
       ^ expected an `end` to close the `def` statement
       ^ expected an `end` to close the `def` statement
       ^ expected an `end` to close the `def` statement
```

This would previously produce three identical errors at the end of the
file. After this commit, they would be reported at the opening token
location:

```ruby
def foo
^~~ expected an `end` to close the `def` statement
def bar
^~~ expected an `end` to close the `def` statement
def baz
^~~ expected an `end` to close the `def` statement
```

I considered using the end of the line where the opening token is
located, but in some cases that would be less useful than the opening
token location itself. For example:

```ruby
def foo def bar def baz
```

Here the end of the line where the opening token is located would be the
same for each of the unclosed `def` nodes.

https://github.com/ruby/prism/commit/2d7829f060
2025-12-29 14:12:20 +00:00
Thomas Marshall
8afd4fade6 [ruby/prism] Add unterminated construct tests
https://github.com/ruby/prism/commit/166764f794
2025-12-29 14:12:20 +00:00
Earlopain
e2c886dd66 [ruby/prism] Reject p(p a, &block => value) and similar
Redo of https://github.com/ruby/prism/pull/3669 with more tests

https://github.com/ruby/prism/commit/48b403ea79
2025-12-18 19:58:53 -05:00
Earlopain
76248400b7 [ruby/prism] Add Ruby 4.1 as a version specifier
https://github.com/ruby/prism/commit/138db9ccc4
2025-12-18 19:58:53 -05:00
Benoit Daloze
d9b03c9369 [ruby/prism] Fix assertions in location_test.rb
* assert_raise's 2nd argument is the failure message,
  shown when the expected exception is not raised.
  It's not the expected message.
  See https://github.com/test-unit/test-unit/issues/347

https://github.com/ruby/prism/commit/e3df994d47
2025-12-18 19:58:53 -05:00
Earlopain
465a86c341 [ruby/prism] Fix %Q with newline delimiter and heredoc interpolation
The lexer did not jump to the `heredoc_end`, causing the heredoc end delimiter
to be parsed twice.

Normally the heredocs get flushed when a newline is encountered. But because
the newline is part of the string delimiter, that codepath is not taken.

Fixes [Bug #21758]

https://github.com/ruby/prism/commit/7440eb4b11
2025-12-04 14:50:46 +00:00
Earlopain
17bcd71e42 [ruby/prism] Clean up test excludes
Mostly not having to list version-specific excludes when testing against ripper/parse.y

Also don't test new syntax additions against the parser gems. The version support
for them may (or may not) be expanded but we shouldn't bother while the ruby version
hasn't even released yet.
(ruby_parser translation is not versioned, so let as is for now)

I also removed excludes that have since been implemented by parse.y

https://github.com/ruby/prism/commit/e5a0221c37
2025-12-02 16:20:43 +00:00
Kevin Newton
3bd9583a52 [ruby/prism] Update unicode tables to match that of CRuby
The unicode version has been updated upstream, which means new
codepoints mapped to alpha/alnum/isupper flags. We need to update
our tables to match.

I'm purposefully not adding a version check here, since that is
such a large amount of code. It's possible that we could include
different tables depending on a macro (like UNICODE_VERSION) or
something to that effect, but it's such a minimal impact on the
running of the actual parser that I don't think it's necessary.

https://github.com/ruby/prism/commit/78925fe5b6
2025-11-30 04:24:06 +00:00
Kevin Newton
b1314f159e [ruby/prism] Fully destroy call operator write arguments
If we are about to delete a call operator write argument, it needs
to be removed from the list of block exits as well.

https://github.com/ruby/prism/commit/ebc91c2e39
2025-11-30 02:08:41 +00:00
Kevin Newton
7c2eb946e0 [ruby/prism] Fix label interpolated string
https://github.com/ruby/prism/commit/e3e2b1ed04
2025-11-29 19:48:30 +00:00
Kevin Newton
f2a6cb2dc8 [ruby/prism] Handle invalid string pattern key
When a pattern match is using a string as a hash pattern key and is
using it incorrectly, we were previously assuming it was a symbol.
In the case of an error, that's not the case. So we need to add a
missing node in this case.

https://github.com/ruby/prism/commit/f0b06d6269
2025-11-29 19:47:45 +00:00
Kevin Newton
b75cf83a33 [ruby/prism] Revert "Reject p(p a, &block => value) and similar"
https://github.com/ruby/prism/commit/fef2c20777
2025-11-23 21:36:19 +00:00
Earlopain
2870b7d7df [ruby/prism] Reject p(p a, &block => value) and similar
They were being parsed as `p((p a, &block) => value)`.
When we get to this point, we must not just have parsed a command call, always consuming the `=>` is not correct.

Closes [Bug #21622]

https://github.com/ruby/prism/commit/796ab0edf4
2025-11-23 18:15:15 +00:00
Thiago Araujo
ba47c2f033 [ruby/prism] Add tests to regexp_encoding_option_mismatch
related to #2667

https://github.com/ruby/prism/commit/44f075bae4
2025-11-20 20:09:19 +00:00
Earlopain
9de66a8c51 [ruby/prism] Remove now obsolete todos
https://github.com/ruby/prism/commit/b00d098f9a
2025-11-17 15:14:21 +00:00
Kevin Newton
8d0105824f Handle deeply nested capture variables syntax err
When there are nested capture variables inside of a pattern match
that has an alternation pattern, it is a syntax error. Currently it
only adds a syntax error when it is at the top level of the pattern.
2025-11-16 21:30:24 -05:00
Earlopain
bec69617a0 [ruby/prism] Reject endless method as a block parameter default
Fixes [Bug #21661]

https://github.com/ruby/prism/commit/475fa46a82
2025-11-14 16:27:38 +00:00
Nobuyoshi Nakada
f4b6a5191c [Feature #21572] Syntax error at capture in alternation pattern
Should fail even with `-c` option.
2025-11-14 21:03:04 +09:00
Earlopain
7037d8f89e [ruby/prism] Rename Ruby 3.5 to Ruby 4.0
See 6d81969b47

It leaves the old variant around. RuboCop for examples accesses `Prism::Translation::Parser35`
to test against ruby-head. For now I left these simply as an alias

https://github.com/ruby/prism/commit/d0a823f045
2025-11-08 00:22:17 +00:00
Nobuyoshi Nakada
f4e01783d3 Prism update for 4.0 2025-11-07 20:42:29 +09:00
Earlopain
d73eba5185 [ruby/prism] Reject def f a, (b) = 1
Fixes [#Bug 21660], followup to https://github.com/ruby/prism/pull/3674

https://github.com/ruby/prism/commit/fb445a49e5

Co-Authored-By: tomoya ishida <tomoyapenguin@gmail.com>
2025-11-06 13:31:46 +00:00
Earlopain
99382f7461 [ruby/prism] Unescape unary method calls
Followup to https://github.com/ruby/prism/pull/2213

Before:
```sh
$ ruby -ve "puts 42.~@"
ruby 3.4.6 (2025-09-16 revision https://github.com/ruby/prism/commit/dbd83256b1) +PRISM [x86_64-linux]
-e:1:in '<main>': undefined method '~@' for an instance of Integer (NoMethodError)
Did you mean?  ~
```

After (matches parse.y):
```sh
$ ./miniruby -ve "puts 42.~@"
ruby 3.5.0dev (2025-10-16T03:40:45Z master https://github.com/ruby/prism/commit/1d95d75c3f) +PRISM [x86_64-linux]
-43
```

https://github.com/ruby/prism/commit/a755bf228f
2025-10-30 13:05:51 +00:00
Earlopain
4c60fc48b1 [ruby/prism] Test against parse.y
17a6a19bba broke ruby/ruby CI
because some tests are only run against parse.y
This will catch that in the future.

https://github.com/ruby/prism/commit/98e1cd5c04
2025-10-22 17:11:46 +00:00
Earlopain
6047eada20 [ruby/prism] Make error and snapshot tests multi-version aware
This one has been on my mind for a while now.

Currently, there are only tests against the latest syntax version.

This changes the snapshot structure as follows:
* Snapshots at their current location are tested against all syntax versions
* Snapshots inside a version folder like "3.3" are tested against all versions starting from that version
* Snapshots inside a version folder like "3.3-4.2" are tested against all versions in the given range.

This makes sure that as new syntax is added, older versions still work as expected.
I also added a few tests for now valid syntax that should be invalid in older versions (and the other way around as well)

These tests run really fast. So even though it does 3x the work for these, I am still able to run the whole test suite in just 11 seconds.

https://github.com/ruby/prism/commit/5191b1aa68
2025-10-22 14:50:11 +00:00
Kevin Newton
68f45a6da7 [ruby/prism] Do not rely on RUBY_VERSION being consistent
https://github.com/ruby/prism/commit/34428946db
2025-10-16 14:38:14 +00:00
Kevin Newton
cea3307fe6 [ruby/prism] Do not stub Ruby version
https://github.com/ruby/prism/commit/44c4306247
2025-10-16 14:10:39 +00:00
Earlopain
f5d3b6e626 [ruby/prism] Add support for Prism.parse(foo, version: "current")
The docs currently say to use `Prism.parse(foo, version: RUBY_VERSION)` for this.
By specifying "current" instead, we can have prism raise a more specifc error.

Note: Does not use `ruby_version` from `ruby/version.h` because writing a test for that is not really possible.
`RUBY_VERSION` is nicely stubbable for both the c-ext and FFI backend.

https://github.com/ruby/prism/commit/9c5cd205cf
2025-10-16 12:34:14 +00:00