-
Notifications
You must be signed in to change notification settings - Fork 26
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
Refactor ForbidIncludeConstLiteral
#153
Conversation
return unless within_onymous_module?(node) | ||
|
||
add_offense(node, message: format(MSG, inclusion_method: inclusion_method)) do |corrector| | ||
explicit_receiver = receiver&.source || 'self' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a bug-fix so I think we have no test cases for the explicit receiver not being self
. Can we add one or two cases for that as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
I did some digging, and it looks like Sorbet doesn't handle include
with an explicit receiver.
# typed: strict
module M
extend T::Sig
sig { void }
def m; end
end
class C1
include M
end
C1.new.m
class C2; end
C2.include M
C2.new.m
# ^ Method m does not exist on C2
That said, it seems like a reasonable thing that might end up supported eventually (I'm not sure why it isn't already, if the receiver is a constant).
So I could:
- Simplify the code, by only looking for
include
,extend
, &prepend
with implicit receivers, or - Keep the cop "smarter than (current) Sorbet", and add tests.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting! I would go for keeping the refactored implementation and add tests for those cases. After all, dynamic or not, those includes are not going to work with Sorbet either way. We could at least push people to use less dynamic mixins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added tests, although I should note that they look like
module M
M.include(dynamic)
end
which this implementation detects, not
M.include(dynamic)
which this implementation does not detect. Do we want to do that? I'm unsure about false positives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think my implementation introduces a false positive bug. Neither of these should be flagged, because we can't be sure they're operating on a module.
Config = []
Config.prepend(1)
class MyClass
Config.prepend(2)
end
I think that is why in my example above Sorbet doesn't handle C2.include M
. 🤔
I'm going to add test cases for this (and the equivalent include
and extend
cases) and make them pass.
7a57aa3
to
240a904
Compare
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
240a904
to
e3d676f
Compare
e3d676f
to
09a959c
Compare
4e38682
to
9083997
Compare
it "adds no offense when an explicit constant receiver includes a send node" do | ||
expect_no_offenses(<<~RUBY) | ||
module MyModule | ||
MyModule.include Rails.application.routes.url_helpers | ||
end | ||
RUBY | ||
end | ||
|
||
it "adds no offense when an explicit constant receiver extends a send node" do | ||
expect_no_offenses(<<~RUBY) | ||
module MyModule | ||
MyModule.extend Rails.application.routes.url_helpers | ||
end | ||
RUBY | ||
end | ||
|
||
it "adds no offense when an explicit constant receiver prepends a send node" do | ||
expect_no_offenses(<<~RUBY) | ||
module MyModule | ||
MyModule.prepend Rails.application.routes.url_helpers | ||
end | ||
RUBY | ||
end | ||
|
||
it "does not add offense when prepend used with array" do | ||
expect_no_offenses(<<~RUBY) | ||
Config = [] | ||
Config.prepend(one) | ||
|
||
module MyModule | ||
Config.prepend(two) | ||
end | ||
|
||
class MyClass | ||
Config.prepend(three) | ||
end | ||
RUBY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paracycle I've added these tests as per #153 (comment) to cover the edge cases you pointed out, and adjusted the implementation accordingly.
This makes the following changes: - Migrates from deprecated `Cop` parent class to `Base` - Improves the offense message - Removes the unused `used_names` accessor and initialization - Renames and alters the node matcher to describe what it matches, not what it doesn't - Extracts named helpers to clarify the code's logic - Leverages the `expect_correction` test helpers and replaces the autocorrection specific tests.
9083997
to
876e1c4
Compare
This makes the following changes:
Cop
parent class toBase
used_names
accessor and initializationexpect_correction
test helpers and replaces the autocorrection specific tests.