Class: Psych::Merge::NodeWrapper
- Inherits:
-
Object
- Object
- Psych::Merge::NodeWrapper
- Defined in:
- lib/psych/merge/node_wrapper.rb
Overview
Wraps Psych::Nodes with comment associations, line information, and signatures. This provides a unified interface for working with YAML nodes during merging.
Instance Attribute Summary collapse
-
#comment_tracker ⇒ CommentTracker?
readonly
Comment tracker used to associate comments.
-
#end_line ⇒ Integer
readonly
End line (1-based).
-
#inline_comment ⇒ Hash?
readonly
Inline/trailing comment on the same line.
-
#key ⇒ String?
readonly
Key name for mapping entries.
-
#leading_comments ⇒ Array<Hash>
readonly
Leading comments associated with this node.
-
#lines ⇒ Array<String>
readonly
Source lines.
-
#node ⇒ Psych::Nodes::Node
readonly
The wrapped Psych node.
-
#start_line ⇒ Integer
readonly
Start line (1-based).
Instance Method Summary collapse
-
#alias? ⇒ Boolean
Check if this wraps an alias node.
-
#alias_anchor ⇒ String?
Get the aliased anchor name.
-
#anchor ⇒ String?
Get the anchor name if this node has one.
-
#children(comment_tracker: nil) ⇒ Array<NodeWrapper>
Get children wrapped as NodeWrappers.
-
#comment_attachment ⇒ Ast::Merge::Comment::Attachment
Get a passive shared comment attachment for this node wrapper.
-
#content ⇒ String
Get the content for this node from source lines.
-
#freeze_node? ⇒ Boolean
Check if this is a freeze node.
-
#initialize(node, lines:, leading_comments: [], inline_comment: nil, key: nil, comment_tracker: nil, next_sibling_line_num: nil, next_sibling_leading_comments: nil, end_line_limit: nil, **_options) ⇒ NodeWrapper
constructor
A new instance of NodeWrapper.
- #inline_comment_region ⇒ Ast::Merge::Comment::Region?
-
#inspect ⇒ String
String representation for debugging.
- #leading_comment_region ⇒ Ast::Merge::Comment::Region?
-
#mapping? ⇒ Boolean
Check if this wraps a mapping node.
-
#mapping_entries(comment_tracker: nil) ⇒ Array<Array(NodeWrapper, NodeWrapper)>
Get mapping entries as key-value pairs of NodeWrappers.
-
#scalar? ⇒ Boolean
Check if this wraps a scalar node.
-
#sequence? ⇒ Boolean
Check if this wraps a sequence node.
-
#sequence_items(comment_tracker: nil) ⇒ Array<NodeWrapper>
Get sequence items as NodeWrappers.
-
#signature ⇒ Array?
Generate a signature for this node for matching purposes.
-
#to_s ⇒ String
String representation of the node value.
-
#value ⇒ String?
Get the scalar value.
Constructor Details
#initialize(node, lines:, leading_comments: [], inline_comment: nil, key: nil, comment_tracker: nil, next_sibling_line_num: nil, next_sibling_leading_comments: nil, end_line_limit: nil, **_options) ⇒ NodeWrapper
Returns a new instance of NodeWrapper.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/psych/merge/node_wrapper.rb', line 42 def initialize( node, lines:, leading_comments: [], inline_comment: nil, key: nil, comment_tracker: nil, next_sibling_line_num: nil, next_sibling_leading_comments: nil, end_line_limit: nil, ** ) @node = node @lines = lines @leading_comments = leading_comments @inline_comment = inline_comment @key = key @comment_tracker = comment_tracker # Extract line information from the Psych node. # # IMPORTANT: Psych (libyaml) line number semantics: # - start_line: 0-based, inclusive (first line of the node's content) # - end_line: 0-based, EXCLUSIVE (points to the line AFTER the last content line) # # Example for a mapping value spanning lines 4-5 (1-based): # Psych reports: start_line=3, end_line=5 (0-based) # - start_line=3 means line 4 (1-based) - correct # - end_line=5 means "up to but not including line 5 (0-based)", # i.e., last included line is 4 (0-based) = line 5 (1-based) # # Conversion to 1-based inclusive range: # - @start_line = node.start_line + 1 (0-based inclusive → 1-based inclusive) # - @end_line = node.end_line (0-based exclusive → 1-based inclusive, since exclusive-1+1=same) # # If Psych/libyaml ever changes end_line to be inclusive, this will need adjustment. # See regression test: "does not duplicate keys when destination adds a new nested mapping" @start_line = node.start_line + 1 if node.respond_to?(:start_line) && node.start_line @end_line = node.end_line if node.respond_to?(:end_line) && node.end_line clamp_end_line_to_next_sibling!(next_sibling_line_num, next_sibling_leading_comments, end_line_limit) # Handle edge case where end_line might be before start_line @end_line = @start_line if @start_line && @end_line && @end_line < @start_line end |
Instance Attribute Details
#comment_tracker ⇒ CommentTracker? (readonly)
Returns Comment tracker used to associate comments.
35 36 37 |
# File 'lib/psych/merge/node_wrapper.rb', line 35 def comment_tracker @comment_tracker end |
#end_line ⇒ Integer (readonly)
Returns End line (1-based).
26 27 28 |
# File 'lib/psych/merge/node_wrapper.rb', line 26 def end_line @end_line end |
#inline_comment ⇒ Hash? (readonly)
Returns Inline/trailing comment on the same line.
20 21 22 |
# File 'lib/psych/merge/node_wrapper.rb', line 20 def inline_comment @inline_comment end |
#key ⇒ String? (readonly)
Returns Key name for mapping entries.
29 30 31 |
# File 'lib/psych/merge/node_wrapper.rb', line 29 def key @key end |
#leading_comments ⇒ Array<Hash> (readonly)
Returns Leading comments associated with this node.
17 18 19 |
# File 'lib/psych/merge/node_wrapper.rb', line 17 def leading_comments @leading_comments end |
#lines ⇒ Array<String> (readonly)
Returns Source lines.
32 33 34 |
# File 'lib/psych/merge/node_wrapper.rb', line 32 def lines @lines end |
#node ⇒ Psych::Nodes::Node (readonly)
Returns The wrapped Psych node.
14 15 16 |
# File 'lib/psych/merge/node_wrapper.rb', line 14 def node @node end |
#start_line ⇒ Integer (readonly)
Returns Start line (1-based).
23 24 25 |
# File 'lib/psych/merge/node_wrapper.rb', line 23 def start_line @start_line end |
Instance Method Details
#alias? ⇒ Boolean
Check if this wraps an alias node
122 123 124 |
# File 'lib/psych/merge/node_wrapper.rb', line 122 def alias? NodeTypeNormalizer.canonical_type(@node.class.name.split('::').last.downcase, :psych) == :alias end |
#alias_anchor ⇒ String?
Get the aliased anchor name
195 196 197 |
# File 'lib/psych/merge/node_wrapper.rb', line 195 def alias_anchor @node.anchor if alias? end |
#anchor ⇒ String?
Get the anchor name if this node has one
128 129 130 |
# File 'lib/psych/merge/node_wrapper.rb', line 128 def anchor @node.anchor if @node.respond_to?(:anchor) end |
#children(comment_tracker: nil) ⇒ Array<NodeWrapper>
Get children wrapped as NodeWrappers
135 136 137 138 139 |
# File 'lib/psych/merge/node_wrapper.rb', line 135 def children(comment_tracker: nil) return [] unless @node.respond_to?(:children) && @node.children wrap_children(@node.children, comment_tracker) end |
#comment_attachment ⇒ Ast::Merge::Comment::Attachment
Get a passive shared comment attachment for this node wrapper.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/psych/merge/node_wrapper.rb', line 210 def @comment_attachment ||= if @comment_tracker @comment_tracker.( self, line_num: @start_line, leading_comments: @leading_comments, inline_comment: @inline_comment, key: @key ) else Ast::Merge::Comment::Attachment.new( owner: self, leading_region: build_comment_region(:leading, @leading_comments), inline_region: build_comment_region(:inline, [@inline_comment].compact), metadata: { key: @key } ) end end |
#content ⇒ String
Get the content for this node from source lines
201 202 203 204 205 |
# File 'lib/psych/merge/node_wrapper.rb', line 201 def content return '' unless @start_line && @end_line (@start_line..@end_line).map { |ln| @lines[ln - 1] }.join end |
#freeze_node? ⇒ Boolean
Check if this is a freeze node
98 99 100 |
# File 'lib/psych/merge/node_wrapper.rb', line 98 def freeze_node? false end |
#inline_comment_region ⇒ Ast::Merge::Comment::Region?
235 236 237 |
# File 'lib/psych/merge/node_wrapper.rb', line 235 def inline_comment_region .inline_region end |
#inspect ⇒ String
String representation for debugging
249 250 251 252 |
# File 'lib/psych/merge/node_wrapper.rb', line 249 def inspect node_type = @node.class.name.split('::').last "#<#{self.class.name} type=#{node_type} lines=#{@start_line}..#{@end_line} key=#{@key.inspect}>" end |
#leading_comment_region ⇒ Ast::Merge::Comment::Region?
230 231 232 |
# File 'lib/psych/merge/node_wrapper.rb', line 230 def leading_comment_region .leading_region end |
#mapping? ⇒ Boolean
Check if this wraps a mapping node
104 105 106 |
# File 'lib/psych/merge/node_wrapper.rb', line 104 def mapping? NodeTypeNormalizer.canonical_type(@node.class.name.split('::').last.downcase, :psych) == :mapping end |
#mapping_entries(comment_tracker: nil) ⇒ Array<Array(NodeWrapper, NodeWrapper)>
Get mapping entries as key-value pairs of NodeWrappers
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/psych/merge/node_wrapper.rb', line 144 def mapping_entries(comment_tracker: nil) return [] unless mapping? entries = [] children = @node.children i = 0 while i < children.length key_node = children[i] value_node = children[i + 1] break unless key_node && value_node key_wrapper = wrap_node(key_node, comment_tracker) value_wrapper = wrap_node( value_node, comment_tracker, key: extract_key_name(key_node), next_sibling_node: children[i + 2], end_line_limit: @end_line ) entries << [key_wrapper, value_wrapper] i += 2 end entries end |
#scalar? ⇒ Boolean
Check if this wraps a scalar node
116 117 118 |
# File 'lib/psych/merge/node_wrapper.rb', line 116 def scalar? NodeTypeNormalizer.canonical_type(@node.class.name.split('::').last.downcase, :psych) == :scalar end |
#sequence? ⇒ Boolean
Check if this wraps a sequence node
110 111 112 |
# File 'lib/psych/merge/node_wrapper.rb', line 110 def sequence? NodeTypeNormalizer.canonical_type(@node.class.name.split('::').last.downcase, :psych) == :sequence end |
#sequence_items(comment_tracker: nil) ⇒ Array<NodeWrapper>
Get sequence items as NodeWrappers
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/psych/merge/node_wrapper.rb', line 174 def sequence_items(comment_tracker: nil) return [] unless sequence? @node.children.each_with_index.map do |child, index| wrap_node( child, comment_tracker, next_sibling_node: @node.children[index + 1], end_line_limit: @end_line ) end end |
#signature ⇒ Array?
Generate a signature for this node for matching purposes. Signatures are used to identify corresponding nodes between template and destination.
92 93 94 |
# File 'lib/psych/merge/node_wrapper.rb', line 92 def signature compute_signature(@node) end |
#to_s ⇒ String
String representation of the node value. For scalars, returns the value. For other nodes, returns inspect.
243 244 245 |
# File 'lib/psych/merge/node_wrapper.rb', line 243 def to_s value || inspect end |
#value ⇒ String?
Get the scalar value
189 190 191 |
# File 'lib/psych/merge/node_wrapper.rb', line 189 def value @node.value if scalar? end |