class RuboCop::Cop::VariableForce::Variable
A Variable
represents existence of a local variable. This holds a variable declaration node and some states of the variable.
Constants
- VARIABLE_DECLARATION_TYPES
Attributes
Public Class Methods
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 15 def initialize(name, declaration_node, scope) unless VARIABLE_DECLARATION_TYPES.include?(declaration_node.type) raise ArgumentError, "Node type must be any of #{VARIABLE_DECLARATION_TYPES}, " \ "passed #{declaration_node.type}" end @name = name.to_sym @declaration_node = declaration_node @scope = scope @assignments = [] @references = [] @captured_by_block = false end
Public Instance Methods
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 105 def argument? ARGUMENT_DECLARATION_TYPES.include?(@declaration_node.type) end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 31 def assign(node) assignment = Assignment.new(node, self) mark_last_as_reassigned!(assignment) @assignments << assignment end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 113 def block_argument? argument? && @scope.node.block_type? end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 85 def capture_with_block! @captured_by_block = true end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 121 def explicit_block_local_variable? @declaration_node.shadowarg_type? end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 77 def in_modifier_conditional?(assignment) parent = assignment.node.parent parent = parent.parent if parent&.begin_type? return false if parent.nil? parent.type?(:if, :while, :until) && parent.modifier_form? end
rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 117 def keyword_argument? %i[kwarg kwoptarg].include?(@declaration_node.type) end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 39 def mark_last_as_reassigned!(assignment) return if captured_by_block? return unless assignment.branch == @assignments.last&.branch @assignments.last&.reassigned! end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 109 def method_argument? argument? && @scope.node.any_def_type? end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 51 def reference!(node) reference = Reference.new(node, @scope) @references << reference consumed_branches = nil @assignments.reverse_each do |assignment| next if consumed_branches&.include?(assignment.branch) assignment.reference!(node) unless assignment.run_exclusively_with?(reference) # Modifier if/unless conditions are special. Assignments made in # them do not put the assigned variable in scope to the left of the # if/unless keyword. A preceding assignment is needed to put the # variable in scope. For this reason we skip to the next assignment # here. next if in_modifier_conditional?(assignment) break if !assignment.branch || assignment.branch == reference.branch unless assignment.branch.may_run_incompletely? (consumed_branches ||= Set.new) << assignment.branch end end end
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 46 def referenced? !@references.empty? end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 101 def should_be_unused? name.to_s.start_with?('_') end
Source
# File lib/rubocop/cop/variable_force/variable.rb, line 97 def used? @captured_by_block || referenced? end
This is a convenient way to check whether the variable is used in its entire variable lifetime. For
more precise usage check, refer Assignment#used?
.
Once the variable is captured by a block, we have no idea when, where, and how many times the block would be invoked. This means we cannot track the usage of the variable. So we consider it’s used to suppress false positive offenses.