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.



6001
6002
6003
6004
6005
6006
6007
# File 'lib/syntax_tree/node.rb', line 6001

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



5999
6000
6001
# File 'lib/syntax_tree/node.rb', line 5999

def comments
  @comments
end

#constantObject (readonly)

nil | Node

the optional constant wrapper



5989
5990
5991
# File 'lib/syntax_tree/node.rb', line 5989

def constant
  @constant
end

#keyword_restObject (readonly)

nil | VarField

an optional parameter to gather up all remaining keywords



5996
5997
5998
# File 'lib/syntax_tree/node.rb', line 5996

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



5993
5994
5995
# File 'lib/syntax_tree/node.rb', line 5993

def keywords
  @keywords
end

Instance Method Details

#===(other) ⇒ Object



6094
6095
6096
6097
6098
6099
6100
6101
# File 'lib/syntax_tree/node.rb', line 6094

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



6009
6010
6011
# File 'lib/syntax_tree/node.rb', line 6009

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

#child_nodesObject Also known as: deconstruct



6013
6014
6015
# File 'lib/syntax_tree/node.rb', line 6013

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

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



6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
# File 'lib/syntax_tree/node.rb', line 6017

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



6032
6033
6034
6035
6036
6037
6038
6039
6040
# File 'lib/syntax_tree/node.rb', line 6032

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

#format(q) ⇒ Object



6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
# File 'lib/syntax_tree/node.rb', line 6042

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