tree_haver 5.0.4 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/tree_haver/backend_context.rb +28 -0
  4. data/lib/tree_haver/backend_registry.rb +19 -432
  5. data/lib/tree_haver/contracts.rb +460 -0
  6. data/lib/tree_haver/kaitai_backend.rb +30 -0
  7. data/lib/tree_haver/language_pack.rb +190 -0
  8. data/lib/tree_haver/peg_backends.rb +76 -0
  9. data/lib/tree_haver/version.rb +1 -12
  10. data/lib/tree_haver.rb +7 -1316
  11. data.tar.gz.sig +0 -0
  12. metadata +34 -245
  13. metadata.gz.sig +0 -0
  14. data/CHANGELOG.md +0 -1366
  15. data/CITATION.cff +0 -20
  16. data/CODE_OF_CONDUCT.md +0 -134
  17. data/CONTRIBUTING.md +0 -359
  18. data/FUNDING.md +0 -74
  19. data/LICENSE.txt +0 -21
  20. data/README.md +0 -2347
  21. data/REEK +0 -0
  22. data/RUBOCOP.md +0 -71
  23. data/SECURITY.md +0 -21
  24. data/lib/tree_haver/backend_api.rb +0 -349
  25. data/lib/tree_haver/backends/citrus.rb +0 -487
  26. data/lib/tree_haver/backends/ffi.rb +0 -1009
  27. data/lib/tree_haver/backends/java.rb +0 -893
  28. data/lib/tree_haver/backends/mri.rb +0 -362
  29. data/lib/tree_haver/backends/parslet.rb +0 -560
  30. data/lib/tree_haver/backends/prism.rb +0 -471
  31. data/lib/tree_haver/backends/psych.rb +0 -375
  32. data/lib/tree_haver/backends/rust.rb +0 -239
  33. data/lib/tree_haver/base/language.rb +0 -98
  34. data/lib/tree_haver/base/node.rb +0 -322
  35. data/lib/tree_haver/base/parser.rb +0 -24
  36. data/lib/tree_haver/base/point.rb +0 -48
  37. data/lib/tree_haver/base/tree.rb +0 -128
  38. data/lib/tree_haver/base.rb +0 -12
  39. data/lib/tree_haver/citrus_grammar_finder.rb +0 -218
  40. data/lib/tree_haver/compat.rb +0 -43
  41. data/lib/tree_haver/grammar_finder.rb +0 -374
  42. data/lib/tree_haver/language.rb +0 -295
  43. data/lib/tree_haver/language_registry.rb +0 -190
  44. data/lib/tree_haver/library_path_utils.rb +0 -80
  45. data/lib/tree_haver/node.rb +0 -579
  46. data/lib/tree_haver/parser.rb +0 -438
  47. data/lib/tree_haver/parslet_grammar_finder.rb +0 -224
  48. data/lib/tree_haver/path_validator.rb +0 -353
  49. data/lib/tree_haver/point.rb +0 -27
  50. data/lib/tree_haver/rspec/dependency_tags.rb +0 -1392
  51. data/lib/tree_haver/rspec/testable_node.rb +0 -217
  52. data/lib/tree_haver/rspec.rb +0 -33
  53. data/lib/tree_haver/tree.rb +0 -258
  54. data/sig/tree_haver/backends.rbs +0 -352
  55. data/sig/tree_haver/grammar_finder.rbs +0 -29
  56. data/sig/tree_haver/path_validator.rbs +0 -32
  57. data/sig/tree_haver.rbs +0 -234
@@ -1,375 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TreeHaver
4
- module Backends
5
- # Psych backend using Ruby's built-in YAML parser
6
- #
7
- # This backend wraps Psych, Ruby's standard library YAML parser.
8
- # Psych provides AST access via Psych.parse_stream which returns
9
- # Psych::Nodes::* objects (Stream, Document, Mapping, Sequence, Scalar, Alias).
10
- #
11
- # @note This backend only parses YAML source code
12
- # @see https://ruby-doc.org/stdlib/libdoc/psych/rdoc/Psych.html Psych documentation
13
- #
14
- # @example Basic usage
15
- # parser = TreeHaver::Parser.new
16
- # parser.language = TreeHaver::Backends::Psych::Language.yaml
17
- # tree = parser.parse(yaml_source)
18
- # root = tree.root_node
19
- # puts root.type # => "stream"
20
- module Psych
21
- @load_attempted = false
22
- @loaded = false
23
-
24
- # Check if the Psych backend is available
25
- #
26
- # Psych is part of Ruby stdlib, so it should always be available.
27
- #
28
- # @return [Boolean] true if psych is available
29
- class << self
30
- def available?
31
- return @loaded if @load_attempted # rubocop:disable ThreadSafety/ClassInstanceVariable
32
- @load_attempted = true # rubocop:disable ThreadSafety/ClassInstanceVariable
33
- begin
34
- require "psych"
35
- @loaded = true # rubocop:disable ThreadSafety/ClassInstanceVariable
36
- rescue LoadError
37
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
38
- rescue StandardError
39
- # :nocov: defensive code - StandardError during require is extremely rare
40
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
41
- # :nocov:
42
- end
43
- @loaded # rubocop:disable ThreadSafety/ClassInstanceVariable
44
- end
45
-
46
- # Reset the load state (primarily for testing)
47
- #
48
- # @return [void]
49
- # @api private
50
- def reset!
51
- @load_attempted = false # rubocop:disable ThreadSafety/ClassInstanceVariable
52
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
53
- end
54
-
55
- # Get capabilities supported by this backend
56
- #
57
- # @return [Hash{Symbol => Object}] capability map
58
- def capabilities
59
- return {} unless available?
60
- {
61
- backend: :psych,
62
- query: false, # Psych doesn't have tree-sitter-style queries
63
- bytes_field: false, # Psych uses line/column, not byte offsets
64
- incremental: false, # Psych doesn't support incremental parsing
65
- pure_ruby: false, # Psych has native libyaml C extension
66
- yaml_only: true, # Psych only parses YAML
67
- error_tolerant: false, # Psych raises on syntax errors
68
- }
69
- end
70
- end
71
-
72
- # Psych language wrapper
73
- #
74
- # Unlike tree-sitter which supports many languages via grammar files,
75
- # Psych only parses YAML. This class exists for API compatibility with
76
- # other tree_haver backends.
77
- #
78
- # @example
79
- # language = TreeHaver::Backends::Psych::Language.yaml
80
- # parser.language = language
81
- class Language < TreeHaver::Base::Language
82
- # Create a new Psych language instance
83
- #
84
- # @param name [Symbol] Language name (should be :yaml)
85
- def initialize(name = :yaml)
86
- super(name, backend: :psych, options: {})
87
- end
88
-
89
- class << self
90
- # Create a YAML language instance
91
- #
92
- # @return [Language] YAML language
93
- def yaml
94
- new(:yaml)
95
- end
96
-
97
- # Load language from library path (API compatibility)
98
- #
99
- # Psych only supports YAML, so path and symbol parameters are ignored.
100
- #
101
- # @param _path [String] Ignored - Psych doesn't load external grammars
102
- # @param symbol [String, nil] Ignored - Psych only supports YAML
103
- # @param name [String, nil] Language name hint (defaults to :yaml)
104
- # @return [Language] YAML language
105
- # @raise [TreeHaver::NotAvailable] if requested language is not YAML
106
- def from_library(_path = nil, symbol: nil, name: nil) # rubocop:disable Lint/UnusedMethodArgument
107
- lang_name = name || :yaml
108
-
109
- unless lang_name == :yaml
110
- raise TreeHaver::NotAvailable,
111
- "Psych backend only supports YAML, not #{lang_name}. " \
112
- "Use a tree-sitter backend for #{lang_name} support."
113
- end
114
-
115
- yaml
116
- end
117
- end
118
- end
119
-
120
- # Psych parser wrapper
121
- #
122
- # Wraps Psych.parse_stream to provide TreeHaver-compatible parsing.
123
- #
124
- # @example
125
- # parser = TreeHaver::Backends::Psych::Parser.new
126
- # parser.language = Language.yaml
127
- # tree = parser.parse(yaml_source)
128
- class Parser < TreeHaver::Base::Parser
129
- # Parse YAML source code
130
- #
131
- # @param source [String] YAML source to parse
132
- # @return [Tree] Parsed tree
133
- # @raise [::Psych::SyntaxError] on syntax errors
134
- def parse(source)
135
- raise "Language not set" unless language
136
- Psych.available? or raise "Psych not available"
137
-
138
- ast = ::Psych.parse_stream(source)
139
- Tree.new(ast, source)
140
- end
141
-
142
- # Alias for compatibility with tree-sitter API
143
- #
144
- # @param _old_tree [nil] Ignored (Psych doesn't support incremental parsing)
145
- # @param source [String] YAML source to parse
146
- # @return [Tree] Parsed tree
147
- def parse_string(_old_tree, source)
148
- parse(source)
149
- end
150
- end
151
-
152
- # Psych tree wrapper
153
- #
154
- # Wraps a Psych::Nodes::Stream to provide TreeHaver-compatible tree interface.
155
- class Tree < TreeHaver::Base::Tree
156
- # @return [::Psych::Nodes::Stream] The underlying Psych stream
157
- attr_reader :inner_tree
158
-
159
- # Create a new tree wrapper
160
- #
161
- # @param stream [::Psych::Nodes::Stream] Psych stream node
162
- # @param source [String] Original source
163
- def initialize(stream, source)
164
- super(stream, source: source)
165
- end
166
-
167
- # Get the root node
168
- #
169
- # @return [Node] Root node
170
- def root_node
171
- Node.new(inner_tree, source: source, lines: lines)
172
- end
173
-
174
- # Human-readable representation
175
- def inspect
176
- "#<TreeHaver::Backends::Psych::Tree documents=#{inner_tree.children&.size || 0}>"
177
- end
178
- end
179
-
180
- # Psych node wrapper
181
- #
182
- # Wraps Psych::Nodes::* classes to provide TreeHaver::Node-compatible interface.
183
- #
184
- # Psych node types:
185
- # - Stream: Root container
186
- # - Document: YAML document (multiple per stream possible)
187
- # - Mapping: Hash/object
188
- # - Sequence: Array/list
189
- # - Scalar: Primitive value (string, number, boolean, null)
190
- # - Psych::Nodes::Alias: YAML anchor reference
191
- class Node < TreeHaver::Base::Node
192
- # Get the node type as a string
193
- #
194
- # @return [String] Node type
195
- def type
196
- inner_node.class.name.split("::").last.downcase
197
- end
198
-
199
- # Alias for type (API compatibility)
200
- # @return [String] node type
201
- def kind
202
- type
203
- end
204
-
205
- # Get the text content of this node
206
- #
207
- # @return [String] Node text
208
- def text
209
- case inner_node
210
- when ::Psych::Nodes::Scalar
211
- inner_node.value.to_s
212
- when ::Psych::Nodes::Alias
213
- "*#{inner_node.anchor}"
214
- else
215
- # For container nodes, extract from source using location
216
- extract_text_from_location
217
- end
218
- end
219
-
220
- # Get child nodes
221
- #
222
- # @return [Array<Node>] Child nodes
223
- def children
224
- return [] unless inner_node.respond_to?(:children) && inner_node.children
225
-
226
- inner_node.children.map { |child| Node.new(child, source: source, lines: lines) }
227
- end
228
-
229
- # Get start byte offset
230
- #
231
- # @return [Integer] Start byte offset
232
- def start_byte
233
- return 0 unless inner_node.respond_to?(:start_line)
234
-
235
- line = inner_node.start_line || 0
236
- col = inner_node.start_column || 0
237
- calculate_byte_offset(line, col)
238
- end
239
-
240
- # Get end byte offset
241
- #
242
- # @return [Integer] End byte offset
243
- def end_byte
244
- return start_byte + text.bytesize unless inner_node.respond_to?(:end_line)
245
-
246
- line = inner_node.end_line || 0
247
- col = inner_node.end_column || 0
248
- calculate_byte_offset(line, col)
249
- end
250
-
251
- # Get start point (row, column) - 0-based
252
- #
253
- # @return [TreeHaver::Base::Point] Start position
254
- def start_point
255
- row = (inner_node.respond_to?(:start_line) ? inner_node.start_line : 0) || 0
256
- col = (inner_node.respond_to?(:start_column) ? inner_node.start_column : 0) || 0
257
- TreeHaver::Base::Point.new(row, col)
258
- end
259
-
260
- # Get end point (row, column) - 0-based
261
- #
262
- # @return [TreeHaver::Base::Point] End position
263
- def end_point
264
- row = (inner_node.respond_to?(:end_line) ? inner_node.end_line : 0) || 0
265
- col = (inner_node.respond_to?(:end_column) ? inner_node.end_column : 0) || 0
266
- TreeHaver::Base::Point.new(row, col)
267
- end
268
-
269
- # Psych-specific: Get the anchor name for Alias/anchored nodes
270
- #
271
- # @return [String, nil] Anchor name
272
- def anchor
273
- inner_node.anchor if inner_node.respond_to?(:anchor)
274
- end
275
-
276
- # Psych-specific: Get the tag for tagged nodes
277
- #
278
- # @return [String, nil] Tag
279
- def tag
280
- inner_node.tag if inner_node.respond_to?(:tag)
281
- end
282
-
283
- # Psych-specific: Get the scalar value
284
- #
285
- # @return [String, nil] Value for scalar nodes
286
- def value
287
- inner_node.value if inner_node.respond_to?(:value)
288
- end
289
-
290
- # Psych-specific: Check if this is a mapping (hash)
291
- #
292
- # @return [Boolean]
293
- def mapping?
294
- inner_node.is_a?(::Psych::Nodes::Mapping)
295
- end
296
-
297
- # Psych-specific: Check if this is a sequence (array)
298
- #
299
- # @return [Boolean]
300
- def sequence?
301
- inner_node.is_a?(::Psych::Nodes::Sequence)
302
- end
303
-
304
- # Psych-specific: Check if this is a scalar (primitive)
305
- #
306
- # @return [Boolean]
307
- def scalar?
308
- inner_node.is_a?(::Psych::Nodes::Scalar)
309
- end
310
-
311
- # Psych-specific: Check if this is an alias
312
- #
313
- # @return [Boolean]
314
- def alias?
315
- inner_node.is_a?(::Psych::Nodes::Alias)
316
- end
317
-
318
- # Psych-specific: Get mapping entries as key-value pairs
319
- #
320
- # For Mapping nodes, children alternate key, value, key, value...
321
- #
322
- # @return [Array<Array(Node, Node)>] Key-value pairs
323
- def mapping_entries
324
- return [] unless mapping?
325
-
326
- pairs = []
327
- children.each_slice(2) do |key, val|
328
- pairs << [key, val] if key && val
329
- end
330
- pairs
331
- end
332
-
333
- private
334
-
335
- # Extract text from source using location
336
- #
337
- # @return [String] Extracted text
338
- def extract_text_from_location
339
- return "" unless inner_node.respond_to?(:start_line) && inner_node.respond_to?(:end_line)
340
-
341
- start_ln = inner_node.start_line || 0
342
- end_ln = inner_node.end_line || start_ln
343
- start_col = inner_node.start_column || 0
344
- end_col = inner_node.end_column || 0
345
-
346
- if start_ln == end_ln
347
- line = lines[start_ln] || ""
348
- line[start_col...end_col] || ""
349
- else
350
- result = []
351
- (start_ln..end_ln).each do |ln|
352
- line = lines[ln] || ""
353
- result << if ln == start_ln
354
- line[start_col..]
355
- elsif ln == end_ln
356
- line[0...end_col]
357
- else
358
- line
359
- end
360
- end
361
- result.compact.join
362
- end
363
- end
364
- end
365
-
366
- # Alias Point to the base class for compatibility
367
- Point = TreeHaver::Base::Point
368
-
369
- # Register the availability checker for RSpec dependency tags
370
- TreeHaver::BackendRegistry.register_availability_checker(:psych) do
371
- available?
372
- end
373
- end
374
- end
375
- end
@@ -1,239 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TreeHaver
4
- module Backends
5
- # Rust backend using the tree_stump gem
6
- #
7
- # This backend wraps the tree_stump gem, which provides Ruby bindings to
8
- # tree-sitter written in Rust. It offers native performance with Rust's
9
- # safety guarantees and includes precompiled binaries for common platforms.
10
- #
11
- # tree_stump supports incremental parsing and the Query API, making it
12
- # suitable for editor/IDE use cases where performance is critical.
13
- #
14
- # == Tree/Node Architecture
15
- #
16
- # This backend (like all tree-sitter backends: MRI, Rust, FFI, Java) does NOT
17
- # define its own Tree or Node classes. Instead:
18
- #
19
- # - Parser#parse returns raw `::TreeStump::Tree` objects
20
- # - These are wrapped by `TreeHaver::Tree` (inherits from `Base::Tree`)
21
- # - `TreeHaver::Tree#root_node` wraps raw nodes in `TreeHaver::Node`
22
- #
23
- # This differs from pure-Ruby backends (Citrus, Prism, Psych) which define
24
- # their own `Backend::X::Tree` and `Backend::X::Node` classes.
25
- #
26
- # @see TreeHaver::Tree The wrapper class for tree-sitter Tree objects
27
- # @see TreeHaver::Node The wrapper class for tree-sitter Node objects
28
- # @see TreeHaver::Base::Tree Base class documenting the Tree API contract
29
- # @see TreeHaver::Base::Node Base class documenting the Node API contract
30
- #
31
- # == Platform Compatibility
32
- #
33
- # - MRI Ruby: ✓ Full support
34
- # - JRuby: ✗ Cannot load native extensions (runs on JVM)
35
- # - TruffleRuby: ✗ magnus/rb-sys incompatible with TruffleRuby's C API emulation
36
- #
37
- # @see https://github.com/joker1007/tree_stump tree_stump
38
- module Rust
39
- @load_attempted = false
40
- @loaded = false
41
-
42
- # Check if the Rust backend is available
43
- #
44
- # Attempts to require tree_stump on first call and caches the result.
45
- #
46
- # @return [Boolean] true if tree_stump is available
47
- # @example
48
- # if TreeHaver::Backends::Rust.available?
49
- # puts "Rust backend is ready"
50
- # end
51
- class << self
52
- def available?
53
- return @loaded if @load_attempted # rubocop:disable ThreadSafety/ClassInstanceVariable
54
- @load_attempted = true # rubocop:disable ThreadSafety/ClassInstanceVariable
55
- begin
56
- # tree_stump uses magnus which requires MRI's C API
57
- # It doesn't work on JRuby or TruffleRuby
58
- if RUBY_ENGINE == "ruby"
59
- require "tree_stump"
60
- @loaded = true # rubocop:disable ThreadSafety/ClassInstanceVariable
61
- else
62
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
63
- end
64
- rescue LoadError
65
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
66
- rescue StandardError
67
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
68
- end
69
- @loaded # rubocop:disable ThreadSafety/ClassInstanceVariable
70
- end
71
-
72
- # Reset the load state (primarily for testing)
73
- #
74
- # @return [void]
75
- # @api private
76
- def reset!
77
- @load_attempted = false # rubocop:disable ThreadSafety/ClassInstanceVariable
78
- @loaded = false # rubocop:disable ThreadSafety/ClassInstanceVariable
79
- end
80
-
81
- # Get capabilities supported by this backend
82
- #
83
- # @return [Hash{Symbol => Object}] capability map
84
- # @example
85
- # TreeHaver::Backends::Rust.capabilities
86
- # # => { backend: :rust, query: true, bytes_field: true, incremental: false }
87
- def capabilities
88
- return {} unless available?
89
- {
90
- backend: :rust,
91
- query: true,
92
- bytes_field: true,
93
- incremental: false, # TreeStump doesn't currently expose incremental parsing to Ruby
94
- }
95
- end
96
- end
97
-
98
- # Wrapper for tree_stump Language
99
- #
100
- # Provides TreeHaver-compatible interface to tree_stump's language loading.
101
- # tree_stump uses a registration-based API where languages are registered
102
- # by name, then referenced by that name when setting parser language.
103
- class Language
104
- include Comparable
105
-
106
- # The registered language name
107
- # @return [String]
108
- attr_reader :name
109
-
110
- # The backend this language is for
111
- # @return [Symbol]
112
- attr_reader :backend
113
-
114
- # The path this language was loaded from (if known)
115
- # @return [String, nil]
116
- attr_reader :path
117
-
118
- # @api private
119
- # @param name [String] the registered language name
120
- # @param path [String, nil] path language was loaded from
121
- def initialize(name, path: nil)
122
- @name = name
123
- @backend = :rust
124
- @path = path
125
- end
126
-
127
- # Compare languages for equality
128
- #
129
- # Rust languages are equal if they have the same backend and name.
130
- # Name uniquely identifies a registered language in TreeStump.
131
- #
132
- # @param other [Object] object to compare with
133
- # @return [Integer, nil] -1, 0, 1, or nil if not comparable
134
- def <=>(other)
135
- return unless other.is_a?(Language)
136
- return unless other.backend == @backend
137
-
138
- @name <=> other.name
139
- end
140
-
141
- # Hash value for this language (for use in Sets/Hashes)
142
- # @return [Integer]
143
- def hash
144
- [@backend, @name].hash
145
- end
146
-
147
- # Alias eql? to ==
148
- alias_method :eql?, :==
149
-
150
- # Load a language from a shared library path
151
- #
152
- # @param path [String] absolute path to the language shared library
153
- # @param symbol [String, nil] the symbol name (accepted for API consistency, but tree_stump derives it from name)
154
- # @param name [String, nil] logical name for the language (optional, derived from path if not provided)
155
- # @return [Language] a wrapper holding the registered language name
156
- # @raise [TreeHaver::NotAvailable] if tree_stump is not available
157
- # @example
158
- # lang = TreeHaver::Backends::Rust::Language.from_library("/usr/local/lib/libtree-sitter-toml.so")
159
- class << self
160
- def from_library(path, symbol: nil, name: nil) # rubocop:disable Lint/UnusedMethodArgument
161
- raise TreeHaver::NotAvailable, "tree_stump not available" unless Rust.available?
162
-
163
- # Validate the path exists before calling register_lang to provide a clear error
164
- raise TreeHaver::NotAvailable, "Language library not found: #{path}" unless File.exist?(path)
165
-
166
- # tree_stump uses TreeStump.register_lang(name, path) to register languages
167
- # The name is used to derive the symbol automatically (tree_sitter_<name>)
168
- # Use shared utility for consistent path parsing across backends
169
- lang_name = name || LibraryPathUtils.derive_language_name_from_path(path)
170
- ::TreeStump.register_lang(lang_name, path)
171
- new(lang_name, path: path)
172
- rescue RuntimeError => e
173
- raise TreeHaver::NotAvailable, "Failed to load language from #{path}: #{e.message}"
174
- end
175
-
176
- # Backward-compatible alias for from_library
177
- alias_method :from_path, :from_library
178
- end
179
- end
180
-
181
- # Wrapper for tree_stump Parser
182
- #
183
- # Provides TreeHaver-compatible interface to tree_stump's parser.
184
- class Parser
185
- # Create a new parser instance
186
- #
187
- # @raise [TreeHaver::NotAvailable] if tree_stump is not available
188
- def initialize
189
- raise TreeHaver::NotAvailable, "tree_stump not available" unless Rust.available?
190
- @parser = ::TreeStump::Parser.new
191
- end
192
-
193
- # Set the language for this parser
194
- #
195
- # Note: TreeHaver::Parser unwraps language objects before calling this method.
196
- # When called from TreeHaver::Parser, receives String (language name).
197
- # For backward compatibility and backend tests, also handles Language wrapper.
198
- #
199
- # @param lang [Language, String] the language wrapper or name string
200
- # @return [Language, String] the language that was set
201
- def language=(lang)
202
- # Extract language name (handle both wrapper and raw string)
203
- lang_name = lang.respond_to?(:name) ? lang.name : lang.to_s
204
- # tree_stump uses set_language with a string name
205
- @parser.set_language(lang_name)
206
- lang # rubocop:disable Lint/Void (intentional return value)
207
- end
208
-
209
- # Parse source code
210
- #
211
- # @param source [String] the source code to parse
212
- # @return [TreeStump::Tree] raw backend tree (wrapping happens in TreeHaver::Parser)
213
- def parse(source)
214
- # Return raw tree_stump tree - TreeHaver::Parser will wrap it
215
- @parser.parse(source)
216
- end
217
-
218
- # Parse source code with optional incremental parsing
219
- #
220
- # Note: TreeStump does not currently expose incremental parsing to Ruby.
221
- # The parse method always does a full parse, ignoring old_tree.
222
- #
223
- # @param old_tree [TreeHaver::Tree, nil] previous tree for incremental parsing (ignored)
224
- # @param source [String] the source code to parse
225
- # @return [TreeStump::Tree] raw backend tree (wrapping happens in TreeHaver::Parser)
226
- def parse_string(old_tree, source) # rubocop:disable Lint/UnusedMethodArgument
227
- # TreeStump's parse method only accepts source as a single argument
228
- # and internally always passes None for the old tree (no incremental parsing support)
229
- @parser.parse(source)
230
- end
231
- end
232
-
233
- # Register the availability checker for RSpec dependency tags
234
- TreeHaver::BackendRegistry.register_availability_checker(:rust) do
235
- available?
236
- end
237
- end
238
- end
239
- end