toml-merge 1.0.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: abfa09261d6a9dadbb743477aa49d16a5ed1800c5d34ff8a22a908b505ccdeb0
4
- data.tar.gz: 7b15341de2da2421ca18fd0fbc2085006e6e586740fac87267d810485bb0808b
3
+ metadata.gz: 2f9cb256fd16a085c6a1d5f568bbe2eef0bcbeaf4a9cbc3f7bce5637b5770bce
4
+ data.tar.gz: 4000f1e9f82713bb1016ab52fa96112ca917f2f371baefc2dabf2a29f0807013
5
5
  SHA512:
6
- metadata.gz: f3293c532e05e13daeedf48c54078d7e4c2949cfd6c6ea8fb6f8be2dc5feb2ce881cdb008d1be2a3ccc8eacde0cd18a6b09375ff4afc4c6c8f762c92189f81b9
7
- data.tar.gz: 63818c0a6e39c802175fe0d7caa175e4ed111131721c549acbb4c081e8ac91501cb083b782959ada10f087590cfdfc892e30c3bad88c2b6f9b4892ff37593e88
6
+ metadata.gz: b57d61b70484cc8099d2d7b8249c093b729718182ffb607cd4f1db59c8ca372b7ee26d4b64f92d7f359956e01b337f07498e396353373d998efefb921feba5a1
7
+ data.tar.gz: 0dce84d713ce68e1f5158fa3c2d883311741e7d28c4a7d93a17c9baa9e2356e8ecbc6d7be0aa1d3247712e287ae153d6170284b7132caa2de19e225b1d305b1e
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,182 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [2.0.0] - 2026-01-09
34
+
35
+ - TAG: [v2.0.0][2.0.0t]
36
+ - COVERAGE: 88.38% -- 563/637 lines in 11 files
37
+ - BRANCH COVERAGE: 64.13% -- 177/276 branches in 11 files
38
+ - 97.03% documented
39
+
40
+ ### Added
41
+
42
+ - FFI backend isolation for test suite
43
+ - Added `bin/rspec-ffi` script to run FFI specs in isolation (before MRI backend loads)
44
+ - Added `spec/spec_ffi_helper.rb` for FFI-specific test configuration
45
+ - Updated Rakefile with `ffi_specs` and `remaining_specs` tasks
46
+ - The `:test` task now runs FFI specs first, then remaining specs
47
+ - **Emitter autoload** - Added `Emitter` to module autoload list
48
+ - Previously missing, causing `NameError: uninitialized constant Emitter` in ConflictResolver
49
+ - Now properly autoloaded via `autoload :Emitter, "toml/merge/emitter"`
50
+ - `Backends` module with constants for backend selection
51
+ - `Backends::TREE_SITTER` (`:tree_sitter_toml`) - Native tree-sitter parser
52
+ - `Backends::CITRUS` (`:citrus_toml`) - Pure Ruby toml-rb parser
53
+ - `Backends::AUTO` (`:auto`) - Auto-detect available backend
54
+ - `Backends.validate!` and `Backends.valid?` for validation
55
+ - `SmartMerger` now accepts `backend:` parameter for explicit backend selection
56
+ - Follows same pattern as markdown-merge
57
+ - Auto-detects backend by default, or use `backend: Backends::CITRUS` to force pure Ruby
58
+ - `FileAnalysis` now accepts `backend:` parameter and exposes resolved backend via `#backend` attr
59
+ - `NodeWrapper` now accepts `backend:` and `document_root:` parameters for correct normalization
60
+ - **Structural normalization for Citrus backend**: Tree-sitter and Citrus backends produce different AST structures for tables:
61
+ - Tree-sitter: Table nodes contain pairs as children
62
+ - Citrus: Table nodes only contain header; pairs are siblings at document level
63
+ - `NodeWrapper#pairs` now finds associated pairs regardless of AST structure
64
+ - `NodeWrapper#content` now returns full table content on both backends
65
+ - `NodeWrapper#effective_end_line` calculates correct end line including pairs
66
+ - `FileAnalysis` passes `document_root` to all NodeWrappers for sibling lookups
67
+ - This enables the merge logic to work identically across backends
68
+ - `NodeTypeNormalizer` module for backend-agnostic node type handling
69
+ - Maps backend-specific types (e.g., `table_array_element`) to canonical types (e.g., `array_of_tables`)
70
+ - Supports both `tree_sitter_toml` and `citrus_toml` backends with comprehensive type mappings
71
+ - Provides helper methods: `table_type?`, `value_type?`, `key_type?`, `container_type?`
72
+ - Extensible via `register_backend` for custom TOML parsers
73
+ - Follows the same pattern as `markdown-merge`'s `NodeTypeNormalizer`
74
+ - `NodeWrapper#canonical_type` method returns the normalized type for a node
75
+ - Comprehensive test suite for `NodeTypeNormalizer` with 26 new specs
76
+ - `spec/support/dependency_tags.rb` for conditional test execution based on backend availability
77
+
78
+ ### Changed
79
+
80
+ - ast-merge v3.1.0
81
+ - tree_haver v4.0.3, adds error handling for FFI backend
82
+ - **Test suite now explicitly tests all available backend modes** - Tests previously ran with
83
+ whatever backend was auto-selected. Now specs explicitly test up to five backend configurations:
84
+ - `:auto` backend - Tests default user experience (backend-agnostic)
85
+ - `:mri` backend via `TreeHaver.with_backend(:mri)` - Tests explicit tree-sitter MRI behavior
86
+ - `:citrus` backend via `TreeHaver.with_backend(:citrus)` - Tests explicit toml-rb behavior
87
+ - `:rust` backend via `TreeHaver.with_backend(:rust)` - Tests explicit tree-sitter Rust behavior
88
+ - `:java` backend via `TreeHaver.with_backend(:java)` - Tests explicit tree-sitter Java behavior
89
+
90
+ This ensures consistent behavior is verified across all backends, rather than relying
91
+ on auto-selection which may vary by platform. Each shared example group is included
92
+ in all contexts with appropriate dependency tags (`:toml_grammar`, `:toml_rb`,
93
+ `:toml_parsing`, `:rust_backend`, `:java_backend`). Tests for unavailable backends
94
+ are automatically skipped.
95
+
96
+ **Note**: The `:java_backend` tag now correctly detects whether the Java backend can
97
+ actually load grammars. Standard `.so` files built for MRI's tree-sitter C bindings
98
+ are NOT compatible with java-tree-sitter. Tests will be skipped on JRuby unless
99
+ grammar JARs from Maven Central (built for java-tree-sitter's Foreign Function Memory
100
+ API) are available.
101
+
102
+ - **Backend handling simplified** - Let TreeHaver handle all backend selection:
103
+ - Removed `backend:` parameter from `SmartMerger` and `FileAnalysis`
104
+ - Removed `Backends` module entirely (was unused after removing `backend:` parameter)
105
+ - Users control backend via TreeHaver directly (`TREE_HAVER_BACKEND` env var, `TreeHaver.backend=`, or `TreeHaver.with_backend`)
106
+ - This ensures compatibility with all TreeHaver backends (mri, rust, ffi, java, citrus)
107
+ - **Backend naming simplified** to align with TreeHaver:
108
+ - `NodeTypeNormalizer` mappings now keyed by `:tree_sitter` and `:citrus`
109
+ - All native TreeHaver backends (mri, rust, ffi, java) produce tree-sitter AST format
110
+ - See `.github/COPILOT_INSTRUCTIONS.md` for comprehensive TreeHaver backend documentation
111
+ - **NodeWrapper**: Now inherits from `Ast::Merge::NodeWrapperBase`
112
+ - Removes ~80 lines of duplicated code (initialization, line extraction, basic methods)
113
+ - Uses `process_additional_options` hook for TOML-specific options (`backend`, `document_root`)
114
+ - Keeps TOML-specific type predicates using `NodeTypeNormalizer`
115
+ - Keeps Citrus structural normalization logic for `#pairs`, `#content`, `#effective_end_line`
116
+ - Adds `#node_wrapper?` method for distinguishing from `NodeTyping::Wrapper`
117
+ - **citrus_toml mappings**: Updated to match actual Citrus/toml-rb node types
118
+ - `table_array` → `:array_of_tables` (Citrus produces `:table_array`, not `:table_array_element`)
119
+ - `keyvalue` → `:pair` (Citrus produces `:keyvalue`, not `:pair`)
120
+ - Added all Citrus-specific integer types: `decimal_integer`, `hexadecimal_integer`, `octal_integer`, `binary_integer`
121
+ - Added all Citrus-specific string types: `basic_string`, `literal_string`, `multiline_string`, `multiline_literal`
122
+ - Added all Citrus-specific datetime types: `local_date`, `local_time`, `local_datetime`, `offset_datetime`
123
+ - Added Citrus-specific boolean types: `true`, `false`
124
+ - Added whitespace types: `space`, `line_break`, `indent`, `repeat`
125
+ - **FileAnalysis error handling**: Now rescues `TreeHaver::Error` instead of `TreeHaver::NotAvailable`
126
+ - `TreeHaver::Error` inherits from `Exception`, not `StandardError`
127
+ - `TreeHaver::NotAvailable` is a subclass of `TreeHaver::Error`, so it's also caught
128
+ - Fixes parse error handling on TruffleRuby where Citrus backend raises `TreeHaver::Error`
129
+ - **Dependency tags**: Refactored to use shared `TreeHaver::RSpec::DependencyTags` from tree_haver gem
130
+ - All dependency detection is now centralized in tree_haver
131
+ - Use `require "tree_haver/rspec"` for shared RSpec configuration
132
+ - `TomlMergeDependencies` is now an alias to `TreeHaver::RSpec::DependencyTags`
133
+ - Enables `TOML_MERGE_DEBUG=1` for dependency summary output
134
+ - **FileAnalysis**: Error handling now follows the standard pattern
135
+ - Parse errors are collected but not re-raised from FileAnalysis
136
+ - `valid?` returns false when there are errors or no AST
137
+ - SmartMergerBase handles raising the appropriate parse error
138
+ - Consistent with json-merge, jsonc-merge, and bash-merge implementations
139
+ - **SmartMerger**: Added `**options` for forward compatibility
140
+ - Accepts additional options that may be added to base class in future
141
+ - Passes all options through to `SmartMergerBase`
142
+ - `node_typing` parameter for per-node-type merge preferences
143
+ - Enables `preference: { default: :destination, special_type: :template }` pattern
144
+ - Works with custom merge_types assigned via node_typing lambdas
145
+ - `regions` and `region_placeholder` parameters for nested content merging
146
+ - **ConflictResolver**: Added `**options` for forward compatibility
147
+ - Now passes `match_refiner` to base class instead of storing locally
148
+ - **MergeResult**: Added `**options` for forward compatibility
149
+ - **FileAnalysis**: Simplified to use `TreeHaver.parser_for` API
150
+ - Removed 40+ lines of grammar loading boilerplate
151
+ - Now relies on tree_haver for auto-discovery and Citrus fallback
152
+ - `:tree_sitter_toml` RSpec tag for tree-sitter-toml grammar tests
153
+ - `:toml_rb` RSpec tag for toml-rb/Citrus backend tests
154
+ - `:toml_backend` RSpec tag for tests requiring any TOML backend
155
+ - **BREAKING**: `NodeWrapper` type predicates now use `NodeTypeNormalizer` for backend-agnostic type checking
156
+ - `array_of_tables?` now correctly identifies both `table_array_element` (tree-sitter) and `array_of_tables` nodes
157
+ - All predicates (`table?`, `pair?`, `string?`, etc.) use canonical types
158
+ - `type?` method checks both raw and canonical types
159
+ - `FileAnalysis#tables` now uses `NodeTypeNormalizer.table_type?` for type detection
160
+ - `FileAnalysis#root_pairs` and `#integrate_nodes` use canonical type checks
161
+ - `TableMatchRefiner#table_node?` uses `NodeTypeNormalizer` for backend-agnostic table detection
162
+ - `compute_signature` method uses canonical types for consistent signatures across backends
163
+ - Rewrote `node_wrapper_spec.rb` with proper tests (removed placeholder/pending tests)
164
+ - Rewrote `table_match_refiner_spec.rb` with working tests using `:toml_backend` tag
165
+ - Updated `spec_helper.rb` load order to ensure `TreeHaver` is available for dependency detection
166
+ - **BREAKING**: Migrate from direct `TreeSitter::Language.load` to `TreeHaver` API
167
+ - Changed `require "tree_sitter"` to `require "tree_haver"` in main module file
168
+ - Added automatic grammar registration via `TreeHaver::GrammarFinder#register!`
169
+ - `FileAnalysis#find_parser_path` now exclusively uses `TreeHaver::GrammarFinder`
170
+ - `FileAnalysis#parse_toml` now uses `TreeHaver::Parser` and `TreeHaver::Language`
171
+ - Removed legacy fallback path search (TreeHaver is now a hard requirement)
172
+ - Updated documentation to reference `TreeHaver::Node` instead of `TreeSitter::Node`
173
+ - Environment variable `TREE_SITTER_TOML_PATH` is still supported via TreeHaver
174
+ - This enables support for multiple tree-sitter backends (MRI, Rust, FFI, Java) and Citrus fallback
175
+
176
+ ### Removed
177
+
178
+ - **Load-time grammar registration** - TreeHaver's `parser_for` now handles grammar discovery
179
+ and registration automatically. Removed manual `GrammarFinder` calls and warnings from
180
+ `lib/toml/merge.rb`.
181
+
182
+ ### Fixed
183
+
184
+ - **Citrus backend normalization improvements** for TruffleRuby compatibility:
185
+ - `NodeWrapper#key_name` now strips whitespace from key text (Citrus includes trailing spaces)
186
+ - `NodeWrapper#table_name` now strips whitespace from table header text
187
+ - `NodeWrapper#extract_inline_table_keys` now recursively handles Citrus's deeply nested
188
+ structure (`inline_table -> optional -> keyvalue -> keyvalue -> stripped_key -> key -> bare_key`)
189
+ - `NodeWrapper#elements` now recursively handles Citrus's array structure where elements
190
+ are nested in `array_elements -> repeat -> indent -> decimal_integer` chains
191
+ - Both methods now correctly extract all values instead of just the first one
192
+ - `NodeWrapper#value_node` now skips Citrus internal nodes (`whitespace`, `unknown`, `space`)
193
+ - All `NodeTypeNormalizer.canonical_type()` calls now pass `@backend` parameter for correct type mapping
194
+ - `FileAnalysis#root_pairs` now correctly filters pairs to only include those BEFORE the first table
195
+ (Citrus has flat AST structure where all pairs are document siblings)
196
+ - `MergeResult#add_node` now uses `effective_end_line` to include table pairs on Citrus backend
197
+ - `TableMatchRefiner#table_node?` now uses node's backend for correct type checking
198
+ - Test helper `parse_toml` now uses `FileAnalysis` for proper backend detection
199
+ - `NodeTypeNormalizer.canonical_type` now defaults to `:tree_sitter_toml` backend when no backend is specified
200
+ - Added `DEFAULT_BACKEND` constant and overrode `canonical_type` and `wrap` methods
201
+ - Fixes issue where calling `canonical_type(:table_array_element)` without a backend argument would passthrough instead of mapping to `:array_of_tables`
202
+ - Value type predicates (`string?`, `integer?`, `float?`, `boolean?`, `array?`, `inline_table?`, `datetime?`) now work correctly
203
+ - Consolidated duplicate `describe` blocks in spec files (`file_analysis_spec.rb`, `merge_result_spec.rb`, `node_wrapper_spec.rb`)
204
+ - Fixed lint violations: added missing expectations to tests, used safe navigation where appropriate
205
+ - No longer warns about missing TOML grammar when the grammar file exists but tree-sitter runtime is unavailable
206
+ - This is expected behavior when using non-tree-sitter backends (Citrus, Prism, etc.)
207
+ - Warning now only appears when the grammar file is actually missing
208
+
33
209
  ## [1.0.0] - 2025-12-19
34
210
 
35
211
  - TAG: [v1.0.0][1.0.0t]
@@ -47,6 +223,10 @@ Please file a bug if you notice a violation of semantic versioning.
47
223
  - Can force Citrus backend via `TREE_HAVER_BACKEND=citrus` environment variable
48
224
  - Added graceful error handling when neither tree-sitter-toml nor toml-rb are available
49
225
 
50
- [Unreleased]: https://github.com/kettle-rb/toml-merge/compare/v1.0.0...HEAD
226
+ [Unreleased]: https://github.com/kettle-rb/toml-merge/compare/v2.0.0...HEAD
227
+ [2.0.1]: https://github.com/kettle-rb/toml-merge/compare/v1.0.0...v2.0.1
228
+ [2.0.1t]: https://github.com/kettle-rb/toml-merge/releases/tag/v2.0.1
229
+ [2.0.0]: https://github.com/kettle-rb/toml-merge/compare/v1.0.0...v2.0.0
230
+ [2.0.0t]: https://github.com/kettle-rb/toml-merge/releases/tag/v2.0.0
51
231
  [1.0.0]: https://github.com/kettle-rb/toml-merge/compare/772a5f5802ce518f2e2c83a561eb583ed634bac4...v1.0.0
52
232
  [1.0.0t]: https://github.com/kettle-rb/toml-merge/tags/v1.0.0
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2025 Peter H. Boling
3
+ Copyright (c) 2025-2026 Peter H. Boling
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal