Skip to content

Commit 40b7eb8

Browse files
committed
Add prism parser support
Resolves #385 Related Prism bug: ruby/prism#3540 (merged) `test/corpus/literal/before/34.rb` contains expressions rejected by Prism (and regexp-related bug, see #385 (comment)): ```bash $ ASDF_RUBY_VERSION=3.4.2 ruby --parser prism test/corpus/literal/before/34.rb test/corpus/literal/before/34.rb:1: syntax errors found (SyntaxError) > 1 | retry | ^~~~~ Invalid retry without rescue > 2 | in {"#{"a"}": 1} then | ^~ unexpected 'in', ignoring it | ^~~~ unexpected 'then', ignoring it | ^~~~ unexpected 'then', expecting end-of-input 3 | true 4 | /\c*a/ 5 | /\c*a\c*/ 6 | /\c*\c*\c*/ > 7 | (break foo) || a | ^~~~~~~~~ Invalid break | ^~~~~~~~~ unexpected void value expression > 8 | (return foo) || a | ^~~~~~~~~~ unexpected void value expression > 9 | a = b || break | ^~~~~ Invalid break > 10 | a = b || next | ^~~~ Invalid next > 11 | a || (break foo) | ^~~~~~~~~ Invalid break > 12 | b or break | ^~~~~ Invalid break > 13 | b or next | ^~~~ Invalid next > 14 | break or b | ^~~~~ Invalid break | ^~~~~ unexpected void value expression > 15 | next or b | ^~~~ Invalid next | ^~~~ unexpected void value expression > 16 | return or a | ^~~~~~ unexpected void value expression ```
1 parent 315c6ec commit 40b7eb8

File tree

24 files changed

+540
-344
lines changed

24 files changed

+540
-344
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
fail-fast: false
2121
matrix:
22-
ruby: [ruby-3.2, ruby-3.3]
22+
ruby: [ruby-3.2, ruby-3.3, ruby-3.4]
2323
os: [ubuntu-latest]
2424
steps:
2525
- uses: actions/checkout@v4
@@ -35,7 +35,7 @@ jobs:
3535
strategy:
3636
fail-fast: false
3737
matrix:
38-
ruby: [ruby-3.2, ruby-3.3]
38+
ruby: [ruby-3.2, ruby-3.3, ruby-3.4]
3939
os: [ubuntu-latest]
4040
steps:
4141
- uses: actions/checkout@v4
@@ -53,7 +53,7 @@ jobs:
5353
strategy:
5454
fail-fast: false
5555
matrix:
56-
ruby: [ruby-3.2, ruby-3.3]
56+
ruby: [ruby-3.2, ruby-3.3, ruby-3.4]
5757
os: [ubuntu-latest]
5858
steps:
5959
- uses: actions/checkout@v4
@@ -69,7 +69,7 @@ jobs:
6969
strategy:
7070
fail-fast: false
7171
matrix:
72-
ruby: [ruby-3.2, ruby-3.3]
72+
ruby: [ruby-3.2, ruby-3.3, ruby-3.4]
7373
os: [ubuntu-latest]
7474
steps:
7575
- uses: actions/checkout@v4
@@ -85,7 +85,7 @@ jobs:
8585
strategy:
8686
fail-fast: false
8787
matrix:
88-
ruby: [ruby-3.2, ruby-3.3]
88+
ruby: [ruby-3.2, ruby-3.3, ruby-3.4]
8989
os: [ubuntu-latest]
9090
steps:
9191
- uses: actions/checkout@v4

.rspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--color
22
--format progress
3-
--warnings
3+
# --warnings
44
--order random
55
--require spec_helper

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ruby 3.4.3

Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Unreleased
2+
3+
[#387](https://github.com/mbj/unparser/pull/387)
4+
5+
* Add `prism` parser support for Ruby 3.4. ([viralpraxis](https://github.com/viralpraxis))
6+
17
# v0.7.0 2025-03-16
28

39
[#366](https://github.com/mbj/unparser/pull/366)

Gemfile.lock

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@ PATH
44
unparser (0.7.0)
55
diff-lcs (~> 1.6)
66
parser (>= 3.3.0)
7+
prism (>= 1.4)
78

89
GEM
910
remote: https://rubygems.org/
1011
specs:
1112
ast (2.4.3)
13+
date (3.4.1)
1214
diff-lcs (1.6.1)
15+
io-console (0.8.0)
16+
irb (1.15.2)
17+
pp (>= 0.6.0)
18+
rdoc (>= 4.0.0)
19+
reline (>= 0.4.2)
1320
json (2.10.2)
1421
language_server-protocol (3.17.0.4)
1522
lint_roller (1.1.0)
@@ -26,10 +33,20 @@ GEM
2633
parser (3.3.8.0)
2734
ast (~> 2.4.1)
2835
racc
36+
pp (0.6.2)
37+
prettyprint
38+
prettyprint (0.2.0)
2939
prism (1.4.0)
40+
psych (5.2.3)
41+
date
42+
stringio
3043
racc (1.8.1)
3144
rainbow (3.1.1)
45+
rdoc (6.13.1)
46+
psych (>= 4.0.0)
3247
regexp_parser (2.10.0)
48+
reline (0.6.1)
49+
io-console (~> 0.5)
3350
rspec (3.13.0)
3451
rspec-core (~> 3.13.0)
3552
rspec-expectations (~> 3.13.0)
@@ -65,6 +82,7 @@ GEM
6582
rubocop (>= 1.72.1, < 2.0)
6683
ruby-progressbar (1.13.0)
6784
sorbet-runtime (0.5.12028)
85+
stringio (3.1.7)
6886
unicode-display_width (3.1.4)
6987
unicode-emoji (~> 4.0, >= 4.0.4)
7088
unicode-emoji (4.0.4)
@@ -74,6 +92,7 @@ PLATFORMS
7492
x86_64-linux
7593

7694
DEPENDENCIES
95+
irb
7796
mutant (~> 0.13.0)
7897
mutant-rspec (~> 0.13.0)
7998
rspec (~> 3.13)

bin/corpus

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module Unparser
2424
# rubocop:disable Metrics/AbcSize
2525
# rubocop:disable Metrics/MethodLength
2626
def verify
27-
puts("Verifiying: #{name}")
27+
puts("Verifying: #{name}")
2828
checkout
2929

3030
paths = Pathname.glob(Pathname.new(repo_path).join('**/*.rb'))

bin/parser-prism-round-trip-test

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
require 'unparser'
5+
require 'prism'
6+
require 'fileutils'
7+
require 'pathname'
8+
9+
module PrismParser
10+
PARSER = 'ruby/prism'
11+
PARSER_VERSION = Prism::VERSION
12+
PARSER_PATH = Pathname('tmp/parser-prism')
13+
14+
PRISM_INVALID = Set[
15+
'def __ENCODING__.a',
16+
'def __FILE__.a',
17+
'def __LINE__.a',
18+
'\777',
19+
'ち\xE3\x81\xFF',
20+
'\x8E\x01',
21+
'a\xE9b',
22+
'a\247b',
23+
'\xE3\xD3\x8B\xE3\x83\xBC\x83\xE3\x83\xE3\x82\xB3\xA3\x82\x99',
24+
'hello \u{fc}',
25+
'# encoding: sjis'
26+
].freeze
27+
28+
PRISM_TODO = Set[
29+
'def a(...); "foo#{b(...)}"; end',
30+
'(a,), = []',
31+
'`
32+
foo\
33+
b\nar
34+
`',
35+
].freeze
36+
37+
PRISM_NO_ROUND_TRIP = (PRISM_INVALID + PRISM_TODO).to_set.freeze
38+
39+
private_constant :PRISM_INVALID, :PRISM_TODO
40+
41+
class << self
42+
def prepare # rubocop:disable Metrics
43+
FileUtils.rm_rf("#{PARSER_PATH}/test/prism/fixtures-tmp")
44+
Dir.mkdir("#{PARSER_PATH}/test/prism/fixtures-tmp")
45+
Dir.glob("#{PARSER_PATH}/test/prism/fixtures/**/*.txt")
46+
.reject { _1.include?('unparser/') }
47+
.each do |path|
48+
examples = File.read(path).split(/(?<=\n\n)/).reject do |example|
49+
PRISM_NO_ROUND_TRIP.any? { |snippet| example.include?(snippet) }
50+
end
51+
path = Pathname(path).relative_path_from("#{PARSER_PATH}/test/prism/fixtures").to_s
52+
path = "#{PARSER_PATH}/test/prism/fixtures-tmp/#{path}"
53+
54+
dirname = File.dirname(path)
55+
unless File.directory?(dirname)
56+
FileUtils.mkdir_p(dirname)
57+
end
58+
File.write(path, examples.join("\n\n"))
59+
end
60+
end
61+
62+
def target_glob
63+
"#{PARSER_PATH}/test/prism/fixtures-tmp/**/*.txt"
64+
end
65+
66+
def excludes
67+
%w[
68+
spanning_heredoc
69+
heredocs_with_fake_newlines
70+
heredocs_nested
71+
].to_set { |file| "#{PARSER_PATH}/test/prism/fixtures-tmp/#{file}.txt" }
72+
end
73+
74+
end
75+
end
76+
77+
unless PrismParser::PARSER_PATH.exist?
78+
Kernel.system(
79+
*%W[
80+
git
81+
clone
82+
https://github.com/#{PrismParser::PARSER}
83+
#{PrismParser::PARSER_PATH}
84+
],
85+
exception: true
86+
)
87+
end
88+
89+
Dir.chdir(PrismParser::PARSER_PATH) do
90+
Kernel.system(
91+
*%W[
92+
git
93+
checkout
94+
v#{PrismParser::PARSER_VERSION}
95+
],
96+
exception: true
97+
)
98+
Kernel.system(*%w[git clean --force -d -X], exception: true)
99+
end
100+
101+
ignores_cli_option = PrismParser.excludes.flat_map { |file| ['--ignore', file] }
102+
103+
PrismParser.prepare
104+
exit Unparser::CLI.run([PrismParser.target_glob, *ignores_cli_option])

0 commit comments

Comments
 (0)