tree_haver 3.2.4 → 3.2.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cea4c9eec7fee0afdffcb4f6b66a7dce698af731cc23028a77f70bc71dc207e
4
- data.tar.gz: 68ac3a9c026204a9f0cd42f0afc01f00478405f0be07b74c32c1a85488c7275e
3
+ metadata.gz: 6e544c31dc86e71be78cfcf24e7cbf8a779ef954845b736ec37ed6b550ffe714
4
+ data.tar.gz: 54f83ef36c8167f5071db278ce33f2603864d339a9c246a733957da41540eab4
5
5
  SHA512:
6
- metadata.gz: 4f48fad6061b7d14cc8cd0b0a7c98e0457f1e65613ef8f4ea469f5cdb36e6137512b42a329f846752e9016a43a2fe6cd24e73cbcce2ecb83b17f4cc9eb3653b6
7
- data.tar.gz: 68949852113d833c6d40d8bde278d08c9b4b68b6d90299af99036683b070a3eeac97a92723de435be2c9e7025f718627d9b100a5fbcbcad554e5e3c6e3b141e3
6
+ metadata.gz: c991da086ba12a279f461f337e7dfa9d0b98d8d6d4f4c5d3d78cc3b848a6174ed42ce71b674e8a2d4ed81c5b17289d6c3903c2ef813db86cd4557a33aa1c1599
7
+ data.tar.gz: 034b9f7df24e5f757013f011b7661559fed243b3fde752d95ab2cac94a0fdfc8270d9ca002d07972c74c1d5455293ac12c7472eacdc106934051cc3231d005b9
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,36 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [3.2.6] - 2026-01-06
34
+
35
+ - TAG: [v3.2.6][3.2.6t]
36
+ - COVERAGE: 92.07% -- 2230/2422 lines in 23 files
37
+ - BRANCH COVERAGE: 74.69% -- 788/1055 branches in 23 files
38
+ - 90.37% documented
39
+
40
+ ### Fixed
41
+
42
+ - **Java backend**: Fixed Optional handling in Node methods that could return nil incorrectly
43
+ - `child(index)`, `child_by_field_name(name)`, `parent`, `next_sibling`, `prev_sibling` now properly check for nil before attempting to unwrap Java Optional
44
+ - Previously, the ternary-based Optional check could fail when jtreesitter returned null directly instead of Optional.empty()
45
+ - This fixes JRuby test failures where `key_name` returned nil and object keys were not extracted
46
+
47
+ ## [3.2.5] - 2026-01-05
48
+
49
+ - TAG: [v3.2.5][3.2.5t]
50
+ - COVERAGE: 92.07% -- 2230/2422 lines in 23 files
51
+ - BRANCH COVERAGE: 74.69% -- 788/1055 branches in 23 files
52
+ - 90.37% documented
53
+
54
+ ### Fixed
55
+
56
+ - **Markly backend**: `Node#text` now correctly handles container nodes (headings, paragraphs, etc.)
57
+ - Previously returned empty string because `string_content` was checked first (responds but returns empty for containers)
58
+ - Now falls through to `to_plaintext` or children concatenation when `string_content` is empty
59
+ - **Commonmarker backend**: `Node#text` now correctly handles container nodes
60
+ - Previously could return empty string in edge cases
61
+ - Now consistently falls through to children concatenation when `string_content` is empty or raises TypeError
62
+
33
63
  ## [3.2.4] - 2026-01-04
34
64
 
35
65
  - TAG: [v3.2.4][3.2.4t]
@@ -885,7 +915,11 @@ Despite the major version bump to 3.0.0 (following semver due to the breaking `L
885
915
 
886
916
  - Initial release
887
917
 
888
- [Unreleased]: https://github.com/kettle-rb/tree_haver/compare/v3.2.4...HEAD
918
+ [Unreleased]: https://github.com/kettle-rb/tree_haver/compare/v3.2.6...HEAD
919
+ [3.2.6]: https://github.com/kettle-rb/tree_haver/compare/v3.2.5...v3.2.6
920
+ [3.2.6t]: https://github.com/kettle-rb/tree_haver/releases/tag/v3.2.6
921
+ [3.2.5]: https://github.com/kettle-rb/tree_haver/compare/v3.2.4...v3.2.5
922
+ [3.2.5t]: https://github.com/kettle-rb/tree_haver/releases/tag/v3.2.5
889
923
  [3.2.4]: https://github.com/kettle-rb/tree_haver/compare/v3.2.3...v3.2.4
890
924
  [3.2.4t]: https://github.com/kettle-rb/tree_haver/releases/tag/v3.2.4
891
925
  [3.2.3]: https://github.com/kettle-rb/tree_haver/compare/v3.2.2...v3.2.3
data/README.md CHANGED
@@ -141,8 +141,8 @@ The Rust backend uses [tree\_stump](https://github.com/joker1007/tree_stump), wh
141
141
 
142
142
  - **JRuby**: Cannot load native `.so` extensions (runs on JVM)
143
143
  - **TruffleRuby**: magnus/rb-sys are incompatible with TruffleRuby's C API emulation
144
- NOTE: `tree_stump` currently requires unreleased fixes in the `main` branch.
145
-
144
+ NOTE: `tree_stump` currently requires unreleased fixes in the `main` branch.
145
+ <!-- end list -->
146
146
  ``` ruby
147
147
  # Add to your Gemfile for Rust backend (MRI only)
148
148
  gem "tree_stump", github: "joker1007/tree_stump", branch: "main"
@@ -155,7 +155,6 @@ gem "tree_stump", github: "joker1007/tree_stump", branch: "main"
155
155
  Requires the `ffi` gem and a system installation of `libtree-sitter`.
156
156
 
157
157
  - **TruffleRuby**: TruffleRuby's FFI implementation doesn't support `STRUCT_BY_VALUE` return types, which tree-sitter's C API uses for functions like `ts_tree_root_node` and `ts_node_child`.
158
-
159
158
  <!-- end list -->
160
159
  ``` ruby
161
160
  # Add to your Gemfile for FFI backend (MRI and JRuby)
@@ -185,9 +184,9 @@ gem "citrus", "~> 3.0"
185
184
 
186
185
  #### Java Backend (JRuby only)
187
186
 
188
- **Requires jtreesitter >= 0.26.0** from Maven Central. Older versions are not supported due to breaking API changes.
187
+ **Requires jtreesitter \>= 0.26.0** from Maven Central. Older versions are not supported due to breaking API changes.
189
188
 
190
- ```ruby
189
+ ``` ruby
191
190
  # No gem dependency - uses JRuby's built-in Java integration
192
191
  # Download the JAR:
193
192
  # curl -L -o jtreesitter-0.26.0.jar \
@@ -198,9 +197,8 @@ gem "citrus", "~> 3.0"
198
197
  ```
199
198
 
200
199
  **Also requires**:
201
- - Tree-sitter runtime library (`libtree-sitter.so`) version 0.26+ (must match jtreesitter version)
202
- - Grammar `.so` files built against tree-sitter 0.26+ (or rebuilt with `tree-sitter generate`)
203
-
200
+ - Tree-sitter runtime library (`libtree-sitter.so`) version 0.26+ (must match jtreesitter version)
201
+ - Grammar `.so` files built against tree-sitter 0.26+ (or rebuilt with `tree-sitter generate`)
204
202
  ### Backend Platform Compatibility
205
203
 
206
204
  Not all backends work on all Ruby platforms. Here's a complete compatibility matrix:
@@ -210,7 +208,7 @@ Not all backends work on all Ruby platforms. Here's a complete compatibility mat
210
208
  | **MRI** ([ruby\_tree\_sitter](https://github.com/Faveod/ruby-tree-sitter)) | ✅ | ❌ | ❌ | ✅ | C extension, MRI only |
211
209
  | **Rust** ([tree\_stump](https://github.com/joker1007/tree_stump)) | ✅ | ❌ | ❌ | ✅ | magnus/rb-sys incompatible with non-MRI |
212
210
  | **FFI** | ✅ | ✅ | ❌ | ⚠️ | TruffleRuby FFI doesn't support `STRUCT_BY_VALUE` |
213
- | **Java** ([jtreesitter](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter)) | ❌ | ✅ | ❌ | ✅ | JRuby only, requires jtreesitter >= 0.26.0 |
211
+ | **Java** ([jtreesitter](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter)) | ❌ | ✅ | ❌ | ✅ | JRuby only, requires jtreesitter \>= 0.26.0 |
214
212
  | **Prism** | ✅ | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
215
213
  | **Psych** | ✅ | ✅ | ✅ | ✅ | YAML parsing, stdlib |
216
214
  | **Citrus** | ✅ | ✅ | ✅ | ⚠️ | Pure Ruby, no native dependencies |
@@ -227,7 +225,7 @@ Not all backends work on all Ruby platforms. Here's a complete compatibility mat
227
225
 
228
226
  All tree-sitter backends (MRI, Rust, FFI, Java) require the tree-sitter runtime library. **Version 0.26+ is required** for the Java backend (to match jtreesitter 0.26.0). Other backends may work with 0.24+, but 0.26+ is recommended for consistency.
229
227
 
230
- ```bash
228
+ ``` bash
231
229
  # Check your tree-sitter version
232
230
  tree-sitter --version # Should be 0.26.0 or newer for Java backend
233
231
 
@@ -243,16 +241,15 @@ dnf install tree-sitter tree-sitter-devel
243
241
 
244
242
  #### jtreesitter (Java Backend)
245
243
 
246
- **The Java backend requires jtreesitter >= 0.26.0.** This version introduced breaking API changes:
247
-
248
- - `Parser.parse()` returns `Optional<Tree>` instead of `Tree`
249
- - `Tree.getRootNode()` returns `Node` directly (not `Optional<Node>`)
250
- - `Node.getChild()`, `getParent()`, `getNextSibling()`, `getPrevSibling()` return `Optional<Node>`
251
- - `Language.load(name)` was removed; use `SymbolLookup` API instead
244
+ **The Java backend requires jtreesitter \>= 0.26.0.** This version introduced breaking API changes:
252
245
 
253
- Older versions of jtreesitter are **NOT supported**.
254
-
255
- ```bash
246
+ - `Parser.parse()` returns `Optional<Tree>` instead of `Tree`
247
+ - `Tree.getRootNode()` returns `Node` directly (not `Optional<Node>`)
248
+ - `Node.getChild()`, `getParent()`, `getNextSibling()`, `getPrevSibling()` return `Optional<Node>`
249
+ - `Language.load(name)` was removed; use `SymbolLookup` API instead
250
+ Older versions of jtreesitter are **NOT supported**.
251
+ <!-- end list -->
252
+ ``` bash
256
253
  # Download jtreesitter 0.26.0 from Maven Central
257
254
  curl -L -o jtreesitter-0.26.0.jar \
258
255
  "https://repo1.maven.org/maven2/io/github/tree-sitter/jtreesitter/0.26.0/jtreesitter-0.26.0.jar"
@@ -263,7 +260,7 @@ bin/setup-jtreesitter
263
260
 
264
261
  Set the environment variable to point to your JAR directory:
265
262
 
266
- ```bash
263
+ ``` bash
267
264
  export TREE_SITTER_JAVA_JARS_DIR=/path/to/jars
268
265
  ```
269
266
 
@@ -273,14 +270,11 @@ export TREE_SITTER_JAVA_JARS_DIR=/path/to/jars
273
270
 
274
271
  Tree-sitter 0.24+ changed how language ABI versions are reported (from `ts_language_version()` to `ts_language_abi_version()`). For the Java backend with jtreesitter 0.26.0, grammars must be built against tree-sitter 0.26+. If you get errors like:
275
272
 
276
- ```
277
- Failed to load tree_sitter_toml
278
- Version mismatch detected: The grammar was built against tree-sitter < 0.26
279
- ```
280
-
273
+ Failed to load tree_sitter_toml
274
+ Version mismatch detected: The grammar was built against tree-sitter < 0.26
281
275
  You need to rebuild the grammar from source:
282
276
 
283
- ```bash
277
+ ``` bash
284
278
  # Use the provided build script
285
279
  bin/build-grammar toml
286
280
 
@@ -306,21 +300,18 @@ TruffleRuby has **no working tree-sitter backend**:
306
300
 
307
301
  - **FFI**: TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` return types (used by `ts_tree_root_node`, `ts_node_child`, etc.)
308
302
  - **MRI/Rust**: C and Rust extensions require MRI's C API internals (`RBasic.flags`, `rb_gc_writebarrier`, etc.) that TruffleRuby doesn't expose
309
- TruffleRuby users should use: **Prism** (Ruby), **Psych** (YAML), **Citrus** (TOML via toml-rb), or potentially **Commonmarker/Markly** (Markdown).
310
-
303
+ TruffleRuby users should use: **Prism** (Ruby), **Psych** (YAML), **Citrus** (TOML via toml-rb), or potentially **Commonmarker/Markly** (Markdown).
311
304
  #### JRuby Limitations
312
305
 
313
306
  JRuby runs on the JVM and **cannot load native `.so` extensions via Ruby's C API**:
314
307
 
315
308
  - **MRI/Rust**: C and Rust extensions simply cannot be loaded
316
309
  - **FFI**: Works\! JRuby has excellent FFI support
317
- - **Java**: Works\! The Java backend uses jtreesitter (requires >= 0.26.0)
318
- JRuby users should use: **Java backend** (best performance, full API) or **FFI backend** for tree-sitter, plus **Prism**, **Psych**, **Citrus** for other formats.
319
-
320
- [ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
321
- [tree_stump]: https://github.com/joker1007/tree_stump
322
- [jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
323
-
310
+ - **Java**: Works\! The Java backend uses jtreesitter (requires \>= 0.26.0)
311
+ JRuby users should use: **Java backend** (best performance, full API) or **FFI backend** for tree-sitter, plus **Prism**, **Psych**, **Citrus** for other formats.
312
+ [ruby\_tree\_sitter](https://github.com/Faveod/ruby-tree-sitter): https://github.com/Faveod/ruby-tree-sitter
313
+ [tree\_stump](https://github.com/joker1007/tree_stump): https://github.com/joker1007/tree\_stump
314
+ \[jtreesitter\]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
324
315
  ### Why TreeHaver?
325
316
 
326
317
  tree-sitter is a powerful parser generator that creates incremental parsers for many programming languages. However, integrating it into Ruby applications can be challenging:
@@ -328,28 +319,27 @@ tree-sitter is a powerful parser generator that creates incremental parsers for
328
319
  - MRI-based C extensions don't work on JRuby
329
320
  - FFI-based solutions may not be optimal for MRI
330
321
  - Managing different backends for different Ruby implementations is cumbersome
331
- TreeHaver solves these problems by providing a unified API that automatically selects the appropriate backend for your Ruby implementation, allowing you to write code once and run it anywhere.
332
-
322
+ TreeHaver solves these problems by providing a unified API that automatically selects the appropriate backend for your Ruby implementation, allowing you to write code once and run it anywhere.
333
323
 
334
324
  ### The `*-merge` Gem Family
335
325
 
336
326
  The `*-merge` gem family provides intelligent, AST-based merging for various file formats. At the foundation is [tree_haver][tree_haver], which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
337
327
 
338
- | Gem | Format | Parser Backend(s) | Description |
339
- |------------------------------------------|----------|-----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
340
- | [tree_haver][tree_haver] | Multi | MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
341
- | [ast-merge][ast-merge] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
342
- | [prism-merge][prism-merge] | Ruby | [Prism][prism] | Smart merge for Ruby source files |
343
- | [psych-merge][psych-merge] | YAML | [Psych][psych] | Smart merge for YAML files |
344
- | [json-merge][json-merge] | JSON | [tree-sitter-json][ts-json] (via tree_haver) | Smart merge for JSON files |
345
- | [jsonc-merge][jsonc-merge] | JSONC | [tree-sitter-jsonc][ts-jsonc] (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
346
- | [bash-merge][bash-merge] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
347
- | [rbs-merge][rbs-merge] | RBS | [RBS][rbs] | Smart merge for Ruby type signatures |
348
- | [dotenv-merge][dotenv-merge] | Dotenv | internal | Smart merge for `.env` files |
349
- | [toml-merge][toml-merge] | TOML | [Citrus + toml-rb][toml-rb] (default, via tree_haver), [tree-sitter-toml][ts-toml] (via tree_haver) | Smart merge for TOML files |
350
- | [markdown-merge][markdown-merge] | Markdown | [Commonmarker][commonmarker] / [Markly][markly] (via tree_haver) | **Foundation**: Shared base for Markdown mergers with inner code block merging |
351
- | [markly-merge][markly-merge] | Markdown | [Markly][markly] (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
352
- | [commonmarker-merge][commonmarker-merge] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
328
+ | Gem | Language<br>/ Format | Parser Backend(s) | Description |
329
+ |------------------------------------------|----------------------|-----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
330
+ | [tree_haver][tree_haver] | Multi | MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
331
+ | [ast-merge][ast-merge] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
332
+ | [bash-merge][bash-merge] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
333
+ | [commonmarker-merge][commonmarker-merge] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
334
+ | [dotenv-merge][dotenv-merge] | Dotenv | internal | Smart merge for `.env` files |
335
+ | [json-merge][json-merge] | JSON | [tree-sitter-json][ts-json] (via tree_haver) | Smart merge for JSON files |
336
+ | [jsonc-merge][jsonc-merge] | JSONC | [tree-sitter-jsonc][ts-jsonc] (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
337
+ | [markdown-merge][markdown-merge] | Markdown | [Commonmarker][commonmarker] / [Markly][markly] (via tree_haver) | **Foundation**: Shared base for Markdown mergers with inner code block merging |
338
+ | [markly-merge][markly-merge] | Markdown | [Markly][markly] (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
339
+ | [prism-merge][prism-merge] | Ruby | [Prism][prism] (`prism` std lib gem) | Smart merge for Ruby source files |
340
+ | [psych-merge][psych-merge] | YAML | [Psych][psych] (`psych` std lib gem) | Smart merge for YAML files |
341
+ | [rbs-merge][rbs-merge] | RBS | [tree-sitter-bash][ts-rbs] (via tree_haver), [RBS][rbs] (`rbs` std lib gem) | Smart merge for Ruby type signatures |
342
+ | [toml-merge][toml-merge] | TOML | [Citrus + toml-rb][toml-rb] (default, via tree_haver), [tree-sitter-toml][ts-toml] (via tree_haver) | Smart merge for TOML files |
353
343
 
354
344
  **Example implementations** for the gem templating use case:
355
345
 
@@ -412,7 +402,7 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
412
402
 
413
403
  **Note:** Java backend works with grammar `.so` files built against tree-sitter 0.24+. The grammars must be rebuilt with `tree-sitter generate` if they were compiled against older tree-sitter versions. FFI is recommended for JRuby as it's easier to set up.
414
404
 
415
- **Note:** TreeHaver can use `ruby_tree_sitter` (MRI) or `tree_stump` (MRI) as backends, or `java-tree-sitter` / `jtreesitter` >= 0.26.0 ([docs](https://tree-sitter.github.io/java-tree-sitter/), [maven](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter), [source](https://github.com/tree-sitter/java-tree-sitter), JRuby), or FFI on any backend, giving you TreeHaver's unified API, grammar discovery, and security features, plus full access to incremental parsing when using those backends.
405
+ **Note:** TreeHaver can use `ruby_tree_sitter` (MRI) or `tree_stump` (MRI) as backends, or `java-tree-sitter` / `jtreesitter` \>= 0.26.0 ([docs](https://tree-sitter.github.io/java-tree-sitter/), [maven](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter), [source](https://github.com/tree-sitter/java-tree-sitter), JRuby), or FFI on any backend, giving you TreeHaver's unified API, grammar discovery, and security features, plus full access to incremental parsing when using those backends.
416
406
 
417
407
  **Note:** `tree_stump` currently requires unreleased fixes in the `main` branch.
418
408
 
@@ -421,28 +411,42 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
421
411
  **Choose TreeHaver when:**
422
412
 
423
413
  - You need JRuby or TruffleRuby support
414
+
424
415
  - You're building a library that should work across Ruby implementations
416
+
425
417
  - You want automatic grammar discovery and security validations
418
+
426
419
  - You want flexibility to switch backends without code changes
420
+
427
421
  - You need incremental parsing with a unified API
428
- **Choose ruby\_tree\_sitter directly when:**
422
+ **Choose ruby\_tree\_sitter directly when:**
429
423
 
430
424
  - You only target MRI Ruby
425
+
431
426
  - You need the full Query API without abstraction
427
+
432
428
  - You want the most battle-tested C bindings
429
+
433
430
  - You don't need TreeHaver's grammar discovery
434
- **Choose tree\_stump directly when:**
431
+ **Choose tree\_stump directly when:**
435
432
 
436
433
  - You only target MRI Ruby
434
+
437
435
  - You prefer Rust-based native extensions
436
+
438
437
  - You want precompiled binaries without system dependencies
438
+
439
439
  - You don't need TreeHaver's grammar discovery
440
+
440
441
  - **Note:** `tree_stump` currently requires unreleased fixes in the `main` branch.
441
- **Choose citrus directly when:**
442
+ **Choose citrus directly when:**
442
443
 
443
444
  - You need zero native dependencies (pure Ruby)
445
+
444
446
  - You're using a Citrus grammar (not tree-sitter grammars)
447
+
445
448
  - Performance is less critical than portability
449
+
446
450
  - You don't need TreeHaver's unified API
447
451
  ## 💡 Info you can shake a stick at
448
452
 
@@ -495,12 +499,16 @@ The maintainers of this and thousands of other packages are working with Tidelif
495
499
  [![Get help from me on Tidelift](https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white)](https://tidelift.com/subscription/pkg/rubygems-tree_haver?utm_source=rubygems-tree_haver&utm_medium=referral&utm_campaign=readme)
496
500
 
497
501
  - 💡Subscribe for support guarantees covering *all* your FLOSS dependencies
502
+
498
503
  - 💡Tidelift is part of [Sonar](https://blog.tidelift.com/tidelift-joins-sonar)
504
+
499
505
  - 💡Tidelift pays maintainers to maintain the software you depend on\!<br/>📊`@`Pointy Haired Boss: An [enterprise support](https://tidelift.com/subscription/pkg/rubygems-tree_haver?utm_source=rubygems-tree_haver&utm_medium=referral&utm_campaign=readme) subscription is "[never gonna let you down](https://www.youtube.com/watch?v=dQw4w9WgXcQ)", and *supports* open source maintainers
500
- Alternatively:
506
+ Alternatively:
501
507
 
502
508
  - [![Live Chat on Discord](https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord)](https://discord.gg/3qme4XHNKN)
509
+
503
510
  - [![Get help from me on Upwork](https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white)](https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share)
511
+
504
512
  - [![Get help from me on Codementor](https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white)](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github)
505
513
  </details>
506
514
 
@@ -567,7 +575,7 @@ TreeHaver supports 10 parsing backends, each with different trade-offs. The `aut
567
575
  | **MRI** | C extension via ruby\_tree\_sitter | ⚡ Fastest | MRI only | [JSON](examples/mri_json.rb) · [JSONC](examples/mri_jsonc.rb) · \~\~Bash\~\~\* · [TOML](examples/mri_toml.rb) |
568
576
  | **Rust** | Precompiled via tree\_stump | ⚡ Very Fast | ✅ Good | [JSON](examples/rust_json.rb) · [JSONC](examples/rust_jsonc.rb) · \~\~Bash\~\~\* · [TOML](examples/rust_toml.rb) |
569
577
  | **FFI** | Dynamic linking via FFI | 🔵 Fast | ✅ Universal | [JSON](examples/ffi_json.rb) · [JSONC](examples/ffi_jsonc.rb) · [Bash](examples/ffi_bash.rb) · [TOML](examples/ffi_toml.rb) |
570
- | **Java** | JNI bindings (jtreesitter >= 0.26.0) | ⚡ Very Fast | JRuby only | [JSON](examples/java_json.rb) · [JSONC](examples/java_jsonc.rb) · [Bash](examples/java_bash.rb) · [TOML](examples/java_toml.rb) |
578
+ | **Java** | JNI bindings (jtreesitter \>= 0.26.0) | ⚡ Very Fast | JRuby only | [JSON](examples/java_json.rb) · [JSONC](examples/java_jsonc.rb) · [Bash](examples/java_bash.rb) · [TOML](examples/java_toml.rb) |
571
579
 
572
580
  #### Language-Specific Backends (Native Parser Integration)
573
581
 
@@ -584,8 +592,8 @@ TreeHaver supports 10 parsing backends, each with different trade-offs. The `aut
584
592
  **Known Issues:**
585
593
  - \*MRI + Bash: ABI incompatibility (use FFI instead)
586
594
  - \*Rust + Bash: Version mismatch (use FFI instead)
587
- **Backend Requirements:**
588
-
595
+ **Backend Requirements:**
596
+ <!-- end list -->
589
597
  ``` ruby
590
598
  # Tree-sitter backends
591
599
  gem "ruby_tree_sitter", "~> 2.0" # MRI backend
@@ -659,7 +667,6 @@ This is particularly useful for:
659
667
  - **Performance comparison**: Benchmark different backends
660
668
  - **Fallback scenarios**: Try one backend, fall back to another
661
669
  - **Thread isolation**: Each thread can use a different backend safely
662
-
663
670
  <!-- end list -->
664
671
  ``` ruby
665
672
  # Example: Testing with multiple backends
@@ -729,10 +736,9 @@ The `find_library_path_safe` method only returns paths in trusted directories.
729
736
  - `/usr/lib/x86_64-linux-gnu`, `/usr/lib/aarch64-linux-gnu`
730
737
  - `/usr/local/lib`
731
738
  - `/opt/homebrew/lib`, `/opt/local/lib`
732
- **Adding custom trusted directories:**
733
-
734
- For non-standard installations (Homebrew on Linux, luarocks, mise, asdf, etc.), register additional trusted directories:
735
-
739
+ **Adding custom trusted directories:**
740
+ For non-standard installations (Homebrew on Linux, luarocks, mise, asdf, etc.), register additional trusted directories:
741
+ <!-- end list -->
736
742
  ``` ruby
737
743
  # Programmatically at application startup
738
744
  TreeHaver::PathValidator.add_trusted_directory("/home/linuxbrew/.linuxbrew/Cellar")
@@ -826,7 +832,6 @@ When loading a language grammar, if you don't specify the `symbol:` parameter, T
826
832
  1. **`TREE_SITTER_LANG_SYMBOL`**: Explicit symbol override
827
833
  2. Guessed from filename (e.g., `libtree-sitter-toml.so` → `tree_sitter_toml`)
828
834
  3. Default fallback (`tree_sitter_toml`)
829
-
830
835
  <!-- end list -->
831
836
  ``` bash
832
837
  export TREE_SITTER_LANG_SYMBOL=tree_sitter_toml
@@ -845,10 +850,10 @@ export TREE_SITTER_JSON_PATH=/usr/local/lib/libtree-sitter-json.so
845
850
 
846
851
  For the Java backend on JRuby, you need:
847
852
 
848
- 1. **jtreesitter >= 0.26.0** JAR from Maven Central
849
- 2. **Tree-sitter runtime library** (`libtree-sitter.so`) version 0.26+
850
- 3. **Grammar `.so` files** built against tree-sitter 0.26+
851
-
853
+ 1. **jtreesitter \>= 0.26.0** JAR from Maven Central
854
+ 2. **Tree-sitter runtime library** (`libtree-sitter.so`) version 0.26+
855
+ 3. **Grammar `.so` files** built against tree-sitter 0.26+
856
+ <!-- end list -->
852
857
  ``` bash
853
858
  # Download jtreesitter JAR (or use bin/setup-jtreesitter)
854
859
  export TREE_SITTER_JAVA_JARS_DIR=/path/to/java-tree-sitter/jars
@@ -864,7 +869,7 @@ export TREE_SITTER_TOML_PATH=/path/to/libtree-sitter-toml.so
864
869
 
865
870
  If you get "version mismatch" errors, rebuild the grammar:
866
871
 
867
- ```bash
872
+ ``` bash
868
873
  # Use the provided build script
869
874
  bin/build-grammar toml
870
875
 
@@ -1047,7 +1052,6 @@ end
1047
1052
  └── TreeHaver::Error # Base error class
1048
1053
  ├── TreeHaver::NotAvailable # Backend/grammar not available
1049
1054
  └── TreeHaver::BackendConflict # Backend incompatibility detected
1050
-
1051
1055
  **Compatibility Mode Behavior:**
1052
1056
 
1053
1057
  The compat mode (`require "tree_haver/compat"`) creates aliases but **does not change the exception hierarchy**:
@@ -1084,14 +1088,13 @@ end
1084
1088
  ```
1085
1089
 
1086
1090
  2. **Never rely on `rescue => e`** to catch TreeHaver errors (it won't work)
1087
- **Why inherit from Exception?**
1088
-
1089
- Following ruby\_tree\_sitter's reasoning:
1091
+ **Why inherit from Exception?**
1092
+ Following ruby\_tree\_sitter's reasoning:
1093
+ <!-- end list -->
1090
1094
  - **Thread safety**: Prevents accidental catching in thread cleanup code
1091
1095
  - **Signal handling**: Ensures parsing errors don't interfere with SIGTERM/SIGINT
1092
1096
  - **Intentional handling**: Forces developers to explicitly handle parsing errors
1093
- See `lib/tree_haver/compat.rb` for compatibility layer documentation.
1094
-
1097
+ See `lib/tree_haver/compat.rb` for compatibility layer documentation.
1095
1098
  ## 🔧 Basic Usage
1096
1099
 
1097
1100
  ### Quick Start
@@ -1309,7 +1312,6 @@ This flexibility is useful for:
1309
1312
  - **Versioning**: Register different grammar versions (e.g., `:ruby_2`, `:ruby_3`)
1310
1313
  - **Testing**: Use unique names to avoid collisions between tests
1311
1314
  - **Context-specific naming**: Use names that make sense for your application
1312
-
1313
1315
  <!-- end list -->
1314
1316
  ``` ruby
1315
1317
  # Register the same TOML grammar under different names for different purposes
@@ -1506,8 +1508,8 @@ The Java backend will work with:
1506
1508
 
1507
1509
  - Grammar JARs built specifically for java-tree-sitter / jtreesitter (self-contained, [docs](https://tree-sitter.github.io/java-tree-sitter/), [maven](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter), [source](https://github.com/tree-sitter/java-tree-sitter))
1508
1510
  - Grammar `.so` files that statically link tree-sitter
1509
- **Option 3: Citrus Backend (pure Ruby, portable)**
1510
-
1511
+ **Option 3: Citrus Backend (pure Ruby, portable)**
1512
+ <!-- end list -->
1511
1513
  ``` ruby
1512
1514
  # Gemfile
1513
1515
  gem "tree_haver"
@@ -2095,7 +2097,7 @@ Thanks for RTFM. ☺️
2095
2097
  [📌gitmoji]: https://gitmoji.dev
2096
2098
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
2097
2099
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
2098
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.421-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
2100
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.422-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
2099
2101
  [🔐security]: SECURITY.md
2100
2102
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
2101
2103
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -231,15 +231,16 @@ module TreeHaver
231
231
  # Container nodes don't have string_content and will raise TypeError
232
232
  if @inner_node.respond_to?(:string_content)
233
233
  begin
234
- @inner_node.string_content.to_s
234
+ content = @inner_node.string_content.to_s
235
+ # If string_content is non-empty, use it (leaf node)
236
+ return content unless content.empty?
235
237
  rescue TypeError
236
- # Container node - concatenate children's text
237
- children.map(&:text).join
238
+ # Container node - fall through to concatenate children
238
239
  end
239
- else
240
- # For container nodes, concatenate children's text
241
- children.map(&:text).join
242
240
  end
241
+
242
+ # For container nodes, concatenate children's text
243
+ children.map(&:text).join
243
244
  end
244
245
 
245
246
  # Get child nodes
@@ -640,8 +640,17 @@ module TreeHaver
640
640
  def child(index)
641
641
  # jtreesitter 0.26.0: getChild returns Optional<Node> or throws IndexOutOfBoundsException
642
642
  result = @impl.getChild(index)
643
- return unless result.respond_to?(:isPresent) ? result.isPresent : result
644
- java_node = result.respond_to?(:get) ? result.get : result
643
+ return if result.nil?
644
+
645
+ # Handle Java Optional
646
+ if result.respond_to?(:isPresent)
647
+ return unless result.isPresent
648
+ java_node = result.get
649
+ else
650
+ # Direct Node return (some jtreesitter versions)
651
+ java_node = result
652
+ end
653
+
645
654
  Node.new(java_node)
646
655
  rescue ::Java::JavaLang::IndexOutOfBoundsException
647
656
  nil
@@ -653,9 +662,19 @@ module TreeHaver
653
662
  # @return [Node, nil] the child node or nil if not found
654
663
  def child_by_field_name(name)
655
664
  # jtreesitter 0.26.0: getChildByFieldName returns Optional<Node>
665
+ # However, some versions or scenarios may return null directly
656
666
  result = @impl.getChildByFieldName(name)
657
- return unless result.respond_to?(:isPresent) ? result.isPresent : result
658
- java_node = result.respond_to?(:get) ? result.get : result
667
+ return if result.nil?
668
+
669
+ # Handle Java Optional
670
+ if result.respond_to?(:isPresent)
671
+ return unless result.isPresent
672
+ java_node = result.get
673
+ else
674
+ # Direct Node return (some jtreesitter versions)
675
+ java_node = result
676
+ end
677
+
659
678
  Node.new(java_node)
660
679
  end
661
680
 
@@ -727,8 +746,16 @@ module TreeHaver
727
746
  def parent
728
747
  # jtreesitter 0.26.0: getParent returns Optional<Node>
729
748
  result = @impl.getParent
730
- return unless result.respond_to?(:isPresent) ? result.isPresent : result
731
- java_node = result.respond_to?(:get) ? result.get : result
749
+ return if result.nil?
750
+
751
+ # Handle Java Optional
752
+ if result.respond_to?(:isPresent)
753
+ return unless result.isPresent
754
+ java_node = result.get
755
+ else
756
+ java_node = result
757
+ end
758
+
732
759
  Node.new(java_node)
733
760
  end
734
761
 
@@ -738,8 +765,16 @@ module TreeHaver
738
765
  def next_sibling
739
766
  # jtreesitter 0.26.0: getNextSibling returns Optional<Node>
740
767
  result = @impl.getNextSibling
741
- return unless result.respond_to?(:isPresent) ? result.isPresent : result
742
- java_node = result.respond_to?(:get) ? result.get : result
768
+ return if result.nil?
769
+
770
+ # Handle Java Optional
771
+ if result.respond_to?(:isPresent)
772
+ return unless result.isPresent
773
+ java_node = result.get
774
+ else
775
+ java_node = result
776
+ end
777
+
743
778
  Node.new(java_node)
744
779
  end
745
780
 
@@ -749,8 +784,16 @@ module TreeHaver
749
784
  def prev_sibling
750
785
  # jtreesitter 0.26.0: getPrevSibling returns Optional<Node>
751
786
  result = @impl.getPrevSibling
752
- return unless result.respond_to?(:isPresent) ? result.isPresent : result
753
- java_node = result.respond_to?(:get) ? result.get : result
787
+ return if result.nil?
788
+
789
+ # Handle Java Optional
790
+ if result.respond_to?(:isPresent)
791
+ return unless result.isPresent
792
+ java_node = result.get
793
+ else
794
+ java_node = result
795
+ end
796
+
754
797
  Node.new(java_node)
755
798
  end
756
799
 
@@ -288,11 +288,17 @@ module TreeHaver
288
288
  #
289
289
  # @return [String] Node text
290
290
  def text
291
- # Markly nodes have string_content for leaf nodes
291
+ # Markly nodes have string_content for leaf nodes (text, code, etc.)
292
+ # Container nodes (heading, paragraph, etc.) have empty string_content
293
+ # and need to use to_plaintext or concatenate children's text.
292
294
  if @inner_node.respond_to?(:string_content)
293
- @inner_node.string_content.to_s
294
- elsif @inner_node.respond_to?(:to_plaintext)
295
- # For container nodes, use to_plaintext or concatenate
295
+ content = @inner_node.string_content.to_s
296
+ # If string_content is non-empty, use it (leaf node)
297
+ return content unless content.empty?
298
+ end
299
+
300
+ # For container nodes, use to_plaintext or concatenate children
301
+ if @inner_node.respond_to?(:to_plaintext)
296
302
  begin
297
303
  @inner_node.to_plaintext
298
304
  rescue
@@ -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.2.4"
13
+ VERSION = "3.2.6"
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: 3.2.4
4
+ version: 3.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -293,10 +293,10 @@ licenses:
293
293
  - MIT
294
294
  metadata:
295
295
  homepage_uri: https://tree-haver.galtzo.com/
296
- source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v3.2.4
297
- changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v3.2.4/CHANGELOG.md
296
+ source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v3.2.6
297
+ changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v3.2.6/CHANGELOG.md
298
298
  bug_tracker_uri: https://github.com/kettle-rb/tree_haver/issues
299
- documentation_uri: https://www.rubydoc.info/gems/tree_haver/3.2.4
299
+ documentation_uri: https://www.rubydoc.info/gems/tree_haver/3.2.6
300
300
  funding_uri: https://github.com/sponsors/pboling
301
301
  wiki_uri: https://github.com/kettle-rb/tree_haver/wiki
302
302
  news_uri: https://www.railsbling.com/tags/tree_haver
metadata.gz.sig CHANGED
Binary file