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

Vendor remaining Rails cops, remove ActiveSupport #16510

Merged
merged 12 commits into from
Jan 30, 2024

Conversation

dduugg
Copy link
Member

@dduugg dduugg commented Jan 19, 2024

  • 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?

Resolves #16190

Begins replacing Rails cops as advised in #16190 (comment)
Three cops in particular can be replaced with Style/InverseMethods and a small subset of their prior logic, which I've attempted in this PR.

@dduugg dduugg marked this pull request as draft January 19, 2024 22:14
@dduugg dduugg force-pushed the inverse-include-exclude-cop branch 4 times, most recently from 2850c5e to b963260 Compare January 19, 2024 23:16
@dduugg dduugg changed the title Replace Rails/NegateInclude with Inverse/Invertible cops Replace some Rails cops with Style/InverseMethods and custom versions Jan 19, 2024
@@ -9357,10 +9360,18 @@ module RuboCop::Cop::HelperFunctions
extend ::T::Private::Methods::SingletonMethodHooks
end

class RuboCop::Cop::Homebrew::Blank
def nil_or_empty?(param0=T.unsafe(nil)); end
Copy link
Member Author

Choose a reason for hiding this comment

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

An update was necessary to pick up these def_node_matcher methods.

@dduugg dduugg force-pushed the inverse-include-exclude-cop branch from b72a730 to fe0fbb1 Compare January 19, 2024 23:32
@dduugg dduugg marked this pull request as ready for review January 19, 2024 23:37
describe RuboCop::Cop::Homebrew::Blank do
subject(:cop) { described_class.new }

shared_examples "offense" do |source, correction, message|
Copy link
Contributor

Choose a reason for hiding this comment

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

Stupid question: would it be possible to use kwargs here to improve readability?

Copy link
Member Author

Choose a reason for hiding this comment

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

Possibly! Though I should have added that the test cases are copy/pasta from upstream, where the test cases are appropriate, and I'm not especially inclined to drift from it:

https://github.com/rubocop/rubocop-rails/blob/master/spec/rubocop/cop/rails/blank_spec.rb#L4

(Source code made available under the MIT license, which may be appropriate to paste into the new files here, depending on one's view of "substantial portions".)

Copy link
Contributor

@apainintheneck apainintheneck left a comment

Choose a reason for hiding this comment

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

LGTM

Library/Homebrew/startup/bootsnap.rb Outdated Show resolved Hide resolved
Comment on lines 353 to 359
Style/InverseMethods:
Exclude:
# Core extensions are not available here:
- "Homebrew/standalone/init.rb"
- "Homebrew/rubocops/**/*"
Copy link
Member

@Bo98 Bo98 Jan 20, 2024

Choose a reason for hiding this comment

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

I'm guessing this also disables vanilla Ruby InverseMethods checking.

If so, maybe worth having a InverseMethodsExtension cop that is nothing but a subclass of RuboCop::Cop::Style::InverseMethods, but will I think allow us to separate configs? You can ignore this suggestion if you prefer though and I can maybe look into that more later.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the call out, I should have added a bit more on my thought process. Let's enumerate some options here, because there are several. More or less in my order of preference, they include:

  • Add :exclude?: :include? here, but exclude Style/InverseMethods cop where exclude? is unavailable (what I've done above)
  • Omit :exclude?: :include? from the cop, as we do with Style/InvertibleUnlessCondition below
  • Add :exclude?: :include? to the cop, use inline disable comments where exclude? is unavailable
  • Just import extend/string and/or extend/array anywhere there's a violation, once some version of Remove ActiveSupport from runtime #16463 lands
  • Omit :exclude?: :include? from the cop, vendor the Rails/NegateInclude include cop (perhaps a simpler, though less extensible, version of what you're suggesting, IIUC)
  • Add an InverseMethodsExtension cop that is nothing but a subclass of RuboCop::Cop::Style::InverseMethods, but would allow us to separate configs
  • Remove the ActiveSupport dependency in rubocop-rails (a long shot, but hey)

I'm generally biased toward whichever results in the least amount of add'l code/comments, and I'm pretty ok if we don't have 100% coverage of InverseMethods. That said, I'm happy to do any of these (except the last one 🙈) if there is consensus otherwise. Let me know if this is helpful/influences where you think we should go with this.

Copy link
Member

Choose a reason for hiding this comment

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

  • Omit :exclude?: :include? from the cop, vendor the Rails/NegateInclude include cop (perhaps a simpler, though less extensible, version of what you're suggesting, IIUC)
  • Add an InverseMethodsExtension cop that is nothing but a subclass of RuboCop::Cop::Style::InverseMethods, but would allow us to separate configs

either of these sound nicest to me!

def blank?
true
end
def blank? = true
Copy link
Member Author

Choose a reason for hiding this comment

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

A bit of Ruby 3 cleanup while were dealing with blank?. (Since these work like constants, I quite prefer this style, but lmk if this inappropriate for the scope of this PR.)

Copy link
Member

Choose a reason for hiding this comment

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

This looks good to me!

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! I'd be fine with merging as-is and iterating on comments, if desired. Thanks @dduugg!

Comment on lines 54 to 56
Homebrew/Blank:
Exclude:
# Core extensions are not available here:
- "Homebrew/rubocops/**/*"
- "Homebrew/startup/bootsnap.rb"
Copy link
Member

Choose a reason for hiding this comment

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

Don't want to blow up the scope but: I almost wonder whether it might be nicer still to have Homebrew/Blank specifically check that blank? is not used in these files?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, my gut instinct is that is a weird scope for a single cop (use a method one way in these paths, and not at all in these others). Possibly we could take inspiration from Lint/DeprecatedClassMethods, use a version of it to ban blank?, and scope the cop to these files.

I do think its worth taking a step back and thinking about whether we should just require extend/blank in these paths though. It seems like less trouble than maintaining separate guard rails based on paths, especially given that workspaces are generally poorly contemplated in Ruby and associated tooling (e.g. sorbet) generally.

Copy link
Member Author

Choose a reason for hiding this comment

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

It turns out we already rely on extend/blank in our rubocops, because it was transitively available via rubocop-rails: https://github.com/Homebrew/brew/blob/8e9d294/Library/Homebrew/rubocops/shell_commands.rb#L123

Mind if I explicitly require it in our rubocops for now? We can circle back and refactor it away later, but i think its reasonable to maintain the status quo in this PR.

Comment on lines 353 to 359
Style/InverseMethods:
Exclude:
# Core extensions are not available here:
- "Homebrew/standalone/init.rb"
- "Homebrew/rubocops/**/*"
Copy link
Member

Choose a reason for hiding this comment

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

  • Omit :exclude?: :include? from the cop, vendor the Rails/NegateInclude include cop (perhaps a simpler, though less extensible, version of what you're suggesting, IIUC)
  • Add an InverseMethodsExtension cop that is nothing but a subclass of RuboCop::Cop::Style::InverseMethods, but would allow us to separate configs

either of these sound nicest to me!

def blank?
true
end
def blank? = true
Copy link
Member

Choose a reason for hiding this comment

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

This looks good to me!

@dduugg dduugg force-pushed the inverse-include-exclude-cop branch 2 times, most recently from d42c0e6 to b945574 Compare January 26, 2024 22:15
@dduugg dduugg changed the title Replace some Rails cops with Style/InverseMethods and custom versions Vendor remaining Rails cops, remove ActiveSupport Jan 26, 2024
@@ -355,15 +344,18 @@ Style/HashAsLastArrayItem:
- "/**/Formula/**/*.rb"
- "**/Formula/**/*.rb"

Style/InverseMethods:
InverseMethods:
:blank?: :present?
Copy link
Member Author

Choose a reason for hiding this comment

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

This, and the InvertibleUnlessCondition entry below it, allow us to remove some redundant contents of the Blank and Present cops (specificallye, the NotPresent, UnlessPresent, NotBlank, and UnlessBlank config option handling.

Style/InvertibleUnlessCondition:
Enabled: true
InverseMethods:
# Favor `if a != b` over `unless a == b`
:==: :!=
# Unset this (prefer `unless a.zero?` over `if a.nonzero?`)
:zero?:
# Don't require non-standard `exclude?` (for now at least) - it's not available in every file
:include?:
Copy link
Member Author

Choose a reason for hiding this comment

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

This was introduced by the rubocop-rails config, and is no longer necessary to unset.

@@ -155,7 +155,7 @@ def to_s
end

def to_args
@dsl_args.reject(&:blank?)
@dsl_args.compact_blank
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm a bit confused why these violations were not caught before 😕

@@ -75,7 +75,7 @@ def sort_conditional_dependencies!(ordered)
ordered.each_with_index do |dep, pos|
idx = pos+1
match_nodes = build_with_dependency_name(dep)
next if !match_nodes || match_nodes.empty?
next if match_nodes.blank?
Copy link
Member Author

Choose a reason for hiding this comment

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

As noted above, blank? is been available (and used) within our custom rubocops already, so i've removed the exclusions, pending refactor


it "does not require i18n" do
# This is a transitive dependency of activesupport, but we don't use it.
expect { I18n }.to raise_error(NameError)
Copy link
Member Author

Choose a reason for hiding this comment

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

This no longer passes typechecking, bc the i18n rbi file is gone. I don't think it's an especially useful test anymore, so let's just yank it.

@dduugg
Copy link
Member Author

dduugg commented Jan 26, 2024

I've updated the PR to vendor the remaining Rails cops and thus remove rupocop-rails and activesupport.

This makes for a large PR, and it would be reasonable to request to break them into 2 PRs instead, just let me know.

As currently scoped, this PR removes > 8% of the checked-in code (by number of lines). 📉

@dduugg dduugg force-pushed the inverse-include-exclude-cop branch from e0ca750 to 9c8219a Compare January 26, 2024 23:02
@dduugg dduugg force-pushed the inverse-include-exclude-cop branch from 9c8219a to 4b59101 Compare January 26, 2024 23:04
@dduugg dduugg force-pushed the inverse-include-exclude-cop branch from 47e66b6 to bec27d4 Compare January 26, 2024 23:38
@MikeMcQuaid
Copy link
Member

Great work, thanks again @dduugg!

@dduugg dduugg merged commit 3a27cac into Homebrew:master Jan 30, 2024
26 checks passed
@dduugg dduugg deleted the inverse-include-exclude-cop branch January 30, 2024 19:59
@github-actions github-actions bot added the outdated PR was locked due to age label Mar 1, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 1, 2024
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.

Remove ActiveSupport dependency
4 participants