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

rubocop: generate_completions DSL #13553

Merged
merged 31 commits into from
Sep 6, 2022

Conversation

max-ae
Copy link
Contributor

@max-ae max-ae commented Jul 13, 2022

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

related to #13536

needs Homebrew/homebrew-core#105707

cc @Rylan12

I have achieved to implement a preliminary RuboCop, but I will appreciate any feedback, since I'm sure there's room for improvement.

The Cop is able to correct

(bash_completion/"foo").write Utils.safe_popen_read(bin/"foo", "completions", "bash")

but I have been unable to come up with a solution to get and replace with all shells whilst only walking the AST once.

The Cop also warns for the

output = Utils.safe_popen_read(bin/"foo", "completion", "bash")
(bash_completion/"foo").write output

pattern, but has no corrector, as discussed in #13536.

Please feel free to push any commits improving my implementation 😄

@Rylan12
Copy link
Member

Rylan12 commented Jul 13, 2022

but I have been unable to come up with a solution to get and replace with all shells whilst only walking the AST once.

Not sure, I guess I haven't tried. I think you could probably write a pattern that checks for multiple instances right after each other. That would probably be pretty easy to implement. You also could probably do something like this (not tested at all):

def audit_formula(_node, _class_node, _parent_class_node, body_node)
  install = find_method_def(body_node, :install)

  completion_nodes_to_fix = []

  correctable_shell_completion_node(install) do |node, shell, base_name, binary, cmd, shell_parameter|
    ...

    # Instead of calling `offending_node` and `problem`:
    completion_nodes_to_fix << [node, replacement]
  end

  completion_nodes_to_fix[0...-1].each do |node, _|
    offending_node(node)
    # The wording here is terrible but is just an example
    problem "Use a single `generate_completions` call to generate completions" do |corrector|
      corrector.replace(@offensive_node.source_range, "")
    end
  end

  # Create the single `generate_completions` call
  offending_node(completion_nodes_to_fix.last.first)
  problem "Use `#{replacement}` instead of `#{@offensive_node.source}`." do |corrector|
    corrector.replace(@offensive_node.source_range, replacement)
  end
end

That's just an example, I haven't thought through the logic very thoroughly so there might be a better way to do it.

If those don't work, you could probably write a separate rubocop that combines all of the individual generate_completions calls into one combined call.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far! Unit tests for this should make it much easier to test.

@Rylan12
Copy link
Member

Rylan12 commented Jul 14, 2022

Looks good so far! Unit tests for this should make it much easier to test.

Ah yes, I forgot to mention tests in my initial comment. RuboCop tests are, luckily, pretty easy to make. I'd recommend looking at the ShellCommands test since it will be almost identical to what you need here. Happy to give more guidance if needed!

@max-ae
Copy link
Contributor Author

max-ae commented Jul 24, 2022

Thank you for the feedback and helpful example code! I'll update the PR with the proposed changes as soon as I refactored the DSL PR, and will also include Unit Tests when doing so.

@max-ae
Copy link
Contributor Author

max-ae commented Jul 27, 2022

Hello there! I have updated the PR to reflect the changes made in the DSL PR, and also included some other fixes.

I have also added another Cop to combine multiple calls with different shells into one.

The only thing I haven't been able to figure out is how to instruct the corrector to also remove the empty lines left behind, as can be seen in the homebrew/core example PR. I have looked into the source_range argument without success, but maybe @Rylan12 can give me a hint 😄

As soon as that is figured out, I will also add Unit tests.

Copy link
Member

@Rylan12 Rylan12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! I did leave a comment with a suggestion for the newline issue

Library/Homebrew/rubocops/lines.rb Outdated Show resolved Hide resolved
Library/Homebrew/rubocops/lines.rb Outdated Show resolved Hide resolved
Library/Homebrew/rubocops/lines.rb Outdated Show resolved Hide resolved
Library/Homebrew/rubocops/lines.rb Outdated Show resolved Hide resolved
Library/Homebrew/rubocops/lines.rb Outdated Show resolved Hide resolved
@max-ae max-ae marked this pull request as ready for review August 11, 2022 11:01
Copy link
Member

@Rylan12 Rylan12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the tests be moved to their own file in test/rubocops/lines/generate_completions_spec.rb?

@max-ae
Copy link
Contributor Author

max-ae commented Aug 11, 2022

Can the tests be moved to their own file in test/rubocops/lines/generate_completions_spec.rb?

Sure, done!

@max-ae
Copy link
Contributor Author

max-ae commented Sep 5, 2022

I have now extended the tests. 😄

Now that Homebrew/homebrew-core#105707 is also merged, this should be good to go if CI passes 🎉

@max-ae
Copy link
Contributor Author

max-ae commented Sep 5, 2022

Yeah, I'm gonna need some help with that CI error...
I feel like I am missing a return unless somewhere?

2022-09-05T17:58:39.3127476Z �[31mAn error occurred while FormulaAudit/GenerateCompletionsDSL cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:39.3130785Z To see the complete backtrace run rubocop -d.
2022-09-05T17:58:39.3134252Z �[31mAn error occurred while FormulaAudit/SingleGenerateCompletionsDSLCall cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:39.3137255Z To see the complete backtrace run rubocop -d.
2022-09-05T17:58:39.6834742Z �[31mAn error occurred while FormulaAudit/GenerateCompletionsDSL cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:39.6835363Z To see the complete backtrace run rubocop -d.
2022-09-05T17:58:39.6836495Z �[31mAn error occurred while FormulaAudit/SingleGenerateCompletionsDSLCall cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:39.6838375Z To see the complete backtrace run rubocop -d.
2022-09-05T17:58:40.0134391Z �[31m
2022-09-05T17:58:40.0135188Z 2 errors occurred:�[0m
2022-09-05T17:58:40.0136425Z �[31mAn error occurred while FormulaAudit/GenerateCompletionsDSL cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:40.0137372Z �[31mAn error occurred while FormulaAudit/SingleGenerateCompletionsDSLCall cop was inspecting /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-portable-ruby/Abstract/portable-formula.rb:72:0.�[0m
2022-09-05T17:58:40.0154164Z undefined method `metadata' for nil:NilClass
2022-09-05T17:58:40.0156644Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:79:in `display_error_summary'
2022-09-05T17:58:40.0157372Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:58:in `display_summary'
2022-09-05T17:58:40.0158062Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:27:in `block in execute_runner'
2022-09-05T17:58:40.0158740Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:52:in `with_redirect'
2022-09-05T17:58:40.0159393Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
2022-09-05T17:58:40.0160202Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
2022-09-05T17:58:40.0160832Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/command.rb:11:in `run'
2022-09-05T17:58:40.0161427Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli/environment.rb:18:in `run'
2022-09-05T17:58:40.0162020Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli.rb:72:in `run_command'
2022-09-05T17:58:40.0162602Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli.rb:79:in `execute_runners'
2022-09-05T17:58:40.0163177Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-1.35.1/lib/rubocop/cli.rb:48:in `run'
2022-09-05T17:58:40.0163588Z /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/utils/rubocop.rb:12:in `<main>'

I can reproduce the failure if I have a formula containing only an install def, but I don't know why the cop should fail then... We are not calling #metadata anywhere...

E.g.

class Foo < Formula
  def install
    (bash_completion/"foo").write Utils.safe_popen_read(bin/"foo", "completions", "bash")
  end
end

@max-ae
Copy link
Contributor Author

max-ae commented Sep 5, 2022

Also, the cask audit test failures should be unrelated.

@max-ae
Copy link
Contributor Author

max-ae commented Sep 5, 2022

Or: should we simply scope this cop to the core tap? The run for all core formulae was fine.

Copy link
Member

@Rylan12 Rylan12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see those audit test failures even on master locally. Not sure what's going on with them and why they haven't been showing up. I guess I'll look into it a bit later today.

Library/Homebrew/rubocops/lines.rb Show resolved Hide resolved
Library/Homebrew/rubocops/lines.rb Show resolved Hide resolved
@max-ae
Copy link
Contributor Author

max-ae commented Sep 5, 2022

Yay, all green now! (except for the unrelated tests) Thanks again!

That should be everything now for the new DSL 🎉

@Rylan12
Copy link
Member

Rylan12 commented Sep 5, 2022

@SMillerDev the current CI issues (which are occurring for me locally even on the master branch) seem to caused by or related to #13746. Any ideas?

Weirdly, I can see the errors if I run brew tests --only=cask/audit but if I add a line number e.g. brew tests --only=cask/audit:6 (which should just run all the tests) I don't see an error.

@SMillerDev
Copy link
Member

I have no idea, it passed for me and in CI.

@carlocab
Copy link
Member

carlocab commented Sep 6, 2022

Failures likely fixed by #13813.

@max-ae
Copy link
Contributor Author

max-ae commented Sep 6, 2022

Failures likely fixed by #13813.

Curiously, they are still present in the latest CI run 🧐
Do I need to rebase?

@carlocab
Copy link
Member

carlocab commented Sep 6, 2022

Do I need to rebase?

Yes, probably.

@max-ae max-ae force-pushed the generate-completions-dsl-rubocop branch from 89bb77e to 088dce0 Compare September 6, 2022 12:42
@Rylan12 Rylan12 merged commit 89cb768 into Homebrew:master Sep 6, 2022
@Rylan12
Copy link
Member

Rylan12 commented Sep 6, 2022

Thanks so much for all of your work on this, @max-ae! 🎉

@max-ae max-ae deleted the generate-completions-dsl-rubocop branch September 7, 2022 09:10
@github-actions github-actions bot added the outdated PR was locked due to age label Oct 8, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants