Class: RuboCop::Cop::VariableForce::Variable Private
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Macros
|
|
Inherits: | Object |
Defined in: | lib/rubocop/cop/variable_force/variable.rb |
Overview
A Variable represents existence of a local variable. This holds a variable declaration node and some states of the variable.
Constant Summary
-
VARIABLE_DECLARATION_TYPES =
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11(VARIABLE_ASSIGNMENT_TYPES + ARGUMENT_DECLARATION_TYPES).freeze
Class Method Summary
- .new(name, declaration_node, scope) ⇒ Variable constructor Internal use only
Instance Attribute Summary
- #argument? ⇒ Boolean readonly Internal use only
- #assignments readonly Internal use only
- #block_argument? ⇒ Boolean readonly Internal use only
-
#captured_by_block?
readonly
Alias for #captured_by_block.
- #declaration_node readonly Internal use only
- #explicit_block_local_variable? ⇒ Boolean readonly Internal use only
- #keyword_argument? ⇒ Boolean readonly Internal use only
- #method_argument? ⇒ Boolean readonly Internal use only
- #name readonly Internal use only
- #referenced? ⇒ Boolean readonly Internal use only
- #references readonly Internal use only
- #scope readonly Internal use only
- #should_be_unused? ⇒ Boolean readonly Internal use only
-
#used? ⇒ Boolean
readonly
Internal use only
This is a convenient way to check whether the variable is used in its entire variable lifetime.
Instance Method Summary
- #assign(node) Internal use only
- #candidate_condition?(node)
- #capture_with_block! Internal use only
- #captured_by_block (also: #captured_by_block?) readonly Internal use only
-
#in_modifier_conditional?(assignment) ⇒ Boolean
Internal use only
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #mark_last_as_reassigned!(assignment) Internal use only
-
#reference!(node)
Internal use only
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
Constructor Details
.new(name, declaration_node, scope) ⇒ Variable
# File 'lib/rubocop/cop/variable_force/variable.rb', line 17
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
Instance Attribute Details
#argument? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 110
def argument? ARGUMENT_DECLARATION_TYPES.include?(@declaration_node.type) end
#assignments (readonly)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#block_argument? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 118
def block_argument? argument? && @scope.node.block_type? end
#captured_by_block? (readonly)
Alias for #captured_by_block.
# File 'lib/rubocop/cop/variable_force/variable.rb', line 15
alias captured_by_block? captured_by_block
#declaration_node (readonly)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#explicit_block_local_variable? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 126
def explicit_block_local_variable? @declaration_node.shadowarg_type? end
#keyword_argument? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 122
def keyword_argument? %i[kwarg kwoptarg].include?(@declaration_node.type) end
#method_argument? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 114
def method_argument? argument? && %i[def defs].include?(@scope.node.type) end
#name (readonly)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#referenced? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 51
def referenced? !@references.empty? end
#references (readonly)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#scope (readonly)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#should_be_unused? ⇒ Boolean
(readonly)
# File 'lib/rubocop/cop/variable_force/variable.rb', line 106
def should_be_unused? name.to_s.start_with?('_') end
#used? ⇒ Boolean
(readonly)
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.
# File 'lib/rubocop/cop/variable_force/variable.rb', line 102
def used? @captured_by_block || referenced? end
Instance Method Details
#assign(node)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 33
def assign(node) assignment = Assignment.new(node, self) mark_last_as_reassigned!(assignment) @assignments << assignment end
#candidate_condition?(node)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 49
def_node_matcher :candidate_condition?, '[{if case case_match when}]'
#capture_with_block!
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 90
def capture_with_block! @captured_by_block = true end
#captured_by_block (readonly) Also known as: #captured_by_block?
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 13
attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
#in_modifier_conditional?(assignment) ⇒ Boolean
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/variable_force/variable.rb', line 82
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
#mark_last_as_reassigned!(assignment)
[ GitHub ]# File 'lib/rubocop/cop/variable_force/variable.rb', line 41
def mark_last_as_reassigned!(assignment) return if captured_by_block? return if candidate_condition?(assignment.node.parent) @assignments.last&.reassigned! end
#reference!(node)
Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/variable_force/variable.rb', line 56
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