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:, comments: []) ⇒ HshPtn

Returns a new instance of HshPtn.



4990
4991
4992
4993
4994
4995
4996
# File 'lib/syntax_tree/node.rb', line 4990

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

Instance Attribute Details

#comments ⇒ Object (readonly)

[Array[ Comment | EmbDoc ]] the comments attached to this node



4988
4989
4990
# File 'lib/syntax_tree/node.rb', line 4988

def comments
  @comments
end

#constant ⇒ Object (readonly)

[nil | untyped] the optional constant wrapper



4978
4979
4980
# File 'lib/syntax_tree/node.rb', line 4978

def constant
  @constant
end

#keyword_rest ⇒ Object (readonly)

[nil | VarField] an optional parameter to gather up all remaining keywords



4985
4986
4987
# File 'lib/syntax_tree/node.rb', line 4985

def keyword_rest
  @keyword_rest
end

#keywords ⇒ Object (readonly)

[Array[ [Label, untyped] ]] the set of tuples representing the keywords that should be matched against in the pattern



4982
4983
4984
# File 'lib/syntax_tree/node.rb', line 4982

def keywords
  @keywords
end

Instance Method Details

#accept(visitor) ⇒ Object



4998
4999
5000
# File 'lib/syntax_tree/node.rb', line 4998

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

#child_nodes ⇒ Object Also known as: deconstruct



5002
5003
5004
# File 'lib/syntax_tree/node.rb', line 5002

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

#deconstruct_keys(_keys) ⇒ Object



5008
5009
5010
5011
5012
5013
5014
5015
5016
# File 'lib/syntax_tree/node.rb', line 5008

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

#format(q) ⇒ Object



5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
# File 'lib/syntax_tree/node.rb', line 5018

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)
  contents = -> do
    q.group { q.seplist(parts) { |part| q.format(part, stackable: false) } }

    # If there isn't a constant, and there's a blank keyword_rest, then we
    # have an plain ** that needs to have a `then` after it in order to
    # parse correctly on the next parse.
    if !constant && keyword_rest && keyword_rest.value.nil? && !nested
      q.text(" then")
    end
  end

  # 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("")
        contents.call
      end
      q.breakable("")
      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
    contents.call
    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
      contents.call
    end
    q.breakable
    q.text("}")
  end
end