Class: TreeHaver::Backends::Psych::Node
- Inherits:
-
Object
- Object
- TreeHaver::Backends::Psych::Node
- Includes:
- Comparable
- Defined in:
- lib/tree_haver/backends/psych.rb
Overview
Psych node wrapper
Wraps Psych::Nodes::* classes to provide TreeHaver::Node-compatible interface.
Psych node types:
-
Stream: Root container
-
Document: YAML document (multiple per stream possible)
-
Mapping: Hash/object
-
Sequence: Array/list
-
Scalar: Primitive value (string, number, boolean, null)
-
Alias: YAML anchor reference
Instance Attribute Summary collapse
-
#inner_node ⇒ ::Psych::Nodes::Node
readonly
The underlying Psych node.
-
#source ⇒ String
readonly
The original source.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer?
Comparison for sorting.
-
#alias? ⇒ Boolean
Psych-specific: Check if this is an alias.
-
#anchor ⇒ String?
Psych-specific: Get the anchor name for Alias/anchored nodes.
-
#child(index) ⇒ Node?
Get child by index.
-
#child_count ⇒ Integer
Get the number of children.
-
#children ⇒ Array<Node>
Get child nodes.
-
#each {|Node| ... } ⇒ Enumerator?
Iterate over child nodes.
-
#end_byte ⇒ Integer
Get end byte offset.
-
#end_line ⇒ Integer
Get the 1-based line number where this node ends.
-
#end_point ⇒ Point
Get end point (row, column).
-
#first_child ⇒ Node?
Get the first child node.
-
#has_error? ⇒ Boolean
Check if the node or any descendant has an error.
-
#initialize(node, source, lines = nil) ⇒ Node
constructor
Create a new node wrapper.
-
#inspect ⇒ String
Human-readable representation.
-
#mapping? ⇒ Boolean
Psych-specific: Check if this is a mapping (hash).
-
#mapping_entries ⇒ Array<Array(Node, Node)>
Psych-specific: Get mapping entries as key-value pairs.
-
#missing? ⇒ Boolean
Check if this is a missing node.
-
#named? ⇒ Boolean
(also: #structural?)
Check if this is a named (structural) node.
-
#scalar? ⇒ Boolean
Psych-specific: Check if this is a scalar (primitive).
-
#sequence? ⇒ Boolean
Psych-specific: Check if this is a sequence (array).
-
#source_position ⇒ Hash{Symbol => Integer}
Get position information as a hash.
-
#start_byte ⇒ Integer
Get start byte offset.
-
#start_line ⇒ Integer
Get the 1-based line number where this node starts.
-
#start_point ⇒ Point
Get start point (row, column).
-
#tag ⇒ String?
Psych-specific: Get the tag for tagged nodes.
-
#text ⇒ String
Get the text content of this node.
-
#type ⇒ String
(also: #kind)
Get the node type as a string.
-
#value ⇒ String?
Psych-specific: Get the scalar value.
Constructor Details
#initialize(node, source, lines = nil) ⇒ Node
Create a new node wrapper
246 247 248 249 250 |
# File 'lib/tree_haver/backends/psych.rb', line 246 def initialize(node, source, lines = nil) @inner_node = node @source = source @lines = lines || source.lines end |
Instance Attribute Details
#inner_node ⇒ ::Psych::Nodes::Node (readonly)
Returns The underlying Psych node.
236 237 238 |
# File 'lib/tree_haver/backends/psych.rb', line 236 def inner_node @inner_node end |
#source ⇒ String (readonly)
Returns The original source.
239 240 241 |
# File 'lib/tree_haver/backends/psych.rb', line 239 def source @source end |
Instance Method Details
#<=>(other) ⇒ Integer?
Comparison for sorting
437 438 439 440 441 442 |
# File 'lib/tree_haver/backends/psych.rb', line 437 def <=>(other) return unless other.respond_to?(:start_byte) cmp = start_byte <=> other.start_byte return cmp unless cmp&.zero? end_byte <=> other.end_byte end |
#alias? ⇒ Boolean
Psych-specific: Check if this is an alias
494 495 496 |
# File 'lib/tree_haver/backends/psych.rb', line 494 def alias? @inner_node.is_a?(::Psych::Nodes::Alias) end |
#anchor ⇒ String?
Psych-specific: Get the anchor name for Alias/anchored nodes
452 453 454 |
# File 'lib/tree_haver/backends/psych.rb', line 452 def anchor @inner_node.anchor if @inner_node.respond_to?(:anchor) end |
#child(index) ⇒ Node?
Get child by index
317 318 319 |
# File 'lib/tree_haver/backends/psych.rb', line 317 def child(index) children[index] end |
#child_count ⇒ Integer
Get the number of children
309 310 311 |
# File 'lib/tree_haver/backends/psych.rb', line 309 def child_count children.size end |
#children ⇒ Array<Node>
Get child nodes
291 292 293 294 295 |
# File 'lib/tree_haver/backends/psych.rb', line 291 def children return [] unless @inner_node.respond_to?(:children) && @inner_node.children @inner_node.children.map { |child| Node.new(child, @source, @lines) } end |
#each {|Node| ... } ⇒ Enumerator?
Iterate over child nodes
301 302 303 304 |
# File 'lib/tree_haver/backends/psych.rb', line 301 def each(&block) return to_enum(__method__) unless block children.each(&block) end |
#end_byte ⇒ Integer
Get end byte offset
337 338 339 340 341 342 343 |
# File 'lib/tree_haver/backends/psych.rb', line 337 def end_byte return start_byte + text.bytesize unless @inner_node.respond_to?(:end_line) line = @inner_node.end_line || 0 col = @inner_node.end_column || 0 calculate_byte_offset(line, col) end |
#end_line ⇒ Integer
Get the 1-based line number where this node ends
376 377 378 379 |
# File 'lib/tree_haver/backends/psych.rb', line 376 def end_line row = end_point.row row + 1 end |
#end_point ⇒ Point
Get end point (row, column)
357 358 359 360 361 |
# File 'lib/tree_haver/backends/psych.rb', line 357 def end_point row = (@inner_node.respond_to?(:end_line) ? @inner_node.end_line : 0) || 0 col = (@inner_node.respond_to?(:end_column) ? @inner_node.end_column : 0) || 0 Point.new(row, col) end |
#first_child ⇒ Node?
Get the first child node
399 400 401 |
# File 'lib/tree_haver/backends/psych.rb', line 399 def first_child children.first end |
#has_error? ⇒ Boolean
Check if the node or any descendant has an error
Psych raises on errors rather than embedding them.
420 421 422 |
# File 'lib/tree_haver/backends/psych.rb', line 420 def has_error? false end |
#inspect ⇒ String
Returns human-readable representation.
445 446 447 |
# File 'lib/tree_haver/backends/psych.rb', line 445 def inspect "#<TreeHaver::Backends::Psych::Node type=#{type} children=#{child_count}>" end |
#mapping? ⇒ Boolean
Psych-specific: Check if this is a mapping (hash)
473 474 475 |
# File 'lib/tree_haver/backends/psych.rb', line 473 def mapping? @inner_node.is_a?(::Psych::Nodes::Mapping) end |
#mapping_entries ⇒ Array<Array(Node, Node)>
Psych-specific: Get mapping entries as key-value pairs
For Mapping nodes, children alternate key, value, key, value…
503 504 505 506 507 508 509 510 511 |
# File 'lib/tree_haver/backends/psych.rb', line 503 def mapping_entries return [] unless mapping? pairs = [] children.each_slice(2) do |key, val| pairs << [key, val] if key && val end pairs end |
#missing? ⇒ Boolean
Check if this is a missing node
Psych doesn’t have missing nodes.
429 430 431 |
# File 'lib/tree_haver/backends/psych.rb', line 429 def missing? false end |
#named? ⇒ Boolean Also known as: structural?
Check if this is a named (structural) node
All Psych nodes are structural.
408 409 410 |
# File 'lib/tree_haver/backends/psych.rb', line 408 def named? true end |
#scalar? ⇒ Boolean
Psych-specific: Check if this is a scalar (primitive)
487 488 489 |
# File 'lib/tree_haver/backends/psych.rb', line 487 def scalar? @inner_node.is_a?(::Psych::Nodes::Scalar) end |
#sequence? ⇒ Boolean
Psych-specific: Check if this is a sequence (array)
480 481 482 |
# File 'lib/tree_haver/backends/psych.rb', line 480 def sequence? @inner_node.is_a?(::Psych::Nodes::Sequence) end |
#source_position ⇒ Hash{Symbol => Integer}
Get position information as a hash
Returns a hash with 1-based line numbers and 0-based columns. Compatible with *-merge gems’ FileAnalysisBase.
387 388 389 390 391 392 393 394 |
# File 'lib/tree_haver/backends/psych.rb', line 387 def source_position { start_line: start_line, end_line: end_line, start_column: start_point.column, end_column: end_point.column, } end |
#start_byte ⇒ Integer
Get start byte offset
Psych doesn’t provide byte offsets directly, so we calculate from line/column.
326 327 328 329 330 331 332 |
# File 'lib/tree_haver/backends/psych.rb', line 326 def start_byte return 0 unless @inner_node.respond_to?(:start_line) line = @inner_node.start_line || 0 col = @inner_node.start_column || 0 calculate_byte_offset(line, col) end |
#start_line ⇒ Integer
Get the 1-based line number where this node starts
Psych provides 0-based line numbers, so we add 1.
368 369 370 371 |
# File 'lib/tree_haver/backends/psych.rb', line 368 def start_line row = start_point.row row + 1 end |
#start_point ⇒ Point
Get start point (row, column)
348 349 350 351 352 |
# File 'lib/tree_haver/backends/psych.rb', line 348 def start_point row = (@inner_node.respond_to?(:start_line) ? @inner_node.start_line : 0) || 0 col = (@inner_node.respond_to?(:start_column) ? @inner_node.start_column : 0) || 0 Point.new(row, col) end |
#tag ⇒ String?
Psych-specific: Get the tag for tagged nodes
459 460 461 |
# File 'lib/tree_haver/backends/psych.rb', line 459 def tag @inner_node.tag if @inner_node.respond_to?(:tag) end |
#text ⇒ String
Get the text content of this node
For Scalar nodes, returns the value. For containers, returns the source text spanning the node’s location.
276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/tree_haver/backends/psych.rb', line 276 def text case @inner_node when ::Psych::Nodes::Scalar @inner_node.value.to_s when ::Psych::Nodes::Alias "*#{@inner_node.anchor}" else # For container nodes, extract from source using location extract_text_from_location end end |
#type ⇒ String Also known as: kind
Get the node type as a string
Maps Psych class names to lowercase type strings:
-
Psych::Nodes::Stream → “stream”
-
Psych::Nodes::Document → “document”
-
Psych::Nodes::Mapping → “mapping”
-
Psych::Nodes::Sequence → “sequence”
-
Psych::Nodes::Scalar → “scalar”
-
Psych::Nodes::Alias → “alias”
263 264 265 |
# File 'lib/tree_haver/backends/psych.rb', line 263 def type @inner_node.class.name.split("::").last.downcase end |
#value ⇒ String?
Psych-specific: Get the scalar value
466 467 468 |
# File 'lib/tree_haver/backends/psych.rb', line 466 def value @inner_node.value if @inner_node.respond_to?(:value) end |