Class: RuboCop::Cop::VariableForce Private
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Force
|
|
Instance Chain:
self,
Force
|
|
Inherits: |
RuboCop::Cop::Force
|
Defined in: | lib/rubocop/cop/variable_force.rb, lib/rubocop/cop/variable_force/assignment.rb, lib/rubocop/cop/variable_force/branch.rb, lib/rubocop/cop/variable_force/branchable.rb, lib/rubocop/cop/variable_force/reference.rb, lib/rubocop/cop/variable_force/scope.rb, lib/rubocop/cop/variable_force/variable.rb, lib/rubocop/cop/variable_force/variable_table.rb |
Overview
This force provides a way to track local variables and scopes of Ruby. Cops interact with this force need to override some of the hook methods.
def before_entering_scope(scope, variable_table)
end
def after_entering_scope(scope, variable_table)
end
def before_leaving_scope(scope, variable_table)
end
def after_leaving_scope(scope, variable_table)
end
def before_declaring_variable(variable, variable_table)
end
def after_declaring_variable(variable, variable_table)
end
Constant Summary
-
ARGUMENT_DECLARATION_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 35[ :arg, :optarg, :restarg, :kwarg, :kwoptarg, :kwrestarg, :blockarg, # This doesn't mean block argument, it's block-pass (&block). :shadowarg # This means block local variable (obj.each { |arg; this| }). ].freeze
-
LOGICAL_OPERATOR_ASSIGNMENT_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 42%i[or_asgn and_asgn].freeze
-
LOOP_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 51(POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze
-
MULTIPLE_ASSIGNMENT_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 45:masgn
-
NODE_HANDLER_METHOD_NAMES =
private
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 115[ [VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment], [REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures], [PATTERN_MATCH_VARIABLE_TYPE, :process_pattern_match_variable], [MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment], [VARIABLE_REFERENCE_TYPE, :process_variable_referencing], [RESCUE_TYPE, :process_rescue], [ZERO_ARITY_SUPER_TYPE, :process_zero_arity_super], [SEND_TYPE, :process_send], *ARGUMENT_DECLARATION_TYPES.product([:process_variable_declaration]), *OPERATOR_ASSIGNMENT_TYPES.product([:process_variable_operator_assignment]), *LOOP_TYPES.product([:process_loop]), *SCOPE_TYPES.product([:process_scope]) ].to_h.freeze
-
OPERATOR_ASSIGNMENT_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 43(LOGICAL_OPERATOR_ASSIGNMENT_TYPES + [:op_asgn]).freeze
-
PATTERN_MATCH_VARIABLE_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 30:match_var
-
POST_CONDITION_LOOP_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 50%i[while_post until_post].freeze
-
REGEXP_NAMED_CAPTURE_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 29:match_with_lvasgn
-
RESCUE_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 53:rescue
-
REST_ASSIGNMENT_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 46:splat
-
SCOPE_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 58(TWISTED_SCOPE_TYPES + [:def]).freeze
-
SEND_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 60:send
-
TWISTED_SCOPE_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 57%i[block numblock class sclass defs module].freeze
-
VARIABLE_ASSIGNMENT_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 28:lvasgn
-
VARIABLE_ASSIGNMENT_TYPES =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 31[ VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE, PATTERN_MATCH_VARIABLE_TYPE ].freeze
-
VARIABLE_REFERENCE_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 48:lvar
-
ZERO_ARITY_SUPER_TYPE =
Internal use only
# File 'lib/rubocop/cop/variable_force.rb', line 55:zsuper
Class Method Summary
Force
- Inherited
Instance Attribute Summary
Instance Method Summary
-
#investigate(processed_source)
Internal use only
Internal use only
Starting point.
- #process_node(node) Internal use only Internal use only
- #variable_table Internal use only Internal use only
- #descendant_reference(node) private Internal use only Internal use only
- #each_descendant_reference(loop_node) private Internal use only Internal use only
- #find_variables_in_loop(loop_node) private Internal use only Internal use only
-
#inspect_variables_in_scope(scope_node)
private
Internal use only
Internal use only
This is called for each scope recursively.
-
#mark_assignments_as_referenced_in_loop(node)
private
Internal use only
Internal use only
Mark all assignments which are referenced in the same loop as referenced by ignoring AST order since they would be referenced in next iteration.
- #node_handler_method_name(node) private Internal use only Internal use only
- #process_children(origin_node) private Internal use only Internal use only
- #process_loop(node) private Internal use only Internal use only
- #process_pattern_match_variable(node) private Internal use only Internal use only
- #process_regexp_named_captures(node) private Internal use only Internal use only
- #process_rescue(node) private Internal use only Internal use only
- #process_scope(node) private Internal use only Internal use only
- #process_send(node) private Internal use only Internal use only
- #process_variable_assignment(node) private Internal use only Internal use only
- #process_variable_declaration(node) private Internal use only Internal use only
- #process_variable_multiple_assignment(node) private Internal use only Internal use only
- #process_variable_operator_assignment(node) private Internal use only Internal use only
- #process_variable_referencing(node) private Internal use only Internal use only
- #process_zero_arity_super(node) private Internal use only Internal use only
- #regexp_captured_names(node) private Internal use only Internal use only
- #scanned_node?(node) ⇒ Boolean private Internal use only Internal use only
- #scanned_nodes private Internal use only Internal use only
- #skip_children! private Internal use only Internal use only
- #twisted_nodes(node) private Internal use only Internal use only
Force
- Inherited
Constructor Details
This class inherits a constructor from RuboCop::Cop::Force
Instance Method Details
#descendant_reference(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 346
def descendant_reference(node) case node.type when :lvar VariableReference.new(node.children.first) when :lvasgn AssignmentReference.new(node) when *OPERATOR_ASSIGNMENT_TYPES VariableReference.new(node.lhs.name) if node.lhs.lvasgn_type? end end
#each_descendant_reference(loop_node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 336
def each_descendant_reference(loop_node) # #each_descendant does not consider scope, # but we don't need to care about it here. loop_node.each_descendant do |node| reference = descendant_reference(node) yield reference if reference end end
#find_variables_in_loop(loop_node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 321
def find_variables_in_loop(loop_node) referenced_variable_names_in_loop = [] assignment_nodes_in_loop = [] each_descendant_reference(loop_node) do |reference| if reference.assignment? assignment_nodes_in_loop << reference.node else referenced_variable_names_in_loop << reference.name end end [referenced_variable_names_in_loop, assignment_nodes_in_loop] end
#inspect_variables_in_scope(scope_node) (private)
This method is for internal use only.
This is called for each scope recursively.
# File 'lib/rubocop/cop/variable_force.rb', line 97
def inspect_variables_in_scope(scope_node) variable_table.push_scope(scope_node) process_children(scope_node) variable_table.pop_scope end
#investigate(processed_source)
This method is for internal use only.
Starting point.
# File 'lib/rubocop/cop/variable_force.rb', line 79
def investigate(processed_source) root_node = processed_source.ast return unless root_node variable_table.push_scope(root_node) process_node(root_node) variable_table.pop_scope end
#mark_assignments_as_referenced_in_loop(node) (private)
This method is for internal use only.
Mark all assignments which are referenced in the same loop as referenced by ignoring AST order since they would be referenced in next iteration.
# File 'lib/rubocop/cop/variable_force.rb', line 302
def mark_assignments_as_referenced_in_loop(node) referenced_variable_names_in_loop, assignment_nodes_in_loop = find_variables_in_loop(node) referenced_variable_names_in_loop.each do |name| variable = variable_table.find_variable(name) # Non related references which are caught in the above scan # would be skipped here. next unless variable variable.assignments.each do |assignment| next if assignment_nodes_in_loop.none? do |assignment_node| assignment_node.equal?(assignment.node) end assignment.reference!(node) end end end
#node_handler_method_name(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 130
def node_handler_method_name(node) NODE_HANDLER_METHOD_NAMES[node.type] end
#process_children(origin_node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 103
def process_children(origin_node) origin_node.each_child_node do |child_node| next if scanned_node?(child_node) process_node(child_node) end end
#process_loop(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 238
def process_loop(node) if POST_CONDITION_LOOP_TYPES.include?(node.type) # See the comment at the end of file for this behavior. condition_node, body_node = *node process_node(body_node) process_node(condition_node) else process_children(node) end mark_assignments_as_referenced_in_loop(node) skip_children! end
#process_node(node)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 88
def process_node(node) method_name = node_handler_method_name(node) retval = send(method_name, node) if method_name process_children(node) unless retval == :skip_children end
#process_pattern_match_variable(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 182
def process_pattern_match_variable(node) name = node.children.first variable_table.declare_variable(name, node) unless variable_table.variable_exist?(name) skip_children! end
#process_regexp_named_captures(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 164
def process_regexp_named_captures(node) regexp_node, rhs_node = *node variable_names = regexp_captured_names(regexp_node) variable_names.each do |name| next if variable_table.variable_exist?(name) variable_table.declare_variable(name, node) end process_node(rhs_node) process_node(regexp_node) variable_names.each { |name| variable_table.assign_to_variable(name, node) } skip_children! end
#process_rescue(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 253
def process_rescue(node) resbody_nodes = node.each_child_node(:resbody) contain_retry = resbody_nodes.any? do |resbody_node| resbody_node.each_descendant.any?(&:retry_type?) end # Treat begin..rescue..end with retry as a loop. process_loop(node) if contain_retry end
#process_scope(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 272
def process_scope(node) if TWISTED_SCOPE_TYPES.include?(node.type) # See the comment at the end of file for this behavior. twisted_nodes(node).each do |twisted_node| process_node(twisted_node) scanned_nodes << twisted_node end end inspect_variables_in_scope(node) skip_children! end
#process_send(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 291
def process_send(node) _receiver, method_name, args = *node return unless method_name == :binding return if args && !args.children.empty? variable_table.accessible_variables.each { |variable| variable.reference!(node) } end
#process_variable_assignment(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 146
def process_variable_assignment(node) name = node.children.first variable_table.declare_variable(name, node) unless variable_table.variable_exist?(name) # Need to scan rhs before assignment so that we can mark previous # assignments as referenced if rhs has referencing to the variable # itself like: # # foo = 1 # foo = foo + 1 process_children(node) variable_table.assign_to_variable(name, node) skip_children! end
#process_variable_declaration(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 134
def process_variable_declaration(node) variable_name = node.children.first # restarg and kwrestarg would have no name: # # def initialize(*) # end return unless variable_name variable_table.declare_variable(variable_name, node) end
#process_variable_multiple_assignment(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 226
def process_variable_multiple_assignment(node) lhs_node, rhs_node = *node process_node(rhs_node) process_node(lhs_node) skip_children! end
#process_variable_operator_assignment(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 196
def process_variable_operator_assignment(node) asgn_node = node.lhs return unless asgn_node.lvasgn_type? name = asgn_node.name variable_table.declare_variable(name, asgn_node) unless variable_table.variable_exist?(name) # The following statements: # # foo = 1 # foo += foo = 2 # # => 3 # # are equivalent to: # # foo = 1 # foo = foo + (foo = 2) # # => 3 # # So, at operator assignment node, we need to reference the variable # before processing rhs nodes. variable_table.reference_variable(name, node) process_node(node.rhs) variable_table.assign_to_variable(name, asgn_node) skip_children! end
#process_variable_referencing(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 233
def process_variable_referencing(node) name = node.children.first variable_table.reference_variable(name, node) end
#process_zero_arity_super(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 264
def process_zero_arity_super(node) variable_table.accessible_variables.each do |variable| next unless variable.method_argument? variable.reference!(node) end end
#regexp_captured_names(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 190
def regexp_captured_names(node) regexp = node.to_regexp regexp.named_captures.keys end
#scanned_node?(node) ⇒ Boolean
(private)
This method is for internal use only.
# File 'lib/rubocop/cop/variable_force.rb', line 357
def scanned_node?(node) scanned_nodes.include?(node) end
#scanned_nodes (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 361
def scanned_nodes @scanned_nodes ||= Set.new.compare_by_identity end
#skip_children! (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 111
def skip_children! :skip_children end
#twisted_nodes(node) (private)
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 285
def twisted_nodes(node) twisted_nodes = [node.children[0]] twisted_nodes << node.children[1] if node.class_type? twisted_nodes.compact end
#variable_table
This method is for internal use only.
[ GitHub ]
# File 'lib/rubocop/cop/variable_force.rb', line 74
def variable_table @variable_table ||= VariableTable.new(self) end