Class: Bash::Merge::NodeWrapper
- Inherits:
-
Object
- Object
- Bash::Merge::NodeWrapper
- Defined in:
- lib/bash/merge/node_wrapper.rb
Overview
Wraps TreeHaver nodes with comment associations, line information, and signatures. This provides a unified interface for working with Bash AST nodes during merging.
Instance Attribute Summary collapse
-
#end_line ⇒ Integer
readonly
End line (1-based).
-
#inline_comment ⇒ Hash?
readonly
Inline/trailing comment on the same line.
-
#leading_comments ⇒ Array<Hash>
readonly
Leading comments associated with this node.
-
#lines ⇒ Array<String>
readonly
Source lines.
-
#node ⇒ TreeHaver::Node
readonly
The wrapped tree-haver node.
-
#source ⇒ String
readonly
The original source string.
-
#start_line ⇒ Integer
readonly
Start line (1-based).
Instance Method Summary collapse
-
#case_statement? ⇒ Boolean
Check if this is a case statement.
-
#children ⇒ Array<NodeWrapper>
Get children wrapped as NodeWrappers.
-
#command? ⇒ Boolean
Check if this is a command.
-
#command_name ⇒ String?
Get the command name if this is a command.
-
#comment? ⇒ Boolean
Check if this is a comment.
-
#content ⇒ String
Get the content for this node from source lines.
-
#find_child_by_field(field_name) ⇒ TreeSitter::Node?
Find a child by field name.
-
#find_child_by_type(type_name) ⇒ TreeSitter::Node?
Find a child by type.
-
#for_statement? ⇒ Boolean
Check if this is a for loop.
-
#freeze_node? ⇒ Boolean
Check if this is a freeze node.
-
#function_definition? ⇒ Boolean
Check if this is a function definition.
-
#function_name ⇒ String?
Get the function name if this is a function definition.
-
#if_statement? ⇒ Boolean
Check if this is an if statement.
-
#initialize(node, lines:, source: nil, leading_comments: [], inline_comment: nil) ⇒ NodeWrapper
constructor
A new instance of NodeWrapper.
-
#inspect ⇒ String
String representation for debugging.
-
#node_text(ts_node) ⇒ String
Extract text from a tree-sitter node using byte positions.
-
#pipeline? ⇒ Boolean
Check if this is a pipeline.
-
#signature ⇒ Array?
Generate a signature for this node for matching purposes.
-
#text ⇒ String
Get the text content for this node by extracting from source using byte positions.
-
#type ⇒ Symbol
Get the node type as a symbol.
-
#type?(type_name) ⇒ Boolean
Check if this node has a specific type.
-
#variable_assignment? ⇒ Boolean
Check if this is a variable assignment.
-
#variable_name ⇒ String?
Get the variable name if this is a variable assignment.
-
#while_statement? ⇒ Boolean
Check if this is a while loop.
Constructor Details
#initialize(node, lines:, source: nil, leading_comments: [], inline_comment: nil) ⇒ NodeWrapper
Returns a new instance of NodeWrapper.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/bash/merge/node_wrapper.rb', line 41 def initialize(node, lines:, source: nil, leading_comments: [], inline_comment: nil) @node = node @lines = lines @source = source || lines.join("\n") @leading_comments = leading_comments @inline_comment = inline_comment # Extract line information from the tree-haver node (0-indexed to 1-indexed) if node.respond_to?(:start_point) point = node.start_point @start_line = (point.respond_to?(:row) ? point.row : point[:row]) + 1 end if node.respond_to?(:end_point) point = node.end_point @end_line = (point.respond_to?(:row) ? point.row : point[:row]) + 1 end # 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
#end_line ⇒ Integer (readonly)
Returns End line (1-based).
28 29 30 |
# File 'lib/bash/merge/node_wrapper.rb', line 28 def end_line @end_line end |
#inline_comment ⇒ Hash? (readonly)
Returns Inline/trailing comment on the same line.
22 23 24 |
# File 'lib/bash/merge/node_wrapper.rb', line 22 def inline_comment @inline_comment end |
#leading_comments ⇒ Array<Hash> (readonly)
Returns Leading comments associated with this node.
19 20 21 |
# File 'lib/bash/merge/node_wrapper.rb', line 19 def leading_comments @leading_comments end |
#lines ⇒ Array<String> (readonly)
Returns Source lines.
31 32 33 |
# File 'lib/bash/merge/node_wrapper.rb', line 31 def lines @lines end |
#node ⇒ TreeHaver::Node (readonly)
Returns The wrapped tree-haver node.
16 17 18 |
# File 'lib/bash/merge/node_wrapper.rb', line 16 def node @node end |
#source ⇒ String (readonly)
Returns The original source string.
34 35 36 |
# File 'lib/bash/merge/node_wrapper.rb', line 34 def source @source end |
#start_line ⇒ Integer (readonly)
Returns Start line (1-based).
25 26 27 |
# File 'lib/bash/merge/node_wrapper.rb', line 25 def start_line @start_line end |
Instance Method Details
#case_statement? ⇒ Boolean
Check if this is a case statement
121 122 123 |
# File 'lib/bash/merge/node_wrapper.rb', line 121 def case_statement? @node.type.to_s == "case_statement" end |
#children ⇒ Array<NodeWrapper>
Get children wrapped as NodeWrappers
179 180 181 182 183 184 185 186 187 |
# File 'lib/bash/merge/node_wrapper.rb', line 179 def children return [] unless @node.respond_to?(:each) result = [] @node.each do |child| result << NodeWrapper.new(child, lines: @lines, source: @source) end result end |
#command? ⇒ Boolean
Check if this is a command
127 128 129 |
# File 'lib/bash/merge/node_wrapper.rb', line 127 def command? @node.type.to_s == "command" end |
#command_name ⇒ String?
Get the command name if this is a command
165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/bash/merge/node_wrapper.rb', line 165 def command_name return unless command? # First child that is a word or simple_expansion @node.each do |child| next if %w[comment file_redirect heredoc_redirect].include?(child.type.to_s) return node_text(child) if %w[word command_name].include?(child.type.to_s) end nil end |
#comment? ⇒ Boolean
Check if this is a comment
139 140 141 |
# File 'lib/bash/merge/node_wrapper.rb', line 139 def comment? @node.type.to_s == "comment" end |
#content ⇒ String
Get the content for this node from source lines
227 228 229 230 231 |
# File 'lib/bash/merge/node_wrapper.rb', line 227 def content return "" unless @start_line && @end_line (@start_line..@end_line).map { |ln| @lines[ln - 1] }.compact.join("\n") end |
#find_child_by_field(field_name) ⇒ TreeSitter::Node?
Find a child by field name
192 193 194 195 196 |
# File 'lib/bash/merge/node_wrapper.rb', line 192 def find_child_by_field(field_name) return unless @node.respond_to?(:child_by_field_name) @node.child_by_field_name(field_name) end |
#find_child_by_type(type_name) ⇒ TreeSitter::Node?
Find a child by type
201 202 203 204 205 206 207 208 |
# File 'lib/bash/merge/node_wrapper.rb', line 201 def find_child_by_type(type_name) return unless @node.respond_to?(:each) @node.each do |child| return child if child.type.to_s == type_name end nil end |
#for_statement? ⇒ Boolean
Check if this is a for loop
109 110 111 |
# File 'lib/bash/merge/node_wrapper.rb', line 109 def for_statement? %w[for_statement c_style_for_statement].include?(@node.type.to_s) end |
#freeze_node? ⇒ Boolean
Check if this is a freeze node
72 73 74 |
# File 'lib/bash/merge/node_wrapper.rb', line 72 def freeze_node? false end |
#function_definition? ⇒ Boolean
Check if this is a function definition
91 92 93 |
# File 'lib/bash/merge/node_wrapper.rb', line 91 def function_definition? @node.type.to_s == "function_definition" end |
#function_name ⇒ String?
Get the function name if this is a function definition
145 146 147 148 149 150 151 |
# File 'lib/bash/merge/node_wrapper.rb', line 145 def function_name return unless function_definition? # In bash tree-sitter, function name is in a 'name' or 'word' child name_node = find_child_by_type("word") || find_child_by_field("name") node_text(name_node) if name_node end |
#if_statement? ⇒ Boolean
Check if this is an if statement
103 104 105 |
# File 'lib/bash/merge/node_wrapper.rb', line 103 def if_statement? @node.type.to_s == "if_statement" end |
#inspect ⇒ String
String representation for debugging
235 236 237 |
# File 'lib/bash/merge/node_wrapper.rb', line 235 def inspect "#<#{self.class.name} type=#{@node.type} lines=#{@start_line}..#{@end_line}>" end |
#node_text(ts_node) ⇒ String
Extract text from a tree-sitter node using byte positions
219 220 221 222 223 |
# File 'lib/bash/merge/node_wrapper.rb', line 219 def node_text(ts_node) return "" unless ts_node.respond_to?(:start_byte) && ts_node.respond_to?(:end_byte) @source[ts_node.start_byte...ts_node.end_byte] || "" end |
#pipeline? ⇒ Boolean
Check if this is a pipeline
133 134 135 |
# File 'lib/bash/merge/node_wrapper.rb', line 133 def pipeline? @node.type.to_s == "pipeline" end |
#signature ⇒ Array?
Generate a signature for this node for matching purposes. Signatures are used to identify corresponding nodes between template and destination.
66 67 68 |
# File 'lib/bash/merge/node_wrapper.rb', line 66 def signature compute_signature(@node) end |
#text ⇒ String
Get the text content for this node by extracting from source using byte positions
212 213 214 |
# File 'lib/bash/merge/node_wrapper.rb', line 212 def text node_text(@node) end |
#type ⇒ Symbol
Get the node type as a symbol
78 79 80 |
# File 'lib/bash/merge/node_wrapper.rb', line 78 def type @node.type.to_sym end |
#type?(type_name) ⇒ Boolean
Check if this node has a specific type
85 86 87 |
# File 'lib/bash/merge/node_wrapper.rb', line 85 def type?(type_name) @node.type.to_s == type_name.to_s end |
#variable_assignment? ⇒ Boolean
Check if this is a variable assignment
97 98 99 |
# File 'lib/bash/merge/node_wrapper.rb', line 97 def variable_assignment? @node.type.to_s == "variable_assignment" end |
#variable_name ⇒ String?
Get the variable name if this is a variable assignment
155 156 157 158 159 160 161 |
# File 'lib/bash/merge/node_wrapper.rb', line 155 def variable_name return unless variable_assignment? # In bash tree-sitter, variable name is a child of type 'variable_name' name_node = find_child_by_type("variable_name") node_text(name_node) if name_node end |
#while_statement? ⇒ Boolean
Check if this is a while loop
115 116 117 |
# File 'lib/bash/merge/node_wrapper.rb', line 115 def while_statement? @node.type.to_s == "while_statement" end |