Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stree write turns correct code into incorrect code for method call with mix of keyword types #446

Open
bradleybuda opened this issue Mar 24, 2024 · 0 comments · May be fixed by #450
Open

Comments

@bradleybuda
Copy link

When calling a method with multiple keyword values, where one of the keywords is "static" and another is "dynamic" (for lack of better terms), stree write emits bad code. Possibly related to #419 but I'm not 100% certain. A minimal example:

Input

def search(keyword:, author: nil, category: nil)
  # implementation elided
end

keyword = 'Ruby'
facet = :author
value = 'Matz'

search(facet => value, keyword:)

Formatted Output

def search(keyword:, author: nil, category: nil)
  # implementation elided
end

keyword = "Ruby"
facet = :author
value = "Matz"

search(facet => value, :keyword =>)

This is with the latest released version (6.2.0). Here's a full transcript of the commands I ran, just in case I missed something:

% cat before.rb
def search(keyword:, author: nil, category: nil)
  # implementation elided
end

keyword = 'Ruby'
facet = :author
value = 'Matz'

search(facet => value, keyword:)

% cp before.rb after.rb

% bundle exec stree version
6.2.0

% bundle exec stree write after.rb
after.rb 2ms

% cat after.rb
def search(keyword:, author: nil, category: nil)
  # implementation elided
end

keyword = "Ruby"
facet = :author
value = "Matz"

search(facet => value, :keyword =>)

% ruby before.rb

% ruby after.rb
after.rb: --> after.rb
syntax error, unexpected ')'
> 1  def search(keyword:, author: nil, category: nil)
> 3  end
> 5  keyword = "Ruby"
> 6  facet = :author
> 7  value = "Matz"
> 9  search(facet => value, :keyword =>)

after.rb:9: syntax error, unexpected ')' (SyntaxError)
...ch(facet => value, :keyword =>)
...                              ^

% ruby --version
ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [arm64-darwin23]
bradleybuda added a commit to bradleybuda/syntax_tree that referenced this issue Apr 5, 2024
The existing assoc formatter has logic to identify the case where a
value is nil (in a Ruby-3.1 style hash) and preserve the existing
formatting. For example: `{ first:, "second" => "value" }` is correctly
left as-is.

However, this logic only worked if the first assoc in the
container had the nil value - if a later assoc had a nil value, the
Identity formatter might not be chosen which could cause the formatter
to generate invalid Ruby code.

As an example, this code: `{ "first" => "value", second: }` would be
turned into `{ "first" => "value", :second => }`.

This patch pulls the nil value check up to the top of
`HashKeyFormatter.for` to ensure it takes precendence over any other
formatting selections. The fixtures have been updated to cover both
cases (nil value in first position, nil value in last position).

Fixes ruby-syntax-tree#446
@bradleybuda bradleybuda linked a pull request Apr 5, 2024 that will close this issue
bradleybuda added a commit to bradleybuda/syntax_tree that referenced this issue Apr 5, 2024
The existing assoc formatter has logic to identify the case where a
value is nil (in a Ruby-3.1 style hash) and preserve the existing
formatting. For example: `{ first:, "second" => "value" }` is correctly
left as-is.

However, this logic only worked if the first assoc in the
container had the nil value - if a later assoc had a nil value, the
Identity formatter might not be chosen which could cause the formatter
to generate invalid Ruby code.

As an example, this code: `{ "first" => "value", second: }` would be
turned into `{ "first" => "value", :second => }`.

This patch pulls the nil value check up to the top of
`HashKeyFormatter.for` to ensure it takes precendence over any other
formatting selections. The fixtures have been updated to cover both
cases (nil value in first position, nil value in last position).

Fixes ruby-syntax-tree#446
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant