Skip to content

Commit

Permalink
[Fixes #117] Optimize Traversal
Browse files Browse the repository at this point in the history
It is ~5x faster to do the hash lookup than compute a symbol dynamically.

Clearly, code isn't DRY
  • Loading branch information
marcandre committed Oct 11, 2020
1 parent cc6f501 commit 4c5c0f4
Showing 1 changed file with 28 additions and 26 deletions.
54 changes: 28 additions & 26 deletions lib/rubocop/ast/traversal.rb
Expand Up @@ -8,10 +8,12 @@ module AST
# Override methods to perform custom processing. Remember to call `super`
# if you want to recursively process descendant nodes.
module Traversal
TYPE_TO_METHOD = Hash.new { |h, type| h[type] = :"on_#{type}" }

def walk(node)
return if node.nil?

send(:"on_#{node.type}", node)
send(TYPE_TO_METHOD[node.type], node)
nil
end

Expand Down Expand Up @@ -48,7 +50,7 @@ def walk(node)
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def on_#{type}(node)
if (child = node.children[0])
send(:"on_\#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
end
RUBY
Expand All @@ -57,7 +59,7 @@ def on_#{type}(node)
MANY_CHILD_NODES.each do |type|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def on_#{type}(node)
node.children.each { |child| send(:"on_\#{child.type}", child) }
node.children.each { |child| send(TYPE_TO_METHOD[child.type], child) }
nil
end
RUBY
Expand All @@ -68,7 +70,7 @@ def on_#{type}(node)
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def on_#{type}(node)
if (child = node.children[1])
send(:"on_\#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
end
RUBY
Expand All @@ -77,44 +79,44 @@ def on_#{type}(node)
def on_const(node)
return unless (child = node.children[0])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_casgn(node)
children = node.children
if (child = children[0]) # always const???
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_class(node)
children = node.children
child = children[0] # always const???
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
if (child = children[1])
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_def(node)
children = node.children
on_args(children[1])
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_send(node)
node.children.each_with_index do |child, i|
next if i == 1

send(:"on_#{child.type}", child) if child
send(TYPE_TO_METHOD[child.type], child) if child
end
nil
end
Expand All @@ -124,40 +126,40 @@ def on_send(node)
def on_op_asgn(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
child = children[2]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_defs(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
on_args(children[2])
return unless (child = children[3])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_if(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
if (child = children[1])
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_while(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
return unless (child = children[1])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

alias on_until on_while
Expand All @@ -167,16 +169,16 @@ def on_while(node)
def on_block(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child) # can be send, zsuper...
send(TYPE_TO_METHOD[child.type], child) # can be send, zsuper...
on_args(children[1])
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end

def on_case(node)
node.children.each do |child|
send(:"on_#{child.type}", child) if child
send(TYPE_TO_METHOD[child.type], child) if child
end
nil
end
Expand All @@ -194,10 +196,10 @@ def on_case(node)
def on_numblock(node)
children = node.children
child = children[0]
send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
return unless (child = children[2])

send(:"on_#{child.type}", child)
send(TYPE_TO_METHOD[child.type], child)
end
end
end
Expand Down

0 comments on commit 4c5c0f4

Please sign in to comment.