Skip to content

Commit f2709e4

Browse files
committed
Support multi versioning for Prism::Translation::Parser
## Summary I'm working on integrating Prism into RuboCop. This PR introduces `Prism::Translation::Parser33` and `Prism::Translation::Parser34`, named in accordance with the following comments. rubocop/rubocop#12600 (comment) Currently, `Prism::Translation::Parser` always operates in Ruby 3.4 mode. This means it will not parse as Ruby 3.3 even if `TargetRubyVersion: 80_82_73_83_77.33` is specified. Therefore, the `it` introduced in Ruby 3.4 is parsed incompatibly with Ruby 3.3. In Ruby 3.3, the expected name for an `lvar` is `:it`, not `:"0it"`. ### Expected AST The following is an expected AST when parsing Ruby 3.3 code: ```console $ bundle exec ruby -rprism -rprism/translation/parser33 -ve "p Prism::Translation::Parser33.parse('items.map { it.do_something }')" ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:block, s(:send, s(:send, nil, :items), :map), s(:args), s(:send, s(:send, nil, :it), :do_something)) ``` ### Actual AST The following is an actual AST when parsing Ruby 3.3 code: ```console $ ruby -rprism -ve "p Prism::Translation::Parser.parse('items.map { it.do_something }')" ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22] s(:block, s(:send, s(:send, nil, :items), :map), s(:args), s(:send, s(:lvar, :"0it"), :do_something)) ``` `Prism::Translation::Parser33` and `Prism::Translation::Parser34` aim to correspond to Ruby 3.3 and Ruby 3.4, respectively. And, The hack of specifying `TargetRubyVersion: 80_82_73_83_77.33` is expected to become unnecessary in the future, but the behavior will be maintained until RuboCop's support is finalized: rubocop/rubocop#12600 (comment) ## Additional Information A private method named `convert_for_prism` is prepared to convert the `version` from Parser to the `version` expected by Prism. For example, a Parser-compatible value is `3.3`, whereas Prism expects `"3.3.0"`. `Parser#version` is not used in RuboCop, but it's unclear how it is utilized in other libraries that rely on the Parser gem. Therefore, logic to maintain compatibility between Parser and Prism is implemented.
1 parent cf0369a commit f2709e4

5 files changed

Lines changed: 46 additions & 5 deletions

File tree

lib/prism/translation/parser.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def parse(source_buffer)
4343
source = source_buffer.source
4444

4545
offset_cache = build_offset_cache(source)
46-
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
46+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
4747

4848
build_ast(result.value, offset_cache)
4949
ensure
@@ -56,7 +56,7 @@ def parse_with_comments(source_buffer)
5656
source = source_buffer.source
5757

5858
offset_cache = build_offset_cache(source)
59-
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
59+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
6060

6161
[
6262
build_ast(result.value, offset_cache),
@@ -75,7 +75,7 @@ def tokenize(source_buffer, recover = false)
7575
offset_cache = build_offset_cache(source)
7676
result =
7777
begin
78-
unwrap(Prism.parse_lex(source, filepath: source_buffer.name), offset_cache)
78+
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
7979
rescue ::Parser::SyntaxError
8080
raise if !recover
8181
end
@@ -168,6 +168,17 @@ def build_range(location, offset_cache)
168168
)
169169
end
170170

171+
def convert_for_prism(version)
172+
case version
173+
when 33
174+
"3.3.0"
175+
when 34
176+
"3.4.0"
177+
else
178+
"latest"
179+
end
180+
end
181+
171182
require_relative "parser/compiler"
172183
require_relative "parser/lexer"
173184

lib/prism/translation/parser/rubocop.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@ class Parser
1212
# This is the special version number that should be used in rubocop
1313
# configuration files to trigger using prism.
1414
VERSION_3_3 = 80_82_73_83_77.33
15+
VERSION_3_4 = 80_82_73_83_77.34
1516

1617
# This module gets prepended into RuboCop::AST::ProcessedSource.
1718
module ProcessedSource
1819
# Redefine parser_class so that we can inject the prism parser into the
1920
# list of known parsers.
2021
def parser_class(ruby_version)
2122
if ruby_version == Prism::Translation::Parser::VERSION_3_3
22-
require "prism/translation/parser"
23-
Prism::Translation::Parser
23+
require "prism/translation/parser33"
24+
Prism::Translation::Parser33
25+
if ruby_version == Prism::Translation::Parser::VERSION_3_4
26+
require "prism/translation/parser34"
27+
Prism::Translation::Parser34
2428
else
2529
super
2630
end

lib/prism/translation/parser33.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require_relative "parser"
2+
3+
module Prism
4+
module Translation
5+
# This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`.
6+
class Parser33 < Parser
7+
def version # :nodoc:
8+
33
9+
end
10+
end
11+
end
12+
end

lib/prism/translation/parser34.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require_relative "parser"
2+
3+
module Prism
4+
module Translation
5+
# This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`.
6+
class Parser34 < Parser
7+
def version # :nodoc:
8+
34
9+
end
10+
end
11+
end
12+
end

prism.gemspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ Gem::Specification.new do |spec|
8787
"lib/prism/serialize.rb",
8888
"lib/prism/translation.rb",
8989
"lib/prism/translation/parser.rb",
90+
"lib/prism/translation/parser33.rb",
91+
"lib/prism/translation/parser34.rb",
9092
"lib/prism/translation/parser/compiler.rb",
9193
"lib/prism/translation/parser/lexer.rb",
9294
"lib/prism/translation/parser/rubocop.rb",

0 commit comments

Comments
 (0)