123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::AST::IfNode

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Node, NodePattern::Macros, Parser::AST::Node
Instance Chain:
self, ModifierNode, ConditionalNode, Node, Descendence, Sexp, Parser::AST::Node
Inherits: RuboCop::AST::Node
Defined in: lib/rubocop/ast/node/if_node.rb

Overview

A node extension for if nodes. This will be used in place of a plain node when the builder constructs the AST, making its methods available to all if nodes within RuboCop.

Constant Summary

Node - Inherited

ASSIGNMENTS, BASIC_CONDITIONALS, BASIC_LITERALS, COMPARISON_OPERATORS, COMPOSITE_LITERALS, CONDITIONALS, EMPTY_CHILDREN, EMPTY_PROPERTIES, EQUALS_ASSIGNMENTS, FALSEY_LITERALS, GROUP_FOR_TYPE, IMMUTABLE_LITERALS, KEYWORDS, LITERALS, LITERAL_RECURSIVE_METHODS, LITERAL_RECURSIVE_TYPES, LOOP_TYPES, MUTABLE_LITERALS, OPERATOR_KEYWORDS, POST_CONDITION_LOOP_TYPES, REFERENCES, SHORTHAND_ASSIGNMENTS, SPECIAL_KEYWORDS, TRUTHY_LITERALS, VARIABLES

Class Method Summary

Node - Inherited

.new,
.def_recursive_literal_predicate

Define a recursive_? predicate method for the given node kind.

NodePattern::Macros - Extended

def_node_matcher

Define a method which applies a pattern to an AST node.

def_node_search

Define a method which recurses over the descendants of an AST node, checking whether any of them match the provided pattern.

Instance Attribute Summary

ModifierNode - Included

#modifier_form?

Checks whether the node is in a modifier form, i.e.

ConditionalNode - Included

#multiline_condition?

Checks whether the condition of the node is written on more than one line.

#single_line_condition?

Checks whether the condition of the node is written on a single line.

Node - Inherited

#any_block_type?, #any_def_type?, #any_match_pattern_type?, #argument?, #argument_type?, #assignment?, #basic_conditional?, #basic_literal?, #boolean_type?, #call_type?, #chained?, #complete?, #conditional?, #empty_source?, #equals_asgn?, #falsey_literal?, #guard_clause?, #immutable_literal?, #keyword?, #literal?,
#loop_keyword?
Note
loop { } is a normal method call and thus not a loop keyword.
#multiline?

Predicates.

#mutable_literal?, #numeric_type?, #operator_keyword?,
#parent

Returns the parent node, or nil if the receiver is a root node.

#parent?, #parenthesized_call?, #post_condition_loop?,
#pure?

Some expressions are evaluated for their value, some for their side effects, and some for both.

#range_type?, #reference?, #root?,
#send_type?

Most nodes are of 'send' type, so this method is defined separately to make this check as fast as possible.

#shorthand_asgn?, #single_line?, #special_keyword?, #truthy_literal?,
#value_used?

Some expressions are evaluated for their value, some for their side effects, and some for both If we know that an expression is useful only for its side effects, that means we can transform it in ways which preserve the side effects, but change the return value So, does the return value of this node matter? If we changed it to (…​; nil), might that affect anything?

#variable?, #begin_value_used?, #case_if_value_used?, #for_value_used?, #while_until_value_used?

Instance Method Summary

ConditionalNode - Included

#body

Returns the body associated with the condition.

#condition

Returns the condition of the node.

Node - Inherited

#ancestors

Returns an array of ancestor nodes.

#assignment_or_similar?

Some cops treat the shovel operator as a kind of assignment.

#class_constructor?, #class_definition?, #complete!, #const_name, #defined_module, #defined_module_name,
#each_ancestor

Calls the given block for each ancestor node from parent to root.

#first_line, #global_const?, #lambda?, #lambda_or_proc?, #last_line,
#left_sibling

Use is discouraged, this is a potentially slow method and can lead to even slower algorithms.

#left_siblings

Use is discouraged, this is a potentially slow method and can lead to even slower algorithms.

#line_count,
#loc?

Shortcut to safely check if a location is present.

#loc_is?

Shortcut to safely test a particular location, even if this location does not exist or is nil.

#match_guard_clause?, #module_definition?,
#node_parts

Common destructuring method.

#nonempty_line_count,
#parent_module_name

Searching the AST.

#proc?, #receiver, #recursive_basic_literal?, #recursive_literal?,
#right_sibling

Use is discouraged, this is a potentially slow method and can lead to even slower algorithms.

#right_siblings

Use is discouraged, this is a potentially slow method and can lead to even slower algorithms.

#sibling_index

Returns the index of the receiver node in its siblings.

#source
Note
Some rare nodes may have no source, like s(:args) in foo {}.
#source_length, #source_range, #str_content, #struct_constructor?,
#type?

Determine if the node is one of several node types in a single query Allows specific single node types, as well as "grouped" types (e.g.

#updated

Override Node#updated so that AST::Processor does not try to mutate our ASTs.

#defined_module0, #new_class_or_module_block?, #parent_module_name_for_block, #parent_module_name_for_sclass, #parent_module_name_part, #visit_ancestors

Descendence - Included

#child_nodes

Returns an array of child nodes.

#descendants

Returns an array of descendant nodes.

#each_child_node

Calls the given block for each child node.

#each_descendant

Calls the given block for each descendant node with depth first order.

#each_node

Calls the given block for the receiver and each descendant node in depth-first order.

Sexp - Included

#s

Creates a Node with type type and children children.

Constructor Details

This class inherits a constructor from RuboCop::AST::Node

Instance Attribute Details

#else?Boolean (readonly)

Note:

This returns true for nodes containing an elsif clause. This is legacy behavior, and many cops rely on it.

Checks whether the if node has an else clause.

Returns:

  • (Boolean)

    whether the node has an else clause

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 49

def else?
  loc?(:else)
end

#elsif?Boolean (readonly)

Checks whether the if is an elsif. Parser handles these by nesting if nodes in the else branch.

Returns:

  • (Boolean)

    whether the node is an elsif

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 39

def elsif?
  keyword == 'elsif'
end

#elsif_conditional?Boolean (readonly)

Checks whether the if node has at least one elsif branch. Returns true if this if node itself is an elsif.

Returns:

  • (Boolean)

    whether the if node has at least one elsif branch

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 111

def elsif_conditional?
  else_branch&.if_type? && else_branch.elsif?
end

#if?Boolean (readonly)

Checks whether this node is an if statement. (This is not true of ternary operators and unless statements.)

Returns:

  • (Boolean)

    whether the node is an if statement

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 16

def if?
  keyword == 'if'
end

#modifier_form?Boolean (readonly)

Checks whether the if node is in a modifier form, i.e. a condition trailing behind an expression. Only if and unless nodes without other branches can be modifiers.

Returns:

  • (Boolean)

    whether the if node is a modifier

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 87

def modifier_form?
  (if? || unless?) && super
end

#nested_conditional?Boolean (readonly)

Note:

This performs a shallow search.

Checks whether the if node has nested if nodes in any of its branches.

Returns:

  • (Boolean)

    whether the if node contains nested conditionals

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 97

def nested_conditional?
  node_parts[1..2].compact.each do |branch|
    branch.each_node(:if) do |nested|
      return true unless nested.elsif?
    end
  end

  false
end

#ternary?Boolean (readonly)

Checks whether the if node is a ternary operator.

Returns:

  • (Boolean)

    whether the if node is a ternary operator

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 56

def ternary?
  loc?(:question)
end

#then?Boolean (readonly)

Checks whether the if node has an then clause.

Returns:

  • (Boolean)

    whether the node has an then clause

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 31

def then?
  loc_is?(:begin, 'then')
end

#unless?Boolean (readonly)

Checks whether this node is an unless statement. (This is not true of ternary operators and if statements.)

Returns:

  • (Boolean)

    whether the node is an unless statement

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 24

def unless?
  keyword == 'unless'
end

Instance Method Details

#branchesArray<Node>

Returns an array of all the branches in the conditional statement.

Returns:

  • (Array<Node>)

    an array of branch nodes

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 154

def branches
  if ternary?
    [if_branch, else_branch]
  elsif !else?
    [if_branch]
  else
    branches = [if_branch]
    other_branches = if elsif_conditional?
                       else_branch.branches
                     else
                       [else_branch]
                     end
    branches.concat(other_branches)
  end
end

#each_branch(&block)

Deprecated.

Use branches.each

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 171

def each_branch(&block)
  return branches.to_enum(__method__) unless block

  branches.each(&block)
end

#else_branchNode?

Note:

This is normalized for unless nodes.

Returns the branch of the if node that gets evaluated when its condition is falsey.

Returns:

  • (Node)

    the falsey branch node of the if node

  • (nil)

    when there is no else branch

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 133

def else_branch
  node_parts[2]
end

#if_branchNode?

Note:

This is normalized for unless nodes.

Returns the branch of the if node that gets evaluated when its condition is truthy.

Returns:

  • (Node)

    the truthy branch node of the if node

  • (nil)

    if the truthy branch is empty

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 122

def if_branch
  node_parts[1]
end

#inverse_keywordString

Returns the inverse keyword of the if node as a string. Returns if for unless nodes and vice versa. Returns an empty string for ternary operators.

Returns:

  • (String)

    the inverse keyword of the if statement

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 73

def inverse_keyword
  case keyword
  when 'if' then 'unless'
  when 'unless' then 'if'
  else
    ''
  end
end

#keywordString

Returns the keyword of the if statement as a string. Returns an empty string for ternary operators.

Returns:

  • (String)

    the keyword of the if statement

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 64

def keyword
  ternary? ? '' : loc.keyword.source
end

#node_partsArray<Node>

Custom destructuring method. This is used to normalize the branches for if and unless nodes, to aid comparisons and conversions.

Returns:

  • (Array<Node>)

    the different parts of the if statement

[ GitHub ]

  
# File 'lib/rubocop/ast/node/if_node.rb', line 141

def node_parts
  if unless?
    condition, false_branch, true_branch = *self
  else
    condition, true_branch, false_branch = *self
  end

  [condition, true_branch, false_branch]
end