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, #pretty_print, #to_json

Constructor Details

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

Returns a new instance of HshPtn.



5946
5947
5948
5949
5950
5951
5952
# File 'lib/syntax_tree/node.rb', line 5946

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



5944
5945
5946
# File 'lib/syntax_tree/node.rb', line 5944

def comments
  @comments
end

#constantObject (readonly)

nil | untyped

the optional constant wrapper



5934
5935
5936
# File 'lib/syntax_tree/node.rb', line 5934

def constant
  @constant
end

#keyword_restObject (readonly)

nil | VarField

an optional parameter to gather up all remaining keywords



5941
5942
5943
# File 'lib/syntax_tree/node.rb', line 5941

def keyword_rest
  @keyword_rest
end

#keywordsObject (readonly)

Array[ [Label, untyped

]] the set of tuples representing the keywords

that should be matched against in the pattern



5938
5939
5940
# File 'lib/syntax_tree/node.rb', line 5938

def keywords
  @keywords
end

Instance Method Details

#===(other) ⇒ Object



6039
6040
6041
6042
6043
6044
6045
6046
# File 'lib/syntax_tree/node.rb', line 6039

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



5954
5955
5956
# File 'lib/syntax_tree/node.rb', line 5954

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

#child_nodesObject Also known as: deconstruct



5958
5959
5960
# File 'lib/syntax_tree/node.rb', line 5958

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

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



5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
# File 'lib/syntax_tree/node.rb', line 5962

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



5977
5978
5979
5980
5981
5982
5983
5984
5985
# File 'lib/syntax_tree/node.rb', line 5977

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

#format(q) ⇒ Object



5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
# File 'lib/syntax_tree/node.rb', line 5987

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