Skip to content

Fix method definition cop - #44

Open
kuahyeow wants to merge 7 commits into
rubocop:masterfrom
kuahyeow:fix_method_definition_cop
Open

Fix method definition cop#44
kuahyeow wants to merge 7 commits into
rubocop:masterfrom
kuahyeow:fix_method_definition_cop

Conversation

@kuahyeow

Copy link
Copy Markdown

Fixes #42

Fixes ClassDefinitionInTask, and MethodDefinitionInTask to allow classes, modules and methods to defined inside tasks

@kuahyeow

Copy link
Copy Markdown
Author

@koic Is the configured Circle CI still working. Am getting the error below:

 CircleCI Pipeline — Could not find a usable config.yml, you may have revoked the CircleCI OAuth app. 

@pboling pboling left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is correct. The difference between which definition of a method or class wins is according to lexical order. The only one that works properly, without polluting the global Ruby Object namespace is inside a task, (whether or not it is inside a namespace is irrelevant).

Comment thread lib/rubocop/cop/rake/class_definition_in_task.rb Outdated
Comment thread lib/rubocop/cop/rake/class_definition_in_task.rb
Comment thread lib/rubocop/cop/rake/class_definition_in_task.rb
Comment thread lib/rubocop/cop/rake/helper/task_definition.rb
Comment thread lib/rubocop/cop/rake/helper/task_definition.rb
Comment thread lib/rubocop/cop/rake/helper/task_definition.rb
Comment thread lib/rubocop/cop/rake/helper/task_definition.rb
Comment thread spec/rubocop/cop/rake/class_definition_in_task_spec.rb Outdated
Comment thread spec/rubocop/cop/rake/class_definition_in_task_spec.rb Outdated
@pboling

pboling commented Nov 9, 2023

Copy link
Copy Markdown

Ping! Just ran into this false positive again, and came looking to see if any activity here.

@kuahyeow
kuahyeow force-pushed the fix_method_definition_cop branch 2 times, most recently from bac9816 to e116f67 Compare November 10, 2023 08:19

@pboling pboling left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM! ❤️

@kuahyeow
kuahyeow force-pushed the fix_method_definition_cop branch from e116f67 to 2915482 Compare November 11, 2023 09:01
@q3aiml

q3aiml commented Dec 22, 2023

Copy link
Copy Markdown

Is this correctly handling when a task is nested inside a namespace? I believe that should be allowed, but the spec doesn't seem to cover it and it looks like it is disallowed.

For example this test fails:

  it 'does not register an offense to `def` in a task when wrapped in a namespace' do
    expect_no_offenses(<<~RUBY)
      namespace :bar do
        task :foo do
          def helper_method
            do_something
          end
        end
      end
    RUBY
  end

@kuahyeow

Copy link
Copy Markdown
Author

That's true. I have now pushed a fix for this.

Is this correctly handling when a task is nested inside a namespace? I believe that should be allowed, but the spec doesn't seem to cover it and it looks like it is disallowed.

For example this test fails:

  it 'does not register an offense to `def` in a task when wrapped in a namespace' do
    expect_no_offenses(<<~RUBY)
      namespace :bar do
        task :foo do
          def helper_method
            do_something
          end
        end
      end
    RUBY
  end

@pboling pboling left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM

@pboling

pboling commented May 10, 2024

Copy link
Copy Markdown

@kuahyeow The build passed before your last fix, but now it failing on Ruby >= 2.7. Any ideas?

@kuahyeow
kuahyeow force-pushed the fix_method_definition_cop branch from 000d0e2 to 0fd68b2 Compare May 11, 2024 05:23
@kuahyeow

Copy link
Copy Markdown
Author

Looks like it's failing on unrelated rubocop errors....

rubocop
Inspecting 25 files
............C.......C....

Offenses:

lib/rubocop/cop/rake/helper/task_name.rb:11:30: C: [Correctable] InternalAffairs/NodeFirstOrLastArgument: Use #first_argument instead of #arguments[0].
            first_arg = node.arguments[0]
                             ^^^^^^^^^^^^
spec/rubocop/cop/rake/desc_spec.rb:4:6: C: [Correctable] InternalAffairs/ExampleDescription: Description does not match use of expect_offense.
  it 'register an offense for task on the top level' do
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
spec/rubocop/cop/rake/desc_spec.rb:16:6: C: [Correctable] InternalAffairs/ExampleDescription: Description does not match use of expect_offense.
  it 'register an offense for task with block in a block' do
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
spec/rubocop/cop/rake/desc_spec.rb:33:6: C: [Correctable] InternalAffairs/ExampleDescription: Description does not match use of expect_offense.
  it 'register an offense for task in kwbegin' do
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

25 files inspected, 4 offenses detected, 4 offenses autocorrectable
rake aborted!
Command failed with status (1): [rubocop...]
/home/circleci/project/Rakefile:36:in `block in <top (required)>'
/home/circleci/.rubygems/gems/rake-12.3.3/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => default => rubocop
(See full trace by running task with --trace)

Exited with code exit status 1

@ydakuka

ydakuka commented Feb 23, 2025

Copy link
Copy Markdown

@kuahyeow could you please rebase the branch? The CI specs should pass as expected now.

@pboling

pboling commented Feb 23, 2025

Copy link
Copy Markdown

LGTM still!

tkuah added 6 commits March 4, 2025 11:00
As methods defined in task do not pollute top level

For example, this rakefile below will show that `do_something` does not
appear in top level methods

```
task :a do
  def do_something
    puts 'a'
  end

  do_something
end

task :b do
  def do_something
    puts 'b'
  end

  do_something
end

puts methods.include?(:do_something)
```
As classes defined in task do not pollute top level.

For example, this Rakefile shows class C in task
does not pollute top level

```
task :a do
  class C
    def do_something
      puts 'a'
    end
  end

  C.new.do_something
end

task :b do
  class C
    def do_something
      puts 'b'
    end
  end

  C.new.do_something
end

puts Object.const_defined?('C')
```
Since the cop is now fixed to warn against class in namespaces, update
the cop name accordingly.
Since the cop is now fixed to warn against method in namespaces, update
the cop name accordingly.
This is similar to definitions within a task (without a namespace).
@kuahyeow
kuahyeow force-pushed the fix_method_definition_cop branch from 0fd68b2 to fc00ab1 Compare March 3, 2025 22:00
@kuahyeow

Copy link
Copy Markdown
Author

@ydakuka @pboling Rebased now ! The rspecs workflow now requires approval from a maintainer to run.

@pboling

pboling commented Apr 5, 2025

Copy link
Copy Markdown

@koic Please approve the workflow!

@pboling pboling left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Needs a minor grammatical fix

Comment thread lib/rubocop/cop/rake/class_definition_in_namespace.rb Outdated
@kuahyeow

kuahyeow commented Apr 5, 2025 via email

Copy link
Copy Markdown
Author

@kuahyeow
kuahyeow force-pushed the fix_method_definition_cop branch from 58eb199 to 7b9f68f Compare April 5, 2025 06:24

@pboling pboling left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM 💯

@tylerhunt

Copy link
Copy Markdown

This one bit me today. Hoping for a merge and release soon.

@@ -30,12 +30,14 @@ module Rake
# task :foo do

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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 task directly.

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?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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 ;)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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

definition location scope rubocop-rake should consider rubocop-rake currently considers
top-level global bad 🛑 good ✅
namespace block global bad 🛑 bad 🛑
task block task good ✅ bad 🛑

"Good Code" example for task:

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:

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 top-level:

desc 'foo task'
task :foo do
  puts 'In foo task'
  greet
end
 
def greet
  puts 'Hello from foo.rake'
end

I think this should be the goal!

@kuahyeow kuahyeow Aug 17, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The 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:

Given this cop's intention is to only highlight "surprising" behavior, I will leave this logic as is.

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.

add a cop for the top level method definition

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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 task block seeing as we are only checking specific files ending in .rake and the specific quirks and features of Rake files.

Also removing the good example in a later PR if necessary also makes sense.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changing it from # good to # okay is the Rubocop doc way to distinguish what the cop accepts vs best practices

Comment thread config/default.yml
Comment thread lib/rubocop/cop/rake/class_definition_in_namespace.rb
Comment thread config/default.yml
@pboling

pboling commented Aug 18, 2025

Copy link
Copy Markdown

This just bit me again, and I commented on this issue... checks notes, within the last day!
It can be hard to remember to do it the right way when I have to turn off this rule, and I very rarely write methods inside rake tasks. :(
♻️ refactoring my code now...

pboling added a commit to floss-funding/floss_funding that referenced this pull request Aug 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rake/MethodDefinitionInTask is 66.6% incorrect

8 participants