tree_haver 3.1.0 → 3.1.2

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.
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TreeHaver RSpec Integration
4
+ #
5
+ # This file provides RSpec helpers and configuration for testing
6
+ # code that uses TreeHaver. Require this in your spec_helper.rb:
7
+ #
8
+ # require "tree_haver/rspec"
9
+ #
10
+ # This will load:
11
+ # - Dependency tags for conditional test execution
12
+ # - (Future) Additional test helpers as needed
13
+ #
14
+ # @example spec_helper.rb
15
+ # require "tree_haver/rspec"
16
+ #
17
+ # RSpec.configure do |config|
18
+ # # Your additional configuration...
19
+ # end
20
+ #
21
+ # @see TreeHaver::RSpec::DependencyTags
22
+
23
+ require_relative "rspec/dependency_tags"
@@ -156,7 +156,7 @@ module TreeHaver
156
156
  raise unless e.name == :edit || e.message.include?("edit")
157
157
  raise TreeHaver::NotAvailable,
158
158
  "Incremental parsing not supported by current backend. " \
159
- "Use MRI (ruby_tree_sitter), Rust (tree_stump), or Java (java-tree-sitter) backend."
159
+ "Use MRI (ruby_tree_sitter), Rust (tree_stump), or Java (java-tree-sitter / jtreesitter) backend."
160
160
  end
161
161
 
162
162
  private
@@ -10,7 +10,7 @@ module TreeHaver
10
10
  # Current version of the tree_haver gem
11
11
  #
12
12
  # @return [String] the version string (e.g., "3.0.0")
13
- VERSION = "3.1.0"
13
+ VERSION = "3.1.2"
14
14
  end
15
15
 
16
16
  # Traditional location for VERSION constant
data/lib/tree_haver.rb CHANGED
@@ -212,6 +212,9 @@ module TreeHaver
212
212
  # @see CitrusGrammarFinder
213
213
  autoload :CitrusGrammarFinder, File.join(__dir__, "tree_haver", "citrus_grammar_finder")
214
214
 
215
+ # Point class for position information (row, column)
216
+ autoload :Point, File.join(__dir__, "tree_haver", "point")
217
+
215
218
  # Unified Node wrapper providing consistent API across backends
216
219
  autoload :Node, File.join(__dir__, "tree_haver", "node")
217
220
 
@@ -725,6 +728,111 @@ module TreeHaver
725
728
  def registered_language(name)
726
729
  LanguageRegistry.registered(name)
727
730
  end
731
+
732
+ # Create a parser configured for a specific language
733
+ #
734
+ # This is the recommended high-level API for creating a parser. It handles:
735
+ # 1. Checking if the language is already registered
736
+ # 2. Auto-discovering tree-sitter grammar via GrammarFinder
737
+ # 3. Falling back to Citrus grammar if tree-sitter is unavailable
738
+ # 4. Creating and configuring the parser
739
+ #
740
+ # @param language_name [Symbol, String] the language to parse (e.g., :toml, :json, :bash)
741
+ # @param library_path [String, nil] optional explicit path to tree-sitter grammar library
742
+ # @param symbol [String, nil] optional tree-sitter symbol name (defaults to "tree_sitter_<name>")
743
+ # @param citrus_config [Hash, nil] optional Citrus fallback configuration
744
+ # @option citrus_config [String] :gem_name gem name for the Citrus grammar
745
+ # @option citrus_config [String] :grammar_const fully qualified constant name for grammar module
746
+ # @return [TreeHaver::Parser] configured parser with language set
747
+ # @raise [TreeHaver::NotAvailable] if no parser backend is available for the language
748
+ #
749
+ # @example Basic usage (auto-discovers grammar)
750
+ # parser = TreeHaver.parser_for(:toml)
751
+ # tree = parser.parse("[package]\nname = \"my-app\"")
752
+ #
753
+ # @example With explicit library path
754
+ # parser = TreeHaver.parser_for(:toml, library_path: "/custom/path/libtree-sitter-toml.so")
755
+ #
756
+ # @example With Citrus fallback configuration
757
+ # parser = TreeHaver.parser_for(:toml,
758
+ # citrus_config: { gem_name: "toml-rb", grammar_const: "TomlRB::Document" }
759
+ # )
760
+ def parser_for(language_name, library_path: nil, symbol: nil, citrus_config: nil)
761
+ name = language_name.to_sym
762
+ symbol ||= "tree_sitter_#{name}"
763
+
764
+ # Step 1: Try to get the language (may already be registered)
765
+ language = begin
766
+ # Check if already registered and loadable
767
+ if registered_language(name)
768
+ Language.public_send(name, path: library_path, symbol: symbol)
769
+ end
770
+ rescue NotAvailable, ArgumentError, LoadError
771
+ nil
772
+ end
773
+
774
+ # Step 2: If not registered, try GrammarFinder for tree-sitter
775
+ unless language
776
+ # Principle of Least Surprise: If user provides an explicit path,
777
+ # it MUST exist. Don't silently fall back to auto-discovery.
778
+ if library_path && !library_path.empty?
779
+ unless File.exist?(library_path)
780
+ raise NotAvailable,
781
+ "Specified parser path does not exist: #{library_path}"
782
+ end
783
+ begin
784
+ register_language(name, path: library_path, symbol: symbol)
785
+ language = Language.public_send(name)
786
+ rescue NotAvailable, ArgumentError, LoadError => e
787
+ # Re-raise with more context since user explicitly provided this path
788
+ raise NotAvailable,
789
+ "Failed to load parser from specified path #{library_path}: #{e.message}"
790
+ end
791
+ else
792
+ # Auto-discover via GrammarFinder (no explicit path provided)
793
+ begin
794
+ finder = GrammarFinder.new(name)
795
+ if finder.available?
796
+ finder.register!
797
+ language = Language.public_send(name)
798
+ end
799
+ rescue NotAvailable, ArgumentError, LoadError
800
+ language = nil
801
+ end
802
+ end
803
+ end
804
+
805
+ # Step 3: Try Citrus fallback if tree-sitter failed
806
+ unless language
807
+ citrus_config ||= {}
808
+ begin
809
+ citrus_finder = CitrusGrammarFinder.new(
810
+ language: name,
811
+ gem_name: citrus_config[:gem_name],
812
+ grammar_const: citrus_config[:grammar_const],
813
+ )
814
+ if citrus_finder.available?
815
+ citrus_finder.register!
816
+ language = Language.public_send(name)
817
+ end
818
+ rescue NotAvailable, ArgumentError, LoadError, NameError
819
+ language = nil
820
+ end
821
+ end
822
+
823
+ # Step 4: Raise if nothing worked
824
+ unless language
825
+ raise NotAvailable,
826
+ "No parser available for #{name}. " \
827
+ "Install tree-sitter-#{name} or the appropriate Ruby gem. " \
828
+ "Set TREE_SITTER_#{name.to_s.upcase}_PATH for custom grammar location."
829
+ end
830
+
831
+ # Step 5: Create and configure parser
832
+ parser = Parser.new
833
+ parser.language = language
834
+ parser
835
+ end
728
836
  end
729
837
 
730
838
  # Represents a tree-sitter language grammar
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tree_haver
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -133,6 +133,26 @@ dependencies:
133
133
  - - "~>"
134
134
  - !ruby/object:Gem::Version
135
135
  version: '3.0'
136
+ - !ruby/object:Gem::Dependency
137
+ name: kettle-soup-cover
138
+ requirement: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '1.1'
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 1.1.1
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.1'
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: 1.1.1
136
156
  - !ruby/object:Gem::Dependency
137
157
  name: kettle-test
138
158
  requirement: !ruby/object:Gem::Requirement
@@ -255,6 +275,9 @@ files:
255
275
  - lib/tree_haver/language_registry.rb
256
276
  - lib/tree_haver/node.rb
257
277
  - lib/tree_haver/path_validator.rb
278
+ - lib/tree_haver/point.rb
279
+ - lib/tree_haver/rspec.rb
280
+ - lib/tree_haver/rspec/dependency_tags.rb
258
281
  - lib/tree_haver/tree.rb
259
282
  - lib/tree_haver/version.rb
260
283
  - sig/tree_haver.rbs
@@ -266,10 +289,10 @@ licenses:
266
289
  - MIT
267
290
  metadata:
268
291
  homepage_uri: https://tree-haver.galtzo.com/
269
- source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v3.1.0
270
- changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v3.1.0/CHANGELOG.md
292
+ source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v3.1.2
293
+ changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v3.1.2/CHANGELOG.md
271
294
  bug_tracker_uri: https://github.com/kettle-rb/tree_haver/issues
272
- documentation_uri: https://www.rubydoc.info/gems/tree_haver/3.1.0
295
+ documentation_uri: https://www.rubydoc.info/gems/tree_haver/3.1.2
273
296
  funding_uri: https://github.com/sponsors/pboling
274
297
  wiki_uri: https://github.com/kettle-rb/tree_haver/wiki
275
298
  news_uri: https://www.railsbling.com/tags/tree_haver
@@ -299,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
299
322
  - !ruby/object:Gem::Version
300
323
  version: '0'
301
324
  requirements: []
302
- rubygems_version: 4.0.1
325
+ rubygems_version: 4.0.3
303
326
  specification_version: 4
304
327
  summary: "\U0001F334 Cross-Ruby adapter for tree-sitter parsing that works on MRI,
305
328
  JRuby, and TruffleRuby"
metadata.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- o�&�z5��G�&U��mo��Z~�Yu8:2ٖOF����*q�|�x| �
2
- �V��zwᵻ��j�^62�/
1
+ ]��:cD1@M���S��ܖq��.8�V� ��h��p�����g�.�dn ����
2
+ K
3
+ c�Ll 捻�r�5>���p �|sl�UԤb���zS��+"1�~㿄 U��j.���F��o3��,ǥ!# �a�)���9��ŬЍij��tU�4��J�