Class: Oxc::Node

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Enumerable[Oxc::Node]
Defined in:
lib/oxc/node.rb,
sig/oxc/node.rbs

Constant Summary collapse

ACRONYM =

Signature:

  • Regexp

Returns:

  • (Regexp)
/([A-Z]+)([A-Z][a-z])/
BOUNDARY =

Signature:

  • Regexp

Returns:

  • (Regexp)
/([a-z\d])([A-Z])/
SPAN =

Signature:

  • Array[String]

Returns:

  • (Array[String])
["type", "start", "end"].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes, parent = nil, text = nil) ⇒ Node

: (Hash[String, untyped], ?Oxc::Node?, ?String?) -> void

Parameters:

  • (Hash[String, untyped])
  • (Oxc::Node, nil)
  • (String, nil)


21
22
23
24
25
# File 'lib/oxc/node.rb', line 21

def initialize(attributes, parent = nil, text = nil)
  @attributes = attributes
  @parent = parent
  @text = text || parent&.text
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *arguments) ⇒ Object

: (Symbol, *untyped) -> untyped

Parameters:

  • (Symbol)
  • (Object)

Returns:

  • (Object)


140
141
142
143
144
145
146
# File 'lib/oxc/node.rb', line 140

def method_missing(name, *arguments)
  key = field_for(name.to_s)

  return super unless key

  wrap(attributes[key])
end

Instance Attribute Details

#attributesHash[String, untyped] (readonly)

Signature:

  • Hash[String, untyped]

Returns:

  • (Hash[String, untyped])


15
16
17
# File 'lib/oxc/node.rb', line 15

def attributes
  @attributes
end

#parentOxc::Node? (readonly)

Signature:

  • Oxc::Node?

Returns:



11
12
13
# File 'lib/oxc/node.rb', line 11

def parent
  @parent
end

#textString? (readonly)

Signature:

  • String?

Returns:

  • (String, nil)


16
17
18
# File 'lib/oxc/node.rb', line 16

def text
  @text
end

Instance Method Details

#[](key) ⇒ Object

: (String) -> untyped

Parameters:

  • (String)

Returns:

  • (Object)


48
49
50
# File 'lib/oxc/node.rb', line 48

def [](key)
  attributes[key]
end

#ancestorsArray[Oxc::Node]

: () -> Array

Returns:



111
112
113
# File 'lib/oxc/node.rb', line 111

def ancestors
  parent ? [parent, *parent.ancestors] : []
end

#at(offset) ⇒ Oxc::Node?

: (Integer) -> Oxc::Node?

Parameters:

  • (Integer)

Returns:



116
117
118
119
120
# File 'lib/oxc/node.rb', line 116

def at(offset)
  covering = each.select { |node| offset >= node.start && offset < node.finish }

  covering.min_by { |node| node.finish - node.start }
end

#child_nodesArray[Oxc::Node]

: () -> Array

Returns:



92
93
94
95
96
97
98
# File 'lib/oxc/node.rb', line 92

def child_nodes
  @child_nodes ||= attributes.each_value
                             .flat_map { |value| value.is_a?(Array) ? value : [value] }
                             .select { |value| value.is_a?(Hash) && value.key?("type") }
                             .map { |value| Node.new(value, self) }
                             .freeze
end

#deconstruct_keys(keys) ⇒ Hash[Symbol, untyped]

: (Array?) -> Hash[Symbol, untyped]

Parameters:

  • (Array[Symbol], nil)

Returns:

  • (Hash[Symbol, untyped])


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/oxc/node.rb', line 75

def deconstruct_keys(keys)
  found = {} #: Hash[Symbol, untyped]

  if keys
    keys.each do |name|
      key = field_for(name.to_s)

      found[name] = wrap(attributes[key]) if key
    end
  else
    attributes.each_key { |key| found[key.to_sym] = wrap(attributes[key]) }
  end

  found
end

#described_field(key, value) ⇒ String

: (String, untyped) -> String

Parameters:

  • (String)
  • (Object)

Returns:

  • (String)


156
157
158
159
160
161
162
163
164
165
166
# File 'lib/oxc/node.rb', line 156

def described_field(key, value)
  case value
  when Array then "#{key}=#{if value.empty?
                              "[]"
                            else
                              "[... #{value.length} #{value.length == 1 ? "item" : "items"}]"
                            end}"
  when Hash then "#{key}=#<#{self.class.name} #{value["type"]}>"
  else "#{key}=#{value.inspect}"
  end
end

#eachvoid #eachEnumerator[Oxc::Node, void]

: () { (Oxc::Node) -> void } -> void : () -> Enumerator[Oxc::Node, void]

Overloads:

  • #eachvoid

    This method returns an undefined value.

  • #eachEnumerator[Oxc::Node, void]

    Returns:

Yields:

Yield Parameters:

Yield Returns:

  • (void)


102
103
104
105
106
107
108
# File 'lib/oxc/node.rb', line 102

def each(&)
  return enum_for(:each) unless block_given?

  yield self

  child_nodes.each { |child| child.each(&) }
end

#every(type) ⇒ Array[Oxc::Node]

: (String) -> Array

Parameters:

  • (String)

Returns:



123
124
125
# File 'lib/oxc/node.rb', line 123

def every(type)
  each.select { |node| node.type == type }
end

#field_for(name) ⇒ String?

: (String) -> String?

Parameters:

  • (String)

Returns:

  • (String, nil)


169
170
171
172
173
174
175
# File 'lib/oxc/node.rb', line 169

def field_for(name)
  return name if attributes.key?(name)

  camelized = name.gsub(/_([a-z\d])/) { Regexp.last_match(1).to_s.upcase }

  camelized if attributes.key?(camelized)
end

#fieldsHash[String, untyped]

: () -> Hash[String, untyped]

Returns:

  • (Hash[String, untyped])


128
129
130
# File 'lib/oxc/node.rb', line 128

def fields
  attributes.except(*SPAN)
end

#finishInteger

: () -> Integer

Returns:

  • (Integer)


38
39
40
# File 'lib/oxc/node.rb', line 38

def finish
  attributes.fetch("end")
end

#inspectString

: () -> String

Returns:

  • (String)


133
134
135
136
137
# File 'lib/oxc/node.rb', line 133

def inspect
  described = fields.map { |key, value| described_field(key, value) }

  "#<#{self.class.name} #{type} range=[#{start}, #{finish}]#{" #{described.join(" ")}" unless described.empty?}>"
end

#keysArray[String]

: () -> Array

Returns:

  • (Array[String])


60
61
62
# File 'lib/oxc/node.rb', line 60

def keys
  attributes.keys
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

: (Symbol, ?bool) -> bool

Parameters:

  • (Symbol)
  • (Boolean)

Returns:

  • (Boolean)


149
150
151
# File 'lib/oxc/node.rb', line 149

def respond_to_missing?(name, include_private = false)
  !field_for(name.to_s).nil? || super
end

#slice(from = text) ⇒ String?

: (?String?) -> String?

Parameters:

  • (String, nil)

Returns:

  • (String, nil)


53
54
55
56
57
# File 'lib/oxc/node.rb', line 53

def slice(from = text)
  raise ArgumentError, "this node does not know its source, so #slice needs it" unless from

  from.byteslice(start, finish - start)
end

#startInteger

: () -> Integer

Returns:

  • (Integer)


33
34
35
# File 'lib/oxc/node.rb', line 33

def start
  attributes.fetch("start")
end

#to_hHash[String, untyped]

: () -> Hash[String, untyped]

Returns:

  • (Hash[String, untyped])


65
66
67
# File 'lib/oxc/node.rb', line 65

def to_h
  attributes
end

#to_json(state = nil) ⇒ String

: (?untyped) -> String

Parameters:

  • (Object)

Returns:

  • (String)


70
71
72
# File 'lib/oxc/node.rb', line 70

def to_json(state = nil)
  state ? attributes.to_json(state) : attributes.to_json
end

#typeString

: () -> String

Returns:

  • (String)


28
29
30
# File 'lib/oxc/node.rb', line 28

def type
  attributes.fetch("type")
end

#underscored_typeString

: () -> String

Returns:

  • (String)


43
44
45
# File 'lib/oxc/node.rb', line 43

def underscored_type
  @underscored_type ||= type.gsub(ACRONYM, '\1_\2').gsub(BOUNDARY, '\1_\2').downcase
end

#wrap(value) ⇒ Object

: (untyped) -> untyped

Parameters:

  • (Object)

Returns:

  • (Object)


178
179
180
181
182
183
184
# File 'lib/oxc/node.rb', line 178

def wrap(value)
  case value
  when Hash then value.key?("type") ? Node.new(value, self, text) : value
  when Array then value.map { |item| wrap(item) }
  else value
  end
end