-
-
Notifications
You must be signed in to change notification settings - Fork 19
Fix method definition cop #44
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
base: master
Are you sure you want to change the base?
Changes from all commits
eb38421
2b0dcde
b82abd6
dcb54ac
973be1d
fc00ab1
7b9f68f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,13 +3,13 @@ | |||||||||||||||||
| module RuboCop | ||||||||||||||||||
| module Cop | ||||||||||||||||||
| module Rake | ||||||||||||||||||
| # Detects method definition in a task or namespace, | ||||||||||||||||||
| # Detects method definition in a namespace, | ||||||||||||||||||
| # because it is defined to the top level. | ||||||||||||||||||
| # It is confusing because the scope looks in the task or namespace, | ||||||||||||||||||
| # It is confusing because the method appears to be defined in the namespace, | ||||||||||||||||||
| # but actually it is defined to the top level. | ||||||||||||||||||
| # | ||||||||||||||||||
| # @example | ||||||||||||||||||
| # # bad | ||||||||||||||||||
| # # good | ||||||||||||||||||
| # task :foo do | ||||||||||||||||||
| # def helper_method | ||||||||||||||||||
| # do_something | ||||||||||||||||||
|
|
@@ -30,12 +30,14 @@ module Rake | |||||||||||||||||
| # task :foo do | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for this PR @kuahyeow 🙏 I don't think "expected behavior" is necessarily the same as a "good" example. It only moves the method definition but still leaves it at the top level of the file, which introduces the same problem of polluting globally. We've already shown a "good" example by adding it in the Not sure what you think, but I would still find this misleading particularly if I was only running a single rake file, and there was a duplicate method definition in a later rake file. I would remove this example, and add a cop for the top level method definition. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. Splitting the example so that only definitions inside the task are considered "good" would be good ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be aligned with my original report in #42, which I've copied here for easier reference
"Good Code" example for namespace :foo_namespace do
desc 'foo task'
task :foo do
def greet
puts 'Hello from foo.rake'
end
puts 'In foo task'
greet
end
end"Bad Code" example for namespace :foo_namespace do
desc 'foo task'
task :foo do
puts 'In foo task'
greet
end
def greet
puts 'Hello from foo.rake'
end
end"Bad Code" example for desc 'foo task'
task :foo do
puts 'In foo task'
greet
end
def greet
puts 'Hello from foo.rake'
endI think this should be the goal!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @rossme for the comment. I think this is slightly related to #44 (comment), where I mentioned:
To keep this PR lean and tidy, my inclination is to make no further changes. Reason: Defining a top level method outside of any block is just like defining (and including) a top level method in any Ruby script. Reason 2: This example is pre-existing.
So, I would like this PR to be merged first (hopefully), and then we have another PR if there's need to this. Hopefully a maintainer comes onboard at some point to review. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do see your point about the top level method and keeping this PR lean 👍 I would still (gently) argue for adding a cop for any method outside of the Also removing the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing it from |
||||||||||||||||||
| # end | ||||||||||||||||||
| # | ||||||||||||||||||
| class MethodDefinitionInTask < Base | ||||||||||||||||||
| MSG = 'Do not define a method in rake task, because it will be defined to the top level.' | ||||||||||||||||||
| class MethodDefinitionInNamespace < Base | ||||||||||||||||||
| MSG = 'Do not define a method in a rake namespace, because it will be defined to the top level.' | ||||||||||||||||||
|
|
||||||||||||||||||
| def on_def(node) | ||||||||||||||||||
| return if Helper::ClassDefinition.in_class_definition?(node) | ||||||||||||||||||
| return unless Helper::TaskDefinition.in_task_or_namespace?(node) | ||||||||||||||||||
| return if Helper::TaskDefinition.in_task?(node) | ||||||||||||||||||
|
|
||||||||||||||||||
| return unless Helper::TaskDefinition.in_namespace?(node) | ||||||||||||||||||
|
|
||||||||||||||||||
| add_offense(node) | ||||||||||||||||||
| end | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require_relative 'rake/class_definition_in_task' | ||
| require_relative 'rake/class_definition_in_namespace' | ||
| require_relative 'rake/desc' | ||
| require_relative 'rake/duplicate_task' | ||
| require_relative 'rake/duplicate_namespace' | ||
| require_relative 'rake/method_definition_in_task' | ||
| require_relative 'rake/method_definition_in_namespace' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe RuboCop::Cop::Rake::ClassDefinitionInNamespace, :config do | ||
| it 'allows class definition in task' do | ||
| expect_no_offenses(<<~RUBY) | ||
| task :foo do | ||
| class C | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'allows module definition in task' do | ||
| expect_no_offenses(<<~RUBY) | ||
| task :foo do | ||
| module M | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'allows class definition in a task when wrapped in a namespace' do | ||
| expect_no_offenses(<<~RUBY) | ||
| namespace :bar do | ||
| task :foo do | ||
| class C | ||
| end | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense to a class definition in namespace' do | ||
| expect_offense(<<~RUBY) | ||
| namespace 'foo' do | ||
| class C | ||
| ^^^^^^^ Do not define a class in a rake namespace, because it will be defined to the top level. | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'registers an offense to a module definition in namespace' do | ||
| expect_offense(<<~RUBY) | ||
| namespace 'foo' do | ||
| module M | ||
| ^^^^^^^^ Do not define a module in a rake namespace, because it will be defined to the top level. | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'allows class definition in Class.new' do | ||
| expect_no_offenses(<<~RUBY) | ||
| task :foo do | ||
| Class.new do | ||
| class C | ||
| end | ||
| end | ||
| end | ||
| RUBY | ||
| end | ||
|
|
||
| it 'allows class definition at the top level' do | ||
| expect_no_offenses(<<~RUBY) | ||
| class C | ||
| end | ||
|
|
||
| task :foo do | ||
| end | ||
| RUBY | ||
| end | ||
| end |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.