Module: SyntaxTree::Ternaryable

Defined in:
lib/syntax_tree/node.rb

Overview

In order for an ‘if` or `unless` expression to be shortened to a ternary, there has to be one and only one consequent clause which is an Else. Both the body of the main node and the body of the Else node must have only one statement, and that statement must not be on the denied list of potential statements.

Class Method Summary collapse

Class Method Details

.call(q, node) ⇒ Object



6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
# File 'lib/syntax_tree/node.rb', line 6146

def call(q, node)
  return false if ENV["STREE_FAST_FORMAT"]

  # If this is a conditional inside of a parentheses as the only content,
  # then we don't want to transform it into a ternary. Presumably the user
  # wanted it to be an explicit conditional because there are parentheses
  # around it. So we'll just leave it in place.
  grandparent = q.grandparent
  if grandparent.is_a?(Paren) && (body = grandparent.contents.body) &&
       body.length == 1 && body.first == node
    return false
  end

  # Otherwise, we'll check the type of predicate. For certain nodes we
  # want to force it to not be a ternary, like if the predicate is an
  # assignment because it's hard to read.
  case node.predicate
  when Assign, Command, CommandCall, MAssign, OpAssign
    return false
  when Not
    return false unless node.predicate.parentheses?
  end

  # If there's no Else, then this can't be represented as a ternary.
  return false unless node.consequent.is_a?(Else)

  truthy_body = node.statements.body
  falsy_body = node.consequent.statements.body

  (truthy_body.length == 1) && ternaryable?(truthy_body.first) &&
    (falsy_body.length == 1) && ternaryable?(falsy_body.first)
end