Class: RuboCop::Cop::VariableForce::Variable Private
- Inherits:
-
Object
- Object
- RuboCop::Cop::VariableForce::Variable
- Defined in:
- lib/rubocop/cop/variable_force/variable.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
A Variable represents existence of a local variable. This holds a variable declaration node and some states of the variable.
Constant Summary collapse
- VARIABLE_DECLARATION_TYPES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
(VARIABLE_ASSIGNMENT_TYPES + ARGUMENT_DECLARATION_TYPES).freeze
Instance Attribute Summary collapse
- #assignments ⇒ Object readonly private
- #captured_by_block ⇒ Object (also: #captured_by_block?) readonly private
- #declaration_node ⇒ Object readonly private
- #name ⇒ Object readonly private
- #references ⇒ Object readonly private
- #scope ⇒ Object readonly private
Instance Method Summary collapse
- #argument? ⇒ Boolean private
- #assign(node) ⇒ Object private
- #block_argument? ⇒ Boolean private
- #capture_with_block! ⇒ Object private
- #covers?(container, node) ⇒ Boolean private
- #explicit_block_local_variable? ⇒ Boolean private
-
#in_modifier_conditional?(assignment, reference_node) ⇒ Boolean
private
rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
-
#initialize(name, declaration_node, scope) ⇒ Variable
constructor
private
A new instance of Variable.
- #keyword_argument? ⇒ Boolean private
- #mark_last_as_reassigned!(assignment) ⇒ Object private
- #method_argument? ⇒ Boolean private
- #modifier_conditional_of(node) ⇒ Object private
-
#reference!(node) ⇒ Object
private
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #referenced? ⇒ Boolean private
- #should_be_unused? ⇒ Boolean private
-
#used? ⇒ Boolean
private
This is a convenient way to check whether the variable is used in its entire variable lifetime.
Constructor Details
#initialize(name, declaration_node, scope) ⇒ Variable
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Variable.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# 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 |
Instance Attribute Details
#assignments ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def assignments @assignments end |
#captured_by_block ⇒ Object (readonly) Also known as: captured_by_block?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def captured_by_block @captured_by_block end |
#declaration_node ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def declaration_node @declaration_node end |
#name ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def name @name end |
#references ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def references @references end |
#scope ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
11 12 13 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 11 def scope @scope end |
Instance Method Details
#argument? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
117 118 119 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 117 def argument? ARGUMENT_DECLARATION_TYPES.include?(@declaration_node.type) end |
#assign(node) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
31 32 33 34 35 36 37 |
# 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 |
#block_argument? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
125 126 127 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 125 def block_argument? argument? && @scope.node.block_type? end |
#capture_with_block! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
97 98 99 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 97 def capture_with_block! @captured_by_block = true end |
#covers?(container, node) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
93 94 95 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 93 def covers?(container, node) container.equal?(node) || container.source_range.contains?(node.source_range) end |
#explicit_block_local_variable? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
133 134 135 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 133 def explicit_block_local_variable? @declaration_node.shadowarg_type? end |
#in_modifier_conditional?(assignment, reference_node) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
77 78 79 80 81 82 83 84 85 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 77 def in_modifier_conditional?(assignment, reference_node) conditional = modifier_conditional_of(assignment.node) return false unless conditional # The out-of-scope problem only affects a reference in the modifier body (to the # left of the keyword); a reference after the modifier is put in scope by the # condition's assignment, so an earlier assignment there is genuinely useless. covers?(conditional, reference_node) && !covers?(conditional.condition, reference_node) end |
#keyword_argument? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
129 130 131 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 129 def keyword_argument? %i[kwarg kwoptarg].include?(@declaration_node.type) end |
#mark_last_as_reassigned!(assignment) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
39 40 41 42 43 44 |
# 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 |
#method_argument? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
121 122 123 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 121 def method_argument? argument? && @scope.node.any_def_type? end |
#modifier_conditional_of(node) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
87 88 89 90 91 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 87 def modifier_conditional_of(node) node.each_ancestor(:if, :while, :until).find do |conditional| conditional.modifier_form? && covers?(conditional.condition, node) end end |
#reference!(node) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# 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, node) break if !assignment.branch || assignment.branch == reference.branch unless assignment.branch.may_run_incompletely? (consumed_branches ||= Set.new) << assignment.branch end end end |
#referenced? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
46 47 48 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 46 def referenced? !@references.empty? end |
#should_be_unused? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
113 114 115 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 113 def should_be_unused? name.to_s.start_with?('_') end |
#used? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
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.
109 110 111 |
# File 'lib/rubocop/cop/variable_force/variable.rb', line 109 def used? @captured_by_block || referenced? end |