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

Handling trailing whitespace in Heredoc #8692

Merged
merged 3 commits into from Oct 16, 2020
Merged

Conversation

marcandre
Copy link
Contributor

@marcandre marcandre commented Sep 10, 2020

I extracted #8695 to remove all trailing whitespaces in our own codebase.

This PR fixes Layout/TrailingWhitespace auto-correction in Heredocs to be safe. Instead of removing the trailing whitespace (which is never equivalent), it inserts #{} after it (which evaluates to an empty string) and thus makes the trailing whitespace no longer trailing. Maybe a more explicit form like #{ '' } or #{ :trailing_whitespace!; '' } would be better though?

Given the fact that we can now autocorrect correctly trailing whitespaces in heredoc, and that they can be a pain to deal with for Rubyists like me that set their editor to automatically trim their whitesapce, I feel that the default should be changed in general. I assume that most projects have much less occurrences of trailing whitespace in their heredoc anyways.

@marcandre
Copy link
Contributor Author

Looks like I need to review my PR, some of these trailing whitespaces were actually a mistake. It doesn't invalidate the rest of the discussion (quite the contrary)

@marcandre
Copy link
Contributor Author

So I found 10 useless trailing whitespaces in our own code...

I tweaked the auto-correction to not do anything for static heredocs <<~'RUBY' inside of which there is no interpolation. I imagine these cases are extremely rare.

@marcandre marcandre marked this pull request as ready for review September 10, 2020 17:31
@marcandre marcandre mentioned this pull request Sep 10, 2020
@marcandre marcandre force-pushed the whitespace branch 4 times, most recently from 61e69c2 to 91ddd7a Compare September 10, 2020 21:37
@bbatsov
Copy link
Collaborator

bbatsov commented Sep 13, 2020

This PR fixes Layout/TrailingWhitespace auto-correction in Heredocs to be safe. Instead of removing the trailing whitespace (which is never equivalent), it inserts #{} after it (which evaluates to an empty string) and thus makes the trailing whitespace no longer trailing. Maybe a more explicit form like #{ '' } or #{ :trailing_whitespace!; '' } would be better though?

I agree with the general premise, but I'm wondering if that won't be a bit confusing. It would certainly confuse me if I didn't read your explanations in the PR's description. :-)

Given the fact that we can now autocorrect correctly trailing whitespaces in heredoc, and that they can be a pain to deal with for Rubyists like me that set their editor to automatically trim their whitesapce, I feel that the default should be changed in general. I assume that most projects have much less occurrences of trailing whitespace in their heredoc anyways.

Fine by me.

@bbatsov
Copy link
Collaborator

bbatsov commented Sep 13, 2020

I also think that if we go down this road it'd be nice to expand the cop description with some of the rationale outlined in the PR's description.

@marcandre
Copy link
Contributor Author

Another possibility would be to replace the trailing whitespace(s) by the interpolation:

hello # + 1 space
world         # + 8 spaces
# corrected to:
hello#{ ' ' }
world#{ '        ' }

Is that a better auto-correction?

@bbatsov
Copy link
Collaborator

bbatsov commented Sep 14, 2020

It seems better/clearer to me.

@marcandre
Copy link
Contributor Author

PR updated. I also realized I had to modify Lint/LiteralInterpolation to accept those without complaining...

@marcandre marcandre force-pushed the whitespace branch 3 times, most recently from ea57399 to 8cd6c7d Compare September 28, 2020 05:46
@marcandre
Copy link
Contributor Author

Note: I used a NodePattern with a Regexp (I didn't think I'd use those so soon!) so I bumped the rubocop-ast gem to the latest/

Looks like there's a dependency issue though with JRuby... I'll check that tomorrow

@lucywyman
Copy link

This ends up resulting in infinite recursion for us - I'm not sure how to appease the cop, other than just disabling it around heredocs?
Code

Inspecting 105 files
.....W

Offenses:

lib/bolt/bolt_option_parser.rb:366:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
lib/bolt/bolt_option_parser.rb:366:11: W: [Corrected] Lint/EmptyInterpolation: Empty interpolation detected.
          #{}
          ^^^
lib/bolt/bolt_option_parser.rb:386:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
lib/bolt/bolt_option_parser.rb:386:2: W: [Corrected] Lint/EmptyInterpolation: Empty interpolation detected.
 #{}
 ^^^
lib/bolt/bolt_option_parser.rb:418:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
lib/bolt/bolt_option_parser.rb:418:2: W: [Corrected] Lint/EmptyInterpolation: Empty interpolation detected.
 #{}
 ^^^
lib/bolt/bolt_option_parser.rb:482:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
lib/bolt/bolt_option_parser.rb:482:2: W: [Corrected] Lint/EmptyInterpolation: Empty interpolation detected.
 #{}
 ^^^
lib/bolt/bolt_option_parser.rb:485:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
lib/bolt/bolt_option_parser.rb:485:2: W: [Corrected] Lint/EmptyInterpolation: Empty interpolation detected.
 #{}
 ^^^

5 files inspected, 10 offenses detected, 10 offenses corrected
Infinite loop detected in /home/lucy/githubs/bolt/lib/bolt/bolt_option_parser.rb and caused by Layout/TrailingWhitespace -> Lint/EmptyInterpolation
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:304:in `check_for_infinite_loop'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:287:in `block in iterate_until_no_changes'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:286:in `loop'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:286:in `iterate_until_no_changes'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:255:in `do_inspection_loop'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:132:in `block in file_offenses'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:157:in `file_offense_cache'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:131:in `file_offenses'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:122:in `process_file'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:101:in `block in each_inspected_file'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:100:in `each'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:100:in `reduce'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:100:in `each_inspected_file'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:86:in `inspect_files'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/runner.rb:47:in `run'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli/command.rb:11:in `run'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli/environment.rb:18:in `run'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli.rb:65:in `run_command'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli.rb:72:in `execute_runners'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/lib/rubocop/cli.rb:41:in `run'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/exe/rubocop:13:in `block in <top (required)>'
/home/lucy/.rvm/rubies/ruby-2.6.3/lib/ruby/2.6.0/benchmark.rb:308:in `realtime'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/gems/rubocop-1.0.0/exe/rubocop:12:in `<top (required)>'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/bin/rubocop:23:in `load'
/home/lucy/githubs/bolt/vendor/bundle/ruby/2.6.0/bin/rubocop:23:in `<top (required)>'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `load'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `kernel_load'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:28:in `run'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli.rb:476:in `exec'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
/home/lucy/.rvm/gems/ruby-2.6.3/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
/home/lucy/.rvm/gems/ruby-2.6.3/bin/bundle:23:in `load'
/home/lucy/.rvm/gems/ruby-2.6.3/bin/bundle:23:in `<main>'

@marcandre
Copy link
Contributor Author

I'm sorry @lucywyman, looks like I wrote the right code but somehow later worked from an older version with the empty #{} (probably when switching computer and not updating my local branch).
I'll fix this asap.

@marcandre
Copy link
Contributor Author

marcandre commented Oct 21, 2020

#8914 should restore our original intent and fix the issue.

Until the next bugfix release, you can either fix them manually, or set your config with:

Layout/TrailingWhitespace:
  AllowInHeredoc: true

To fix them manually, either remove the trailing whitespace, or replace it with #{' '}

Thanks for reporting this, and again sorry for the trouble.

@lucywyman
Copy link

No prob! Thanks for addressing it so quickly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants