tree_haver 5.0.0 → 5.0.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.
@@ -162,11 +162,17 @@ require "set"
162
162
  # ==== Language Parsing Capability Tags (*_parsing)
163
163
  #
164
164
  # [:toml_parsing]
165
- # At least one TOML parser (tree-sitter-toml OR toml-rb/Citrus) is available.
165
+ # At least one TOML parser (tree-sitter-toml OR toml-rb/Citrus OR toml/Parslet) is available.
166
166
  #
167
167
  # [:markdown_parsing]
168
168
  # At least one markdown parser (commonmarker OR markly) is available.
169
169
  #
170
+ # [:json_parsing]
171
+ # At least one JSON parser (tree-sitter-json) is available.
172
+ #
173
+ # [:jsonc_parsing]
174
+ # At least one JSONC (JSON with Comments) parser (tree-sitter-jsonc) is available.
175
+ #
170
176
  # [:rbs_parsing]
171
177
  # At least one RBS parser (rbs gem OR tree-sitter-rbs) is available.
172
178
  #
@@ -491,9 +497,12 @@ module TreeHaver
491
497
  def libtree_sitter_available?
492
498
  return @libtree_sitter_available if defined?(@libtree_sitter_available)
493
499
  @libtree_sitter_available = begin
494
- return false unless ffi_available?
495
- TreeHaver::Backends::FFI::Native.try_load!
496
- true
500
+ if !ffi_available?
501
+ false
502
+ else
503
+ TreeHaver::Backends::FFI::Native.try_load!
504
+ true
505
+ end
497
506
  rescue TreeHaver::NotAvailable, LoadError
498
507
  false
499
508
  rescue StandardError
@@ -531,25 +540,26 @@ module TreeHaver
531
540
  nil
532
541
  end
533
542
 
534
- # Check if commonmarker gem is available
543
+ # ============================================================
544
+ # Dynamic Backend Availability (via BackendRegistry)
545
+ # ============================================================
535
546
  #
536
- # Uses BackendRegistry which allows commonmarker-merge to register its checker.
547
+ # External gems register tags with BackendRegistry.register_tag which
548
+ # dynamically defines *_available? methods on this module.
537
549
  #
538
- # @return [Boolean] true if commonmarker gem is available
539
- def commonmarker_available?
540
- return @commonmarker_available if defined?(@commonmarker_available)
541
- @commonmarker_available = TreeHaver::BackendRegistry.available?(:commonmarker)
542
- end
543
-
544
- # Check if markly gem is available
550
+ # @example External gem registers a tag
551
+ # TreeHaver::BackendRegistry.register_tag(
552
+ # :my_backend_backend,
553
+ # category: :backend,
554
+ # require_path: "my_backend/merge"
555
+ # ) { MyBackend::Merge::Backend.available? }
545
556
  #
546
- # Uses BackendRegistry which allows markly-merge to register its checker.
557
+ # # The registration automatically defines:
558
+ # TreeHaver::RSpec::DependencyTags.my_backend_available? # => true/false
547
559
  #
548
- # @return [Boolean] true if markly gem is available
549
- def markly_available?
550
- return @markly_available if defined?(@markly_available)
551
- @markly_available = TreeHaver::BackendRegistry.available?(:markly)
552
- end
560
+ # Built-in backends (prism, psych, citrus, parslet) have explicit methods
561
+ # defined below. External backends get methods defined dynamically when
562
+ # their gem calls register_tag.
553
563
 
554
564
  # Check if prism gem is available
555
565
  #
@@ -738,9 +748,33 @@ module TreeHaver
738
748
 
739
749
  # Check if at least one markdown backend is available
740
750
  #
751
+ # Uses BackendRegistry.tag_available? to check external backends that may
752
+ # not have their methods defined yet (registered by external gems).
753
+ #
741
754
  # @return [Boolean] true if any markdown backend works
742
755
  def any_markdown_backend_available?
743
- markly_available? || commonmarker_available?
756
+ TreeHaver::BackendRegistry.tag_available?(:markly_backend) ||
757
+ TreeHaver::BackendRegistry.tag_available?(:commonmarker_backend)
758
+ end
759
+
760
+ # Check if at least one JSON parsing backend is available
761
+ #
762
+ # Currently only tree-sitter-json is supported for JSON parsing.
763
+ # Future backends (e.g., pure-Ruby JSON parsers) can be added here.
764
+ #
765
+ # @return [Boolean] true if any JSON parsing backend works
766
+ def any_json_backend_available?
767
+ tree_sitter_json_available?
768
+ end
769
+
770
+ # Check if at least one JSONC parsing backend is available
771
+ #
772
+ # Currently only tree-sitter-jsonc is supported for JSONC parsing.
773
+ # Future backends (e.g., pure-Ruby JSONC parsers) can be added here.
774
+ #
775
+ # @return [Boolean] true if any JSONC parsing backend works
776
+ def any_jsonc_backend_available?
777
+ tree_sitter_jsonc_available?
744
778
  end
745
779
 
746
780
  def any_native_grammar_available?
@@ -812,46 +846,71 @@ module TreeHaver
812
846
  # Use stored blocked_backends if available, otherwise compute dynamically
813
847
  blocked = @blocked_backends || compute_blocked_backends
814
848
 
815
- {
849
+ result = {
816
850
  # Backend selection from environment variables
817
851
  selected_backend: selected_backend,
818
852
  allowed_native_backends: allowed_native_backends,
819
853
  allowed_ruby_backends: allowed_ruby_backends,
820
- # TreeHaver backends (*_backend) - skip blocked backends to avoid loading them
821
- ffi_backend: blocked.include?(:ffi) ? :blocked : ffi_available?,
822
- mri_backend: blocked.include?(:mri) ? :blocked : mri_backend_available?,
823
- rust_backend: blocked.include?(:rust) ? :blocked : rust_backend_available?,
824
- java_backend: blocked.include?(:java) ? :blocked : java_backend_available?,
825
- prism_backend: blocked.include?(:prism) ? :blocked : prism_available?,
826
- psych_backend: blocked.include?(:psych) ? :blocked : psych_available?,
827
- commonmarker_backend: blocked.include?(:commonmarker) ? :blocked : commonmarker_available?,
828
- markly_backend: blocked.include?(:markly) ? :blocked : markly_available?,
829
- citrus_backend: blocked.include?(:citrus) ? :blocked : citrus_available?,
830
- parslet_backend: blocked.include?(:parslet) ? :blocked : parslet_available?,
831
- rbs_backend: blocked.include?(:rbs) ? :blocked : rbs_backend_available?,
832
- # Ruby engines (*_engine)
833
- ruby_engine: RUBY_ENGINE,
834
- mri_engine: mri?,
835
- jruby_engine: jruby?,
836
- truffleruby_engine: truffleruby?,
837
- # Tree-sitter grammars (*_grammar) - also respect blocked backends
838
- # since grammar checks may load backends
839
- libtree_sitter: libtree_sitter_available?,
840
- bash_grammar: blocked.include?(:mri) ? :blocked : tree_sitter_bash_available?,
841
- toml_grammar: blocked.include?(:mri) ? :blocked : tree_sitter_toml_available?,
842
- json_grammar: blocked.include?(:mri) ? :blocked : tree_sitter_json_available?,
843
- jsonc_grammar: blocked.include?(:mri) ? :blocked : tree_sitter_jsonc_available?,
844
- rbs_grammar: blocked.include?(:mri) ? :blocked : tree_sitter_rbs_available?,
845
- any_native_grammar: blocked.include?(:mri) ? :blocked : any_native_grammar_available?,
846
- # Language parsing capabilities (*_parsing)
847
- toml_parsing: any_toml_backend_available?,
848
- markdown_parsing: any_markdown_backend_available?,
849
- rbs_parsing: any_rbs_backend_available?,
850
- # Specific libraries (*_gem)
851
- toml_rb_gem: toml_rb_gem_available?,
852
- toml_gem: toml_gem_available?,
853
- rbs_gem: rbs_gem_available?,
854
854
  }
855
+
856
+ # Built-in TreeHaver backends (*_backend) - skip blocked backends to avoid loading them
857
+ builtin_backends = {
858
+ ffi: :ffi_available?,
859
+ mri: :mri_backend_available?,
860
+ rust: :rust_backend_available?,
861
+ java: :java_backend_available?,
862
+ prism: :prism_available?,
863
+ psych: :psych_available?,
864
+ citrus: :citrus_available?,
865
+ parslet: :parslet_available?,
866
+ rbs: :rbs_backend_available?,
867
+ }
868
+
869
+ builtin_backends.each do |backend, method|
870
+ tag = :"#{backend}_backend"
871
+ result[tag] = blocked.include?(backend) ? :blocked : public_send(method)
872
+ end
873
+
874
+ # Dynamically registered backends from BackendRegistry
875
+ TreeHaver::BackendRegistry.registered_tags.each do |tag_name|
876
+ next if result.key?(tag_name) # Don't override built-ins
877
+
878
+ meta = TreeHaver::BackendRegistry.tag_metadata(tag_name)
879
+ next unless meta && meta[:category] == :backend
880
+
881
+ backend = meta[:backend_name]
882
+ result[tag_name] = blocked.include?(backend) ? :blocked : TreeHaver::BackendRegistry.tag_available?(tag_name)
883
+ end
884
+
885
+ # Ruby engines (*_engine)
886
+ result[:ruby_engine] = RUBY_ENGINE
887
+ result[:mri_engine] = mri?
888
+ result[:jruby_engine] = jruby?
889
+ result[:truffleruby_engine] = truffleruby?
890
+
891
+ # Tree-sitter grammars (*_grammar) - also respect blocked backends
892
+ # since grammar checks may load backends
893
+ result[:libtree_sitter] = libtree_sitter_available?
894
+ result[:bash_grammar] = blocked.include?(:mri) ? :blocked : tree_sitter_bash_available?
895
+ result[:toml_grammar] = blocked.include?(:mri) ? :blocked : tree_sitter_toml_available?
896
+ result[:json_grammar] = blocked.include?(:mri) ? :blocked : tree_sitter_json_available?
897
+ result[:jsonc_grammar] = blocked.include?(:mri) ? :blocked : tree_sitter_jsonc_available?
898
+ result[:rbs_grammar] = blocked.include?(:mri) ? :blocked : tree_sitter_rbs_available?
899
+ result[:any_native_grammar] = blocked.include?(:mri) ? :blocked : any_native_grammar_available?
900
+
901
+ # Language parsing capabilities (*_parsing)
902
+ result[:toml_parsing] = any_toml_backend_available?
903
+ result[:markdown_parsing] = any_markdown_backend_available?
904
+ result[:json_parsing] = any_json_backend_available?
905
+ result[:jsonc_parsing] = any_jsonc_backend_available?
906
+ result[:rbs_parsing] = any_rbs_backend_available?
907
+
908
+ # Specific libraries (*_gem)
909
+ result[:toml_rb_gem] = toml_rb_gem_available?
910
+ result[:toml_gem] = toml_gem_available?
911
+ result[:rbs_gem] = rbs_gem_available?
912
+
913
+ result
855
914
  end
856
915
 
857
916
  # Get environment variable summary for debugging
@@ -907,7 +966,7 @@ module TreeHaver
907
966
  # @param test_source [String] sample source code to parse
908
967
  # @return [Boolean] true if parsing works without errors
909
968
  def grammar_works?(language, test_source)
910
- debug = ENV["TREE_HAVER_DEBUG"]
969
+ debug = !ENV.fetch("TREE_HAVER_DEBUG", "false").casecmp?("false")
911
970
  env_var = "TREE_SITTER_#{language.to_s.upcase}_PATH"
912
971
  env_value = ENV[env_var]
913
972
 
@@ -972,7 +1031,7 @@ RSpec.configure do |config|
972
1031
 
973
1032
  config.before(:suite) do
974
1033
  # Print dependency summary if TREE_HAVER_DEBUG is set
975
- if ENV["TREE_HAVER_DEBUG"]
1034
+ unless ENV.fetch("TREE_HAVER_DEBUG", "false").casecmp?("false")
976
1035
  puts "\n=== TreeHaver Environment Variables ==="
977
1036
  deps.env_summary.each do |var, value|
978
1037
  puts " #{var}: #{value.inspect}"
@@ -1063,35 +1122,35 @@ RSpec.configure do |config|
1063
1122
  #
1064
1123
  # This is dynamic based on TreeHaver::Backends::BLOCKED_BY configuration.
1065
1124
 
1066
- # Map of backend symbols to their availability check methods
1067
- backend_availability_methods = {
1068
- mri: :mri_backend_available?,
1069
- rust: :rust_backend_available?,
1070
- ffi: :ffi_available?,
1071
- java: :java_backend_available?,
1072
- prism: :prism_available?,
1073
- psych: :psych_available?,
1074
- commonmarker: :commonmarker_available?,
1075
- markly: :markly_available?,
1076
- citrus: :citrus_available?,
1077
- parslet: :parslet_available?,
1078
- rbs: :rbs_backend_available?,
1079
- }
1080
-
1081
- # Map of backend symbols to their RSpec tag names
1082
- backend_tags = {
1083
- mri: :mri_backend,
1084
- rust: :rust_backend,
1085
- ffi: :ffi_backend,
1086
- java: :java_backend,
1087
- prism: :prism_backend,
1088
- psych: :psych_backend,
1089
- commonmarker: :commonmarker_backend,
1090
- markly: :markly_backend,
1091
- citrus: :citrus_backend,
1092
- parslet: :parslet_backend,
1093
- rbs: :rbs_backend,
1094
- }
1125
+ # Build backend maps dynamically from BackendRegistry and built-in backends
1126
+ # This allows external gems to register and automatically get tag support
1127
+ backend_availability_methods = {}
1128
+ backend_tags = {}
1129
+
1130
+ # Built-in backends (always present in tree_haver)
1131
+ builtin_backends = %i[mri rust ffi java prism psych citrus parslet rbs]
1132
+ builtin_backends.each do |backend|
1133
+ # Special case for ffi which uses ffi_available? not ffi_backend_available?
1134
+ availability_method = (backend == :ffi) ? :ffi_available? : :"#{backend}_available?"
1135
+ # Special case for backends that use *_backend_available? naming
1136
+ availability_method = :"#{backend}_backend_available?" if %i[mri rust java rbs].include?(backend)
1137
+
1138
+ backend_availability_methods[backend] = availability_method
1139
+ backend_tags[backend] = :"#{backend}_backend"
1140
+ end
1141
+
1142
+ # Add dynamically registered backends from BackendRegistry
1143
+ # This picks up external gems like commonmarker-merge, markly-merge, etc.
1144
+ TreeHaver::BackendRegistry.registered_tags.each do |tag_name|
1145
+ meta = TreeHaver::BackendRegistry.tag_metadata(tag_name)
1146
+ next unless meta && meta[:category] == :backend
1147
+
1148
+ backend_name = meta[:backend_name]
1149
+ next if backend_availability_methods.key?(backend_name) # Don't override built-ins
1150
+
1151
+ backend_availability_methods[backend_name] = :"#{backend_name}_available?"
1152
+ backend_tags[backend_name] = tag_name
1153
+ end
1095
1154
 
1096
1155
  # Determine which backends should NOT have availability checked
1097
1156
  # based on which *_backend_only tag is being run OR which backend is
@@ -1219,7 +1278,7 @@ RSpec.configure do |config|
1219
1278
  # Language Parsing Capability Tags
1220
1279
  # ============================================================
1221
1280
  # Tags: *_parsing - require ANY parser for a language (any backend that can parse it)
1222
- # :toml_parsing - any TOML parser (tree-sitter-toml OR toml-rb/Citrus)
1281
+ # :toml_parsing - any TOML parser (tree-sitter-toml OR toml-rb/Citrus OR toml/Parslet)
1223
1282
  # :markdown_parsing - any Markdown parser (commonmarker OR markly)
1224
1283
  # :rbs_parsing - any RBS parser (rbs gem OR tree-sitter-rbs)
1225
1284
  # :native_parsing - any native tree-sitter backend + grammar
@@ -1283,6 +1342,8 @@ RSpec.configure do |config|
1283
1342
  # Language parsing capabilities
1284
1343
  config.filter_run_excluding(not_toml_parsing: true) if deps.any_toml_backend_available?
1285
1344
  config.filter_run_excluding(not_markdown_parsing: true) if deps.any_markdown_backend_available?
1345
+ config.filter_run_excluding(not_json_parsing: true) if deps.any_json_backend_available?
1346
+ config.filter_run_excluding(not_jsonc_parsing: true) if deps.any_jsonc_backend_available?
1286
1347
  config.filter_run_excluding(not_rbs_parsing: true) if deps.any_rbs_backend_available?
1287
1348
  end
1288
1349
 
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ensure TreeHaver::Node and TreeHaver::Point are loaded
4
+ require "tree_haver"
5
+
6
+ module TreeHaver
7
+ module RSpec
8
+ # A mock inner node that provides the minimal interface TreeHaver::Node expects.
9
+ #
10
+ # This is what TreeHaver::Node wraps - it simulates the backend-specific node
11
+ # (like tree-sitter's Node, Markly::Node, etc.)
12
+ #
13
+ # @api private
14
+ class MockInnerNode
15
+ attr_reader :type, :start_byte, :end_byte, :children_data
16
+
17
+ def initialize(
18
+ type:,
19
+ text: nil,
20
+ start_byte: 0,
21
+ end_byte: nil,
22
+ start_row: 0,
23
+ start_column: 0,
24
+ end_row: nil,
25
+ end_column: nil,
26
+ children: []
27
+ )
28
+ @type = type.to_s
29
+ @text_content = text
30
+ @start_byte = start_byte
31
+ @end_byte = end_byte || (text ? start_byte + text.length : start_byte)
32
+ @start_row = start_row
33
+ @start_column = start_column
34
+ @end_row = end_row || start_row
35
+ @end_column = end_column || (text ? start_column + text.length : start_column)
36
+ @children_data = children
37
+ end
38
+
39
+ def start_point
40
+ TreeHaver::Point.new(@start_row, @start_column)
41
+ end
42
+
43
+ def end_point
44
+ TreeHaver::Point.new(@end_row, @end_column)
45
+ end
46
+
47
+ def child_count
48
+ @children_data.length
49
+ end
50
+
51
+ def child(index)
52
+ return if index.nil? || index < 0 || index >= @children_data.length
53
+
54
+ @children_data[index]
55
+ end
56
+
57
+ # Return children array (for enumerable behavior)
58
+ def children
59
+ @children_data
60
+ end
61
+
62
+ def first_child
63
+ @children_data.first
64
+ end
65
+
66
+ def last_child
67
+ @children_data.last
68
+ end
69
+
70
+ # Iterate over children
71
+ def each(&block)
72
+ return enum_for(:each) unless block
73
+
74
+ @children_data.each(&block)
75
+ end
76
+
77
+ def named?
78
+ true
79
+ end
80
+
81
+ # Test nodes are always valid (no parse errors)
82
+ def has_error?
83
+ false
84
+ end
85
+
86
+ # Test nodes are never missing (not error recovery insertions)
87
+ def missing?
88
+ false
89
+ end
90
+
91
+ # Some backends provide text directly
92
+ def text
93
+ @text_content
94
+ end
95
+
96
+ # For backends that use string_content (like Markly/Commonmarker)
97
+ def string_content
98
+ @text_content
99
+ end
100
+ end
101
+
102
+ # A real TreeHaver::Node that wraps a MockInnerNode.
103
+ #
104
+ # This gives us full TreeHaver::Node behavior (#text, #type, #source_position, etc.)
105
+ # while allowing us to control the underlying data for testing.
106
+ #
107
+ # TestableNode is designed for testing code that works with TreeHaver nodes
108
+ # without requiring an actual parser backend. It creates real TreeHaver::Node
109
+ # instances with controlled, predictable data.
110
+ #
111
+ # @example Creating a testable node
112
+ # node = TreeHaver::RSpec::TestableNode.create(
113
+ # type: :heading,
114
+ # text: "## My Heading",
115
+ # start_line: 1
116
+ # )
117
+ # node.text # => "## My Heading"
118
+ # node.type # => "heading"
119
+ # node.start_line # => 1
120
+ #
121
+ # @example Creating with children
122
+ # parent = TreeHaver::RSpec::TestableNode.create(
123
+ # type: :document,
124
+ # text: "# Title\n\nParagraph",
125
+ # children: [
126
+ # { type: :heading, text: "# Title", start_line: 1 },
127
+ # { type: :paragraph, text: "Paragraph", start_line: 3 },
128
+ # ]
129
+ # )
130
+ #
131
+ # @example Using the convenience constant
132
+ # # After requiring tree_haver/rspec/testable_node, you can use:
133
+ # node = TestableNode.create(type: :paragraph, text: "Hello")
134
+ #
135
+ class TestableNode < TreeHaver::Node
136
+ class << self
137
+ # Create a TestableNode with the given attributes.
138
+ #
139
+ # @param type [Symbol, String] Node type (e.g., :heading, :paragraph)
140
+ # @param text [String] The text content of the node
141
+ # @param start_line [Integer] 1-based start line number (default: 1)
142
+ # @param end_line [Integer, nil] 1-based end line number (default: calculated from text)
143
+ # @param start_column [Integer] 0-based start column (default: 0)
144
+ # @param end_column [Integer, nil] 0-based end column (default: calculated from text)
145
+ # @param start_byte [Integer] Start byte offset (default: 0)
146
+ # @param end_byte [Integer, nil] End byte offset (default: calculated from text)
147
+ # @param children [Array<Hash>] Child node specifications
148
+ # @param source [String, nil] Full source text (default: uses text param)
149
+ # @return [TestableNode]
150
+ def create(
151
+ type:,
152
+ text: "",
153
+ start_line: 1,
154
+ end_line: nil,
155
+ start_column: 0,
156
+ end_column: nil,
157
+ start_byte: 0,
158
+ end_byte: nil,
159
+ children: [],
160
+ source: nil
161
+ )
162
+ # Convert 1-based line to 0-based row
163
+ start_row = start_line - 1
164
+ end_row = end_line ? end_line - 1 : start_row + text.count("\n")
165
+
166
+ # Calculate end_column if not provided
167
+ if end_column.nil?
168
+ lines = text.split("\n", -1)
169
+ end_column = lines.last&.length || 0
170
+ end
171
+
172
+ # Build children as MockInnerNodes
173
+ child_nodes = children.map do |child_spec|
174
+ MockInnerNode.new(**child_spec)
175
+ end
176
+
177
+ inner = MockInnerNode.new(
178
+ type: type,
179
+ text: text,
180
+ start_byte: start_byte,
181
+ end_byte: end_byte,
182
+ start_row: start_row,
183
+ start_column: start_column,
184
+ end_row: end_row,
185
+ end_column: end_column,
186
+ children: child_nodes,
187
+ )
188
+
189
+ # Create a real TreeHaver::Node wrapping our mock
190
+ # Pass source so TreeHaver::Node can extract text if needed
191
+ new(inner, source: source || text)
192
+ end
193
+
194
+ # Create multiple nodes from an array of specifications.
195
+ #
196
+ # @param specs [Array<Hash>] Array of node specifications
197
+ # @return [Array<TestableNode>]
198
+ def create_list(*specs)
199
+ specs.flatten.map { |spec| create(**spec) }
200
+ end
201
+ end
202
+
203
+ # Additional test helper methods
204
+
205
+ # Check if this is a testable node (for test assertions)
206
+ #
207
+ # @return [Boolean] true
208
+ def testable?
209
+ true
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ # Make TestableNode available at top level for convenience in specs.
216
+ # This allows specs to use `TestableNode.create(...)` without the full namespace.
217
+ TestableNode = TreeHaver::RSpec::TestableNode
@@ -9,7 +9,7 @@
9
9
  #
10
10
  # This will load:
11
11
  # - Dependency tags for conditional test execution
12
- # - (Future) Additional test helpers as needed
12
+ # - TestableNode for creating mock nodes in tests
13
13
  #
14
14
  # @example spec_helper.rb
15
15
  # require "tree_haver/rspec"
@@ -18,6 +18,16 @@
18
18
  # # Your additional configuration...
19
19
  # end
20
20
  #
21
+ # @example Using TestableNode
22
+ # node = TestableNode.create(
23
+ # type: :heading,
24
+ # text: "## My Heading",
25
+ # start_line: 1
26
+ # )
27
+ # expect(node.type).to eq("heading")
28
+ #
21
29
  # @see TreeHaver::RSpec::DependencyTags
30
+ # @see TreeHaver::RSpec::TestableNode
22
31
 
23
32
  require_relative "rspec/dependency_tags"
33
+ require_relative "rspec/testable_node"
@@ -10,7 +10,7 @@ module TreeHaver
10
10
  # Current version of the tree_haver gem
11
11
  #
12
12
  # @return [String] the version string
13
- VERSION = "5.0.0"
13
+ VERSION = "5.0.2"
14
14
  end
15
15
 
16
16
  # Traditional location for VERSION constant
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: 5.0.0
4
+ version: 5.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -288,6 +288,7 @@ files:
288
288
  - lib/tree_haver/point.rb
289
289
  - lib/tree_haver/rspec.rb
290
290
  - lib/tree_haver/rspec/dependency_tags.rb
291
+ - lib/tree_haver/rspec/testable_node.rb
291
292
  - lib/tree_haver/tree.rb
292
293
  - lib/tree_haver/version.rb
293
294
  - sig/tree_haver.rbs
@@ -299,10 +300,10 @@ licenses:
299
300
  - MIT
300
301
  metadata:
301
302
  homepage_uri: https://tree-haver.galtzo.com/
302
- source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v5.0.0
303
- changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v5.0.0/CHANGELOG.md
303
+ source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v5.0.2
304
+ changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v5.0.2/CHANGELOG.md
304
305
  bug_tracker_uri: https://github.com/kettle-rb/tree_haver/issues
305
- documentation_uri: https://www.rubydoc.info/gems/tree_haver/5.0.0
306
+ documentation_uri: https://www.rubydoc.info/gems/tree_haver/5.0.2
306
307
  funding_uri: https://github.com/sponsors/pboling
307
308
  wiki_uri: https://github.com/kettle-rb/tree_haver/wiki
308
309
  news_uri: https://www.railsbling.com/tags/tree_haver
metadata.gz.sig CHANGED
Binary file