Skip to content

Ruby 3.0 parser might be incorrect #347

@ofedoren

Description

@ofedoren

Starting Ruby 3.0, there is a difference between passing a hash or list of keywords as a method arguments. But Ruby 3.0 parser returns the same result for RubyParser::V30.new.parse:

code = "variable.method(a: 1)"
RubyParser::V30.new.parse(code)
#=> s(:call, s(:call, nil, :variable), :method, s(:hash, s(:lit, :a), s(:lit, 1)))

code = "variable.method({a: 1})"
RubyParser::V30.new.parse(code)
#=> s(:call, s(:call, nil, :variable), :method, s(:hash, s(:lit, :a), s(:lit, 1)))

Note that the result is the same, but it will lead to errors trying to execute it back via Ruby2Ruby if method has def method(hash, kw: 1) signature.

I've tried to make up with easier example. Noticed this error when looking at how is "kwargs = { b_keyword: false }; @article.method_with_kwargs('positional', a_keyword: true, **kwargs)" parsed:

s(:block,
 s(:lasgn, :kwargs, s(:hash, s(:lit, :b_keyword), s(:false))),
 s(:call, s(:ivar, :@article), :method_with_kwargs, s(:str, "positional"), s(:hash, s(:lit, :a_keyword), s(:true), s(:kwsplat, s(:lvar, :kwargs)))))

Note that a_keyword becomes part of hash, even though it's obviously an explicit keyword. Moreover, **kwargs then become part of the same hash, which is just wrong. It sometimes work, just because { :a_keyword => true, **kwargs } is being naively extracted in https://github.com/seattlerb/ruby2ruby/blob/master/lib/ruby2ruby.rb#L262-L265.

Could you please tell me if it's expected or it's a bug?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions