Skip to content

Commit

Permalink
Add on_after_<type> callbacks
Browse files Browse the repository at this point in the history
I doubled check that this has basically no performance impact (less than ~0.1% overall) after #8882
  • Loading branch information
marcandre committed Oct 13, 2020
1 parent e1e12a9 commit 2f2c910
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### New features

* [#8889](https://github.com/rubocop-hq/rubocop/pull/8889): Cops can use new `on_after_<type>` callbacks (only for nodes that may have children nodes, like `:send` and unlike `:sym`). ([@marcandre][])

### Changes

* [#8882](https://github.com/rubocop-hq/rubocop/pull/8882): **(Potentially breaking)** RuboCop assumes that Cop classes do not define new `on_<type>` methods at runtime (e.g. via `extend`). ([@marcandre][])
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/development.adoc
Expand Up @@ -248,6 +248,8 @@ module RuboCop
end
----

Note that `on_send` will be called on a given `node` before the callbacks `on_<some type>` for its children are called. There's also a callback `on_after_send` that is called after the children are processed. There's a similar `on_after_<some type>` callback for all types, except those that never have children.

Update the spec to cover the expected syntax:

[source,ruby]
Expand Down
20 changes: 11 additions & 9 deletions lib/rubocop/cop/commissioner.rb
Expand Up @@ -7,7 +7,7 @@ module Cop
class Commissioner
include RuboCop::AST::Traversal

RESTRICTED_CALLBACKS = %i[on_send on_csend].freeze
RESTRICTED_CALLBACKS = %i[on_send on_csend on_after_send on_after_csend].freeze
private_constant :RESTRICTED_CALLBACKS

# How a Commissioner returns the results of the investigation
Expand Down Expand Up @@ -60,16 +60,18 @@ def initialize(cops, forces = [], options = {})
method_name = :"on_#{node_type}"
next unless method_defined?(method_name)

if RESTRICTED_CALLBACKS.include?(method_name)
trigger_restricted = "trigger_restricted_cops(:on_#{node_type}, node)"
end
# Hacky: Comment-out code as needed
r = '#' unless RESTRICTED_CALLBACKS.include?(method_name) # has Restricted?
c = '#' if NO_CHILD_NODES.include?(node_type) # has Children?

class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def on_#{node_type}(node)
trigger_responding_cops(:on_#{node_type}, node)
#{trigger_restricted}
#{'super(node)' unless NO_CHILD_NODES.include?(node_type)}
end
def on_#{node_type}(node)
trigger_responding_cops(:on_#{node_type}, node)
#{r} trigger_restricted_cops(:on_#{node_type}, node)
#{c} super(node)
#{c} trigger_responding_cops(:on_after_#{node_type}, node)
#{c}#{r} trigger_restricted_cops(:on_after_#{node_type}, node)
end
RUBY
end

Expand Down

0 comments on commit 2f2c910

Please sign in to comment.