Skip to content
Snippets Groups Projects
Commit 5b97a8f2 authored by Gautham Goli's avatar Gautham Goli
Browse files

Add methods in FormulaCop to find method nodes, dependency nodes

parent d1f802c3
No related branches found
No related tags found
No related merge requests found
......@@ -7,9 +7,9 @@ module RuboCop
def on_class(node)
file_path = processed_source.buffer.name
return unless file_path_allowed?(file_path)
class_node, parent_class_node, body = *node
return unless formula_class?(parent_class_node)
return unless formula_class?(node)
return unless respond_to?(:audit_formula)
class_node, parent_class_node, body = *node
@formula_name = class_name(class_node)
audit_formula(node, class_node, parent_class_node, body)
end
......@@ -46,12 +46,61 @@ module RuboCop
nil
end
# Returns an array of method call nodes matching method_name inside node
# Set the given node as the offending node when required in custom cops
def offending_node(node)
@offensive_node = node
@offense_source_range = node.source_range
end
# Returns an array of method call nodes matching method_name inside node with depth first order (Children nodes)
def find_method_calls_by_name(node, method_name)
return if node.nil?
node.each_child_node(:send).select { |method_node| method_name == method_node.method_name }
end
# Returns an array of method call nodes matching method_name in every descendant of node
def find_every_method_call_by_name(node, method_name)
return if node.nil?
node.each_descendant(:send).select { |method_node| method_name == method_node.method_name }
end
# Returns nil if does not depend on dependency_name
# args: node - formula class' body node
# dependency_name - dependency's name
def depends_on?(node, dependency_name)
dependency_nodes = find_every_method_call_by_name(node, :depends_on)
idx = dependency_nodes.index do |n|
depends_on_name_type?(n, dependency_name, :required) ||
depends_on_name_type?(n, dependency_name, :build) ||
depends_on_name_type?(n, dependency_name, :optional) ||
depends_on_name_type?(n, dependency_name, :recommended) ||
depends_on_name_type?(n, dependency_name, :run)
end
return nil if idx.nil?
@offense_source_range = dependency_nodes[idx].source_range
@offensive_node = dependency_nodes[idx]
end
# Returns true if given dependency name and dependency type exist in given dependency method call node
def depends_on_name_type?(node, dependency_name = nil, dependency_type = :required)
dependency_name_match = true if dependency_name.nil? # Match only by type
case dependency_type
when :required
dependency_type_match = !node.method_args.nil? && node.method_args.first.str_type?
dependency_name_match = (string_content(node.method_args.first) == dependency_name) if dependency_type_match
when :build || :optional || :recommended || :run
dependency_type_match = !node.method_args.nil? &&
node.method_args.first.hash_type? &&
node.method_args.first.values[0].children.first == dependency_type
dependency_name_match = (node.method_args.first.keys[0].children.first == dependency_name) if dependency_type_match
end
if dependency_type_match || dependency_name_match
@offensive_node = node
@offense_source_range = node.source_range
end
dependency_type_match && dependency_name_match
end
# Returns a block named block_name inside node
def find_block(node, block_name)
return if node.nil?
......@@ -112,6 +161,17 @@ module RuboCop
false
end
# Check if method_name is called among every descendant node of given node
def method_called_ever?(node, method_name)
node.each_descendant(:send) do |call_node|
next unless call_node.method_name == method_name
@offensive_node = call_node
@offense_source_range = call_node.source_range
return true
end
false
end
# Checks for precedence, returns the first pair of precedence violating nodes
def check_precedence(first_nodes, next_nodes)
next_nodes.each do |each_next_node|
......@@ -138,6 +198,17 @@ module RuboCop
method_node.method_args
end
# Returns true if the given parameters are present in method call
# and sets the method call as the offending node
def parameters_passed?(method_node, *params)
method_params = parameters(method_node)
@offensive_node = method_node
@offense_source_range = method_node.source_range
params.all? do |given_param|
method_params.any? { |method_param| given_param == string_content(method_param) }
end
end
# Returns the begin position of the node's line in source code
def line_start_column(node)
node.source_range.source_buffer.line_range(node.loc.line).begin_pos
......@@ -180,10 +251,16 @@ module RuboCop
node.source_range.source_buffer
end
# Returns the string representation if node is of type str(plain) or dstr(interpolated)
# Returns the string representation if node is of type str(plain) or dstr(interpolated) or const
def string_content(node)
return node.str_content if node.type == :str
node.each_child_node(:str).map(&:str_content).join("") if node.type == :dstr
case node.type
when :str
return node.str_content if node.type == :str
when :dstr
return node.each_child_node(:str).map(&:str_content).join("") if node.type == :dstr
when :const
return node.const_name if node.type == :const
end
end
# Returns printable component name
......@@ -198,8 +275,9 @@ module RuboCop
private
def formula_class?(parent_class_node)
parent_class_node && parent_class_node.const_name == "Formula"
def formula_class?(node)
_, class_node, = *node
class_node && string_content(class_node) == "Formula"
end
def file_path_allowed?(file_path)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment