Class: SyntaxTree::HshPtn

Inherits:
Node
  • Object
show all
Defined in:
lib/syntax_tree/node.rb

Overview

HshPtn represents matching against a hash pattern using the Ruby 2.7+ pattern matching syntax.

case value
in { key: }
end

Defined Under Namespace

Classes: KeywordFormatter, KeywordRestFormatter

Instance Attribute Summary collapse

Attributes inherited from Node

#location

Instance Method Summary collapse

Methods inherited from Node

#construct_keys, #end_char, #pretty_print, #start_char, #to_json, #to_mermaid

Constructor Details

#initialize(constant:, keywords:, keyword_rest:, location:) ⇒ HshPtn

Returns a new instance of HshPtn.



6069
6070
6071
6072
6073
6074
6075
# File 'lib/syntax_tree/node.rb', line 6069

def initialize(constant:, keywords:, keyword_rest:, location:)
  @constant = constant
  @keywords = keywords
  @keyword_rest = keyword_rest
  @location = location
  @comments = []
end

Instance Attribute Details

#commentsObject (readonly)

Array[ Comment | EmbDoc ]

the comments attached to this node



6067
6068
6069
# File 'lib/syntax_tree/node.rb', line 6067

def comments
  @comments
end

#constantObject (readonly)

nil | VarRef | ConstPathRef

the optional constant wrapper



6057
6058
6059
# File 'lib/syntax_tree/node.rb', line 6057

def constant
  @constant
end

#keyword_restObject (readonly)

nil | VarField

an optional parameter to gather up all remaining keywords



6064
6065
6066
# File 'lib/syntax_tree/node.rb', line 6064

def keyword_rest
  @keyword_rest
end

#keywordsObject (readonly)

Array[ [DynaSymbol | Label, nil | Node

]] the set of tuples

representing the keywords that should be matched against in the pattern



6061
6062
6063
# File 'lib/syntax_tree/node.rb', line 6061

def keywords
  @keywords
end

Instance Method Details

#===(other) ⇒ Object



6162
6163
6164
6165
6166
6167
6168
6169
# File 'lib/syntax_tree/node.rb', line 6162

def ===(other)
  other.is_a?(HshPtn) && constant === other.constant &&
    keywords.length == other.keywords.length &&
    keywords
      .zip(other.keywords)
      .all? { |left, right| ArrayMatch.call(left, right) } &&
    keyword_rest === other.keyword_rest
end

#accept(visitor) ⇒ Object



6077
6078
6079
# File 'lib/syntax_tree/node.rb', line 6077

def accept(visitor)
  visitor.visit_hshptn(self)
end

#child_nodesObject Also known as: deconstruct



6081
6082
6083
# File 'lib/syntax_tree/node.rb', line 6081

def child_nodes
  [constant, *keywords.flatten(1), keyword_rest]
end

#copy(constant: nil, keywords: nil, keyword_rest: nil, location: nil) ⇒ Object



6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
# File 'lib/syntax_tree/node.rb', line 6085

def copy(constant: nil, keywords: nil, keyword_rest: nil, location: nil)
  node =
    HshPtn.new(
      constant: constant || self.constant,
      keywords: keywords || self.keywords,
      keyword_rest: keyword_rest || self.keyword_rest,
      location: location || self.location
    )

  node.comments.concat(comments.map(&:copy))
  node
end

#deconstruct_keys(_keys) ⇒ Object



6100
6101
6102
6103
6104
6105
6106
6107
6108
# File 'lib/syntax_tree/node.rb', line 6100

def deconstruct_keys(_keys)
  {
    constant: constant,
    keywords: keywords,
    keyword_rest: keyword_rest,
    location: location,
    comments: comments
  }
end

#format(q) ⇒ Object



6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
# File 'lib/syntax_tree/node.rb', line 6110

def format(q)
  parts = keywords.map { |(key, value)| KeywordFormatter.new(key, value) }
  parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
  nested = PATTERNS.include?(q.parent.class)

  # If there is a constant, we're going to format to have the constant name
  # first and then use brackets.
  if constant
    q.group do
      q.format(constant)
      q.text("[")
      q.indent do
        q.breakable_empty
        format_contents(q, parts, nested)
      end
      q.breakable_empty
      q.text("]")
    end
    return
  end

  # If there's nothing at all, then we're going to use empty braces.
  if parts.empty?
    q.text("{}")
    return
  end

  # If there's only one pair, then we'll just print the contents provided
  # we're not inside another pattern.
  if !nested && parts.size == 1
    format_contents(q, parts, nested)
    return
  end

  # Otherwise, we're going to always use braces to make it clear it's a hash
  # pattern.
  q.group do
    q.text("{")
    q.indent do
      q.breakable_space
      format_contents(q, parts, nested)
    end

    if q.target_ruby_version < Formatter::SemanticVersion.new("2.7.3")
      q.text(" }")
    else
      q.breakable_space
      q.text("}")
    end
  end
end