ast-merge 2.0.1 → 2.0.3
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +42 -1
- data/README.md +224 -201
- data/lib/ast/merge/debug_logger.rb +5 -6
- data/lib/ast/merge/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +8 -8
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87b2cf66d0fbccf11852ffad3a967f7b470473a31e47af2e87fab99e57f54d23
|
|
4
|
+
data.tar.gz: 8472ce9175eb6fb14e29bcb4f65775d6557d40206ec5c763800012cf70ff7178
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7149ffb09a690608f382f63e9cff91bd85ceb25518b6744cc4617c638fe0acc4bd3a96de17f047c72161a5e4836b615e1721e550e34eee998916ab78b82df380
|
|
7
|
+
data.tar.gz: 0b5b63b49be561c75027767dd850a692d31a047e000aa2404cc83df27bc4304a6d047e434e2402ddf1ffaed63a5044ea60f515b80959284b6faa52222da8e7fa
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,43 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.0.3] - 2025-12-30
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.0.3][2.0.3t]
|
|
36
|
+
- COVERAGE: 88.45% -- 2894/3272 lines in 53 files
|
|
37
|
+
- BRANCH COVERAGE: 67.83% -- 698/1029 branches in 53 files
|
|
38
|
+
- 98.82% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `Ast::Merge::DebugLogger::BENCHMARK_AVAILABLE` now correctly detects when benchmark gem is unavailable
|
|
43
|
+
- Previous implementation used `autoload` which never raises `LoadError` (it only registers for lazy loading)
|
|
44
|
+
- Now uses `require "benchmark"` which properly catches `LoadError` on Ruby 4.0+ where benchmark is a bundled gem
|
|
45
|
+
- The `#time` method now correctly falls back to non-timed execution when benchmark is unavailable
|
|
46
|
+
|
|
47
|
+
## [2.0.2] - 2025-12-30
|
|
48
|
+
|
|
49
|
+
- TAG: [v2.0.2][2.0.2t]
|
|
50
|
+
- COVERAGE: 88.47% -- 2894/3271 lines in 53 files
|
|
51
|
+
- BRANCH COVERAGE: 67.83% -- 698/1029 branches in 53 files
|
|
52
|
+
- 98.82% documented
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- Backend Platform Compatibility section to README and GEM_FAMILY_SECTION.md
|
|
57
|
+
- Documents which tree_haver backends work on MRI, JRuby, and TruffleRuby
|
|
58
|
+
- Explains why JRuby and TruffleRuby have limited tree-sitter backend support
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
|
|
62
|
+
- Updated RSpec README documentation for tree_haver dependency tag changes
|
|
63
|
+
- All tags now follow consistent naming conventions with suffixes
|
|
64
|
+
- Backend tags use `*_backend` suffix
|
|
65
|
+
- Engine tags use `*_engine` suffix
|
|
66
|
+
- Grammar tags use `*_grammar` suffix
|
|
67
|
+
- Parsing capability tags use `*_parsing` suffix
|
|
68
|
+
- See [lib/ast/merge/rspec/README.md](lib/ast/merge/rspec/README.md) for complete tag reference
|
|
69
|
+
|
|
33
70
|
## [2.0.1] - 2025-12-29
|
|
34
71
|
|
|
35
72
|
- TAG: [v2.0.1][2.0.1t]
|
|
@@ -261,7 +298,11 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
261
298
|
|
|
262
299
|
- Initial release
|
|
263
300
|
|
|
264
|
-
[Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v2.0.
|
|
301
|
+
[Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v2.0.3...HEAD
|
|
302
|
+
[2.0.3]: https://github.com/kettle-rb/ast-merge/compare/v2.0.2...v2.0.3
|
|
303
|
+
[2.0.3t]: https://github.com/kettle-rb/ast-merge/releases/tag/v2.0.3
|
|
304
|
+
[2.0.2]: https://github.com/kettle-rb/ast-merge/compare/v2.0.1...v2.0.2
|
|
305
|
+
[2.0.2t]: https://github.com/kettle-rb/ast-merge/releases/tag/v2.0.2
|
|
265
306
|
[2.0.1]: https://github.com/kettle-rb/ast-merge/compare/v2.0.0...v2.0.1
|
|
266
307
|
[2.0.1t]: https://github.com/kettle-rb/ast-merge/releases/tag/v2.0.1
|
|
267
308
|
[2.0.0]: https://github.com/kettle-rb/ast-merge/compare/v1.1.0...v2.0.0
|
data/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
| 📍 NOTE
|
|
2
|
-
|
|
3
|
-
| RubyGems (the [GitHub org]
|
|
4
|
-
| Ultimately [4 maintainers]
|
|
5
|
-
| It is a [complicated story]
|
|
6
|
-
| Simply put - there was active policy for adding or removing maintainers/owners of [rubygems]
|
|
7
|
-
| I'm adding notes like this to gems because I [don't condone theft]
|
|
8
|
-
| If a similar theft happened with my repos/gems, I'd hope some would stand up for me.
|
|
9
|
-
| Disenfranchised former-maintainers have started [gem.coop]
|
|
10
|
-
| Once available I will publish there exclusively; unless RubyCentral makes amends with the community.
|
|
11
|
-
| The ["Technology for Humans: Joel Draper"]
|
|
12
|
-
| See [here]
|
|
13
|
-
| What I'm doing: A (WIP) proposal for [bundler/gem scopes]
|
|
1
|
+
| 📍 NOTE |
|
|
2
|
+
| --- |
|
|
3
|
+
| RubyGems (the [GitHub org](https://github.com/rubygems/), not the website) [suffered](https://joel.drapper.me/p/ruby-central-security-measures/) a [hostile takeover](https://pup-e.com/blog/goodbye-rubygems/) in September 2025. |
|
|
4
|
+
| Ultimately [4 maintainers](https://www.reddit.com/r/ruby/s/gOk42POCaV) were [hard removed](https://bsky.app/profile/martinemde.com/post/3m3occezxxs2q) and a reason has been given for only 1 of those, while 2 others resigned in protest. |
|
|
5
|
+
| It is a [complicated story](https://joel.drapper.me/p/ruby-central-takeover/) which is difficult to [parse quickly](https://joel.drapper.me/p/ruby-central-fact-check/). |
|
|
6
|
+
| Simply put - there was active policy for adding or removing maintainers/owners of [rubygems](https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/rubygems/POLICIES.md?plain=1#L187-L196) and [bundler](https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/bundler/playbooks/TEAM_CHANGES.md), and those [policies were not followed](https://www.reddit.com/r/ruby/comments/1ove9vp/rubycentral_hates_this_one_fact/). |
|
|
7
|
+
| I'm adding notes like this to gems because I [don't condone theft](https://joel.drapper.me/p/ruby-central/) of repositories or gems from their rightful owners. |
|
|
8
|
+
| If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
|
|
9
|
+
| Disenfranchised former-maintainers have started [gem.coop](https://gem.coop). |
|
|
10
|
+
| Once available I will publish there exclusively; unless RubyCentral makes amends with the community. |
|
|
11
|
+
| The ["Technology for Humans: Joel Draper"](https://youtu.be/_H4qbtC5qzU?si=BvuBU90R2wAqD2E6) podcast episode by [reinteractive](https://reinteractive.com/ruby-on-rails) is the most cogent summary I'm aware of. |
|
|
12
|
+
| See [here](https://github.com/gem-coop/gem.coop/issues/12), [here](https://gem.coop) and [here](https://martinemde.com/2025/10/05/announcing-gem-coop.html) for more info on what comes next. |
|
|
13
|
+
| What I'm doing: A (WIP) proposal for [bundler/gem scopes](https://github.com/galtzo-floss/bundle-namespace), and a (WIP) proposal for a federated [gem server](https://github.com/galtzo-floss/gem-server). |
|
|
14
14
|
|
|
15
15
|
[rubygems-org]: https://github.com/rubygems/
|
|
16
16
|
[draper-security]: https://joel.drapper.me/p/ruby-central-security-measures/
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
[rubygems-maint-policy]: https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/rubygems/POLICIES.md?plain=1#L187-L196
|
|
32
32
|
[policy-fail]: https://www.reddit.com/r/ruby/comments/1ove9vp/rubycentral_hates_this_one_fact/
|
|
33
33
|
|
|
34
|
-
[![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0]
|
|
34
|
+
[](https://discord.gg/3qme4XHNKN) [](https://www.ruby-lang.org/) [](https://github.com/kettle-rb)
|
|
35
35
|
|
|
36
36
|
[🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
|
|
37
37
|
[🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
|
|
43
43
|
# ☯️ Ast::Merge
|
|
44
44
|
|
|
45
|
-
[![Version]
|
|
45
|
+
[](https://bestgems.org/gems/ast-merge) [](http://github.com/kettle-rb/ast-merge/releases) [](https://opensource.org/licenses/MIT) [](https://bestgems.org/gems/ast-merge) [](https://www.codetriage.com/kettle-rb/ast-merge) [](https://codecov.io/gh/kettle-rb/ast-merge) [](https://coveralls.io/github/kettle-rb/ast-merge?branch=main) [](https://qlty.sh/gh/kettle-rb/projects/ast-merge/metrics/code?sort=coverageRating) [](https://qlty.sh/gh/kettle-rb/projects/ast-merge) [](https://github.com/kettle-rb/ast-merge/actions/workflows/heads.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/dep-heads.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/truffle.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/locked_deps.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/unlocked_deps.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/supported.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/coverage.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/style.yml) [](https://github.com/kettle-rb/ast-merge/security/code-scanning) [](https://github.com/kettle-rb/ast-merge/actions/workflows/license-eye.yml)
|
|
46
46
|
|
|
47
|
-
`if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know]
|
|
48
|
-
|
|
49
|
-
---
|
|
47
|
+
`if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know](https://discord.gg/3qme4XHNKN), as I may have missed the [discord notification](https://discord.gg/3qme4XHNKN).
|
|
50
48
|
|
|
49
|
+
-----
|
|
51
50
|
`if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
|
|
52
51
|
|
|
53
|
-
[![OpenCollective Backers]
|
|
52
|
+
[](https://opencollective.com/kettle-rb#backer) [](https://opencollective.com/kettle-rb#sponsor) [](https://github.com/sponsors/pboling) [](https://liberapay.com/pboling/donate) [](https://www.paypal.com/paypalme/peterboling) [](https://www.buymeacoffee.com/pboling) [](https://polar.sh/pboling) [](https://ko-fi.com/O5O86SNP4)
|
|
54
53
|
|
|
55
54
|
## 🌻 Synopsis
|
|
56
55
|
|
|
57
56
|
Ast::Merge is **not typically used directly** - instead, use one of the format-specific gems built on top of it.
|
|
58
57
|
|
|
58
|
+
|
|
59
59
|
### The `*-merge` Gem Family
|
|
60
60
|
|
|
61
61
|
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.
|
|
@@ -79,9 +79,9 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
|
|
|
79
79
|
**Example implementations** for the gem templating use case:
|
|
80
80
|
|
|
81
81
|
| Gem | Purpose | Description |
|
|
82
|
-
|
|
83
|
-
| [kettle-dev]
|
|
84
|
-
| [kettle-jem]
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| [kettle-dev](https://github.com/kettle-rb/kettle-dev) | Gem Development | Gem templating tool using `*-merge` gems |
|
|
84
|
+
| [kettle-jem](https://github.com/kettle-rb/kettle-jem) | Gem Templating | Gem template library with smart merge support |
|
|
85
85
|
|
|
86
86
|
[tree_haver]: https://github.com/kettle-rb/tree_haver
|
|
87
87
|
[ast-merge]: https://github.com/kettle-rb/ast-merge
|
|
@@ -107,84 +107,112 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
|
|
|
107
107
|
[toml-rb]: https://github.com/emancu/toml-rb
|
|
108
108
|
[markly]: https://github.com/ioquatix/markly
|
|
109
109
|
[commonmarker]: https://github.com/gjtorikian/commonmarker
|
|
110
|
+
[ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
|
|
111
|
+
[tree_stump]: https://github.com/joker1007/tree_stump
|
|
112
|
+
[jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
|
|
110
113
|
|
|
111
|
-
### Architecture: tree_haver + ast-merge
|
|
112
114
|
|
|
113
|
-
|
|
115
|
+
[ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
|
|
116
|
+
[dotenv]: https://github.com/bkeepers/dotenv
|
|
114
117
|
|
|
115
|
-
####
|
|
118
|
+
#### Backend Platform Compatibility
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
tree\_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
|
|
118
121
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
| Backend | MRI | JRuby | TruffleRuby | Notes |
|
|
123
|
+
| --- | :-: | :-: | :-: | --- |
|
|
124
|
+
| **MRI** ([ruby\_tree\_sitter](https://github.com/Faveod/ruby-tree-sitter)) | ✅ | ❌ | ❌ | C extension, MRI only |
|
|
125
|
+
| **Rust** ([tree\_stump](https://github.com/joker1007/tree_stump)) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
|
|
126
|
+
| **FFI** | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
|
|
127
|
+
| **Java** ([jtreesitter](https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter)) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
|
|
128
|
+
| **Prism** | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
|
|
129
|
+
| **Psych** | ✅ | ✅ | ✅ | YAML parsing, stdlib |
|
|
130
|
+
| **Citrus** | ✅ | ✅ | ✅ | Pure Ruby, no native dependencies |
|
|
131
|
+
| **Commonmarker** | ✅ | ❌ | ❓ | Rust extension for Markdown |
|
|
132
|
+
| **Markly** | ✅ | ❌ | ❓ | C extension for Markdown |
|
|
124
133
|
|
|
125
|
-
|
|
134
|
+
**Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
|
|
135
|
+
|
|
136
|
+
**Why some backends don't work on certain platforms**:
|
|
137
|
+
|
|
138
|
+
- **JRuby**: Runs on the JVM; cannot load native C/Rust extensions (`.so` files)
|
|
139
|
+
- **TruffleRuby**: Has C API emulation via Sulong/LLVM, but it doesn't expose all MRI internals that native extensions require (e.g., `RBasic.flags`, `rb_gc_writebarrier`)
|
|
140
|
+
- **FFI on TruffleRuby**: TruffleRuby's FFI implementation doesn't support returning structs by value, which tree-sitter's C API requires
|
|
141
|
+
### Architecture: tree\_haver + ast-merge
|
|
142
|
+
|
|
143
|
+
The `*-merge` gem family is built on a two-layer architecture:
|
|
126
144
|
|
|
127
|
-
|
|
145
|
+
#### Layer 1: tree\_haver (Parsing Foundation)
|
|
128
146
|
|
|
129
|
-
-
|
|
130
|
-
- **Shared Modules**: `FileAnalysisBase`, `FileAnalyzable`, `MergerConfig`, `DebugLogger`
|
|
131
|
-
- **Freeze Block Support**: Configurable marker patterns for multiple comment syntaxes (preserve sections during merge)
|
|
132
|
-
- **Node Typing System**: `NodeTyping` for canonical node type identification across different parsers
|
|
133
|
-
- **Conflict Resolution**: `ConflictResolverBase` with pluggable strategies
|
|
134
|
-
- **Error Classes**: `ParseError`, `TemplateParseError`, `DestinationParseError`
|
|
135
|
-
- **Region Detection**: `RegionDetectorBase`, `FencedCodeBlockDetector` for text-based analysis
|
|
136
|
-
- **RSpec Shared Examples**: Test helpers for implementing new merge gems
|
|
147
|
+
[tree\_haver](https://github.com/kettle-rb/tree_haver) provides cross-Ruby parsing capabilities:
|
|
137
148
|
|
|
149
|
+
- **Universal Backend Support**: Automatically selects the best parsing backend for your Ruby implementation (MRI, JRuby, TruffleRuby)
|
|
150
|
+
- **10 Backend Options**: MRI C extensions, Rust bindings, FFI, Java (JRuby), language-specific parsers (Prism, Psych, Commonmarker, Markly), and pure Ruby fallback (Citrus)
|
|
151
|
+
- **Unified API**: Write parsing code once, run on any Ruby implementation
|
|
152
|
+
- **Grammar Discovery**: Built-in `GrammarFinder` for platform-aware grammar library discovery
|
|
153
|
+
- **Thread-Safe**: Language registry with thread-safe caching
|
|
154
|
+
#### Layer 2: ast-merge (Merge Infrastructure)
|
|
155
|
+
|
|
156
|
+
Ast::Merge builds on tree\_haver to provide:
|
|
157
|
+
|
|
158
|
+
- **Base Classes**: `FreezeNode`, `MergeResult` base classes with unified constructors
|
|
159
|
+
- **Shared Modules**: `FileAnalysisBase`, `FileAnalyzable`, `MergerConfig`, `DebugLogger`
|
|
160
|
+
- **Freeze Block Support**: Configurable marker patterns for multiple comment syntaxes (preserve sections during merge)
|
|
161
|
+
- **Node Typing System**: `NodeTyping` for canonical node type identification across different parsers
|
|
162
|
+
- **Conflict Resolution**: `ConflictResolverBase` with pluggable strategies
|
|
163
|
+
- **Error Classes**: `ParseError`, `TemplateParseError`, `DestinationParseError`
|
|
164
|
+
- **Region Detection**: `RegionDetectorBase`, `FencedCodeBlockDetector` for text-based analysis
|
|
165
|
+
- **RSpec Shared Examples**: Test helpers for implementing new merge gems
|
|
138
166
|
### Creating a New Merge Gem
|
|
139
167
|
|
|
140
|
-
```ruby
|
|
168
|
+
``` ruby
|
|
141
169
|
require "ast/merge"
|
|
142
170
|
|
|
143
171
|
module MyFormat
|
|
144
172
|
module Merge
|
|
145
173
|
# Inherit from base classes and pass **options for forward compatibility
|
|
146
|
-
|
|
174
|
+
|
|
147
175
|
class SmartMerger < Ast::Merge::SmartMergerBase
|
|
148
176
|
DEFAULT_FREEZE_TOKEN = "myformat-merge"
|
|
149
|
-
|
|
177
|
+
|
|
150
178
|
def initialize(template, dest, my_custom_option: nil, **options)
|
|
151
179
|
@my_custom_option = my_custom_option
|
|
152
180
|
super(template, dest, **options)
|
|
153
181
|
end
|
|
154
|
-
|
|
182
|
+
|
|
155
183
|
protected
|
|
156
|
-
|
|
184
|
+
|
|
157
185
|
def analysis_class
|
|
158
186
|
FileAnalysis
|
|
159
187
|
end
|
|
160
|
-
|
|
188
|
+
|
|
161
189
|
def default_freeze_token
|
|
162
190
|
DEFAULT_FREEZE_TOKEN
|
|
163
191
|
end
|
|
164
|
-
|
|
192
|
+
|
|
165
193
|
def perform_merge
|
|
166
194
|
# Implement format-specific merge logic
|
|
167
195
|
# Returns a MergeResult
|
|
168
196
|
end
|
|
169
197
|
end
|
|
170
|
-
|
|
198
|
+
|
|
171
199
|
class FileAnalysis
|
|
172
200
|
include Ast::Merge::FileAnalyzable
|
|
173
|
-
|
|
201
|
+
|
|
174
202
|
def initialize(source, freeze_token: nil, signature_generator: nil, **options)
|
|
175
203
|
@source = source
|
|
176
204
|
@freeze_token = freeze_token
|
|
177
205
|
@signature_generator = signature_generator
|
|
178
206
|
# Process source...
|
|
179
207
|
end
|
|
180
|
-
|
|
208
|
+
|
|
181
209
|
def compute_node_signature(node)
|
|
182
210
|
# Return signature array for node matching
|
|
183
211
|
end
|
|
184
212
|
end
|
|
185
|
-
|
|
213
|
+
|
|
186
214
|
class ConflictResolver < Ast::Merge::ConflictResolverBase
|
|
187
|
-
def initialize(template_analysis, dest_analysis, preference: :destination,
|
|
215
|
+
def initialize(template_analysis, dest_analysis, preference: :destination,
|
|
188
216
|
add_template_only_nodes: false, match_refiner: nil, **options)
|
|
189
217
|
super(
|
|
190
218
|
strategy: :batch, # or :node, :boundary
|
|
@@ -196,30 +224,30 @@ module MyFormat
|
|
|
196
224
|
**options
|
|
197
225
|
)
|
|
198
226
|
end
|
|
199
|
-
|
|
227
|
+
|
|
200
228
|
protected
|
|
201
|
-
|
|
229
|
+
|
|
202
230
|
def resolve_batch(result)
|
|
203
231
|
# Implement batch resolution logic
|
|
204
232
|
end
|
|
205
233
|
end
|
|
206
|
-
|
|
234
|
+
|
|
207
235
|
class MergeResult < Ast::Merge::MergeResultBase
|
|
208
236
|
def initialize(**options)
|
|
209
237
|
super(**options)
|
|
210
238
|
@statistics = { merged_count: 0 }
|
|
211
239
|
end
|
|
212
|
-
|
|
240
|
+
|
|
213
241
|
def to_my_format
|
|
214
242
|
to_s
|
|
215
243
|
end
|
|
216
244
|
end
|
|
217
|
-
|
|
245
|
+
|
|
218
246
|
class MatchRefiner < Ast::Merge::MatchRefinerBase
|
|
219
247
|
def initialize(threshold: 0.7, node_types: nil, **options)
|
|
220
248
|
super(threshold: threshold, node_types: node_types, **options)
|
|
221
249
|
end
|
|
222
|
-
|
|
250
|
+
|
|
223
251
|
def similarity(template_node, dest_node)
|
|
224
252
|
# Return similarity score between 0.0 and 1.0
|
|
225
253
|
end
|
|
@@ -231,7 +259,7 @@ end
|
|
|
231
259
|
### Base Classes Reference
|
|
232
260
|
|
|
233
261
|
| Base Class | Purpose | Key Methods to Implement |
|
|
234
|
-
|
|
262
|
+
| --- | --- | --- |
|
|
235
263
|
| `SmartMergerBase` | Main merge orchestration | `analysis_class`, `perform_merge` |
|
|
236
264
|
| `ConflictResolverBase` | Resolve node conflicts | `resolve_batch` or `resolve_node_pair` |
|
|
237
265
|
| `MergeResultBase` | Track merge results | `to_s`, format-specific output |
|
|
@@ -243,7 +271,7 @@ end
|
|
|
243
271
|
|
|
244
272
|
`Ast::Merge::ContentMatchRefiner` is a built-in match refiner for fuzzy text content matching using Levenshtein distance. Unlike signature-based matching which requires exact content hashes, this refiner allows matching nodes with similar (but not identical) content.
|
|
245
273
|
|
|
246
|
-
```ruby
|
|
274
|
+
``` ruby
|
|
247
275
|
# Basic usage - match nodes with 70% similarity
|
|
248
276
|
refiner = Ast::Merge::ContentMatchRefiner.new(threshold: 0.7)
|
|
249
277
|
|
|
@@ -279,17 +307,16 @@ merger = MyFormat::SmartMerger.new(
|
|
|
279
307
|
```
|
|
280
308
|
|
|
281
309
|
This is particularly useful for:
|
|
282
|
-
- Paragraphs with minor edits (typos, rewording)
|
|
283
|
-
- Headings with slight changes
|
|
284
|
-
- Comments with updated text
|
|
285
|
-
- Any text-based node that may have been slightly modified
|
|
286
|
-
|
|
310
|
+
- Paragraphs with minor edits (typos, rewording)
|
|
311
|
+
- Headings with slight changes
|
|
312
|
+
- Comments with updated text
|
|
313
|
+
- Any text-based node that may have been slightly modified
|
|
287
314
|
### Namespace Reference
|
|
288
315
|
|
|
289
316
|
The `Ast::Merge` module is organized into several namespaces, each with detailed documentation:
|
|
290
317
|
|
|
291
318
|
| Namespace | Purpose | Documentation |
|
|
292
|
-
|
|
319
|
+
| --- | --- | --- |
|
|
293
320
|
| `Ast::Merge::Detector` | Region detection and merging | [lib/ast/merge/detector/README.md](lib/ast/merge/detector/README.md) |
|
|
294
321
|
| `Ast::Merge::Recipe` | YAML-based merge recipes | [lib/ast/merge/recipe/README.md](lib/ast/merge/recipe/README.md) |
|
|
295
322
|
| `Ast::Merge::Comment` | Comment parsing and representation | [lib/ast/merge/comment/README.md](lib/ast/merge/comment/README.md) |
|
|
@@ -298,46 +325,45 @@ The `Ast::Merge` module is organized into several namespaces, each with detailed
|
|
|
298
325
|
|
|
299
326
|
**Key Classes by Namespace:**
|
|
300
327
|
|
|
301
|
-
- **Detector**: `Region`, `Base`, `Mergeable`, `FencedCodeBlock`, `YamlFrontmatter`, `TomlFrontmatter`
|
|
302
|
-
- **Recipe**: `Config`, `Runner`, `ScriptLoader`
|
|
303
|
-
- **Comment**: `Line`, `Block`, `Empty`, `Parser`, `Style`
|
|
304
|
-
- **Text**: `SmartMerger`, `FileAnalysis`, `LineNode`, `WordNode`, `Section`
|
|
305
|
-
- **RSpec**: Shared examples and dependency tags for testing `*-merge` implementations
|
|
306
|
-
|
|
328
|
+
- **Detector**: `Region`, `Base`, `Mergeable`, `FencedCodeBlock`, `YamlFrontmatter`, `TomlFrontmatter`
|
|
329
|
+
- **Recipe**: `Config`, `Runner`, `ScriptLoader`
|
|
330
|
+
- **Comment**: `Line`, `Block`, `Empty`, `Parser`, `Style`
|
|
331
|
+
- **Text**: `SmartMerger`, `FileAnalysis`, `LineNode`, `WordNode`, `Section`
|
|
332
|
+
- **RSpec**: Shared examples and dependency tags for testing `*-merge` implementations
|
|
307
333
|
## 💡 Info you can shake a stick at
|
|
308
334
|
|
|
309
|
-
| Tokens to Remember
|
|
310
|
-
|
|
311
|
-
| Works with JRuby
|
|
312
|
-
| Works with Truffle Ruby | [![Truffle Ruby 23.1 Compat]
|
|
313
|
-
| Works with MRI Ruby 3
|
|
314
|
-
| Support & Community
|
|
315
|
-
| Source
|
|
316
|
-
| Documentation
|
|
317
|
-
| Compliance
|
|
318
|
-
| Style
|
|
319
|
-
| Maintainer 🎖️
|
|
320
|
-
| `...` 💖
|
|
335
|
+
| Tokens to Remember | [](https://bestgems.org/gems/ast-merge) [](https://github.com/kettle-rb/ast-merge) |
|
|
336
|
+
| --- | --- |
|
|
337
|
+
| Works with JRuby | [](https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/heads.yml) |
|
|
338
|
+
| Works with Truffle Ruby | [](https://github.com/kettle-rb/ast-merge/actions/workflows/truffle.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml) |
|
|
339
|
+
| Works with MRI Ruby 3 | [](https://github.com/kettle-rb/ast-merge/actions/workflows/supported.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/supported.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml) [](https://github.com/kettle-rb/ast-merge/actions/workflows/heads.yml) |
|
|
340
|
+
| Support & Community | [](https://app.daily.dev/squads/rubyfriends) [](https://discord.gg/3qme4XHNKN) [](https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share) [](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github) |
|
|
341
|
+
| Source | [](https://gitlab.com/kettle-rb/ast-merge/) [](https://codeberg.org/kettle-rb/ast-merge) [](https://github.com/kettle-rb/ast-merge) [](https://www.youtube.com/watch?v=dQw4w9WgXcQ) |
|
|
342
|
+
| Documentation | [](http://rubydoc.info/gems/ast-merge) [](https://ast-merge.galtzo.com) [](http://www.railsbling.com/tags/ast-merge) [](https://gitlab.com/kettle-rb/ast-merge/-/wikis/home) [](https://github.com/kettle-rb/ast-merge/wiki) |
|
|
343
|
+
| Compliance | [](https://opensource.org/licenses/MIT) [](https://dev.to/galtzo/how-to-check-license-compatibility-41h0) [](https://www.ilo.org/declaration/lang--en/index.htm) [](SECURITY.md) [](CODE_OF_CONDUCT.md) [](https://semver.org/spec/v2.0.0.html) |
|
|
344
|
+
| Style | [](https://github.com/rubocop-lts/rubocop-lts) [](https://keepachangelog.com/en/1.0.0/) [](https://gitmoji.dev) [](https://github.com/appraisal-rb/appraisal2) |
|
|
345
|
+
| Maintainer 🎖️ | [](http://www.linkedin.com/in/peterboling) [](https://ruby.social/@galtzo) [](https://bsky.app/profile/galtzo.com) [](http://www.railsbling.com/contact) [](https://dev.to/galtzo) |
|
|
346
|
+
| `...` 💖 | [](https://wellfound.com/u/peter-boling) [](https://www.crunchbase.com/person/peter-boling) [](https://linktr.ee/galtzo) [](https://about.me/peter.boling) [🧊](https://codeberg.org/pboling) [🐙](https://github.org/pboling) [🛖](https://sr.ht/~galtzo/) [🧪](https://gitlab.com/pboling) |
|
|
321
347
|
|
|
322
348
|
### Compatibility
|
|
323
349
|
|
|
324
350
|
Compatible with MRI Ruby 3.2.0+, and concordant releases of JRuby, and TruffleRuby.
|
|
325
351
|
|
|
326
|
-
| 🚚
|
|
327
|
-
|
|
328
|
-
| 👟 Check it out
|
|
352
|
+
| 🚚 *Amazing* test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
|
|
353
|
+
| --- | --- |
|
|
354
|
+
| 👟 Check it out\! | ✨ [github.com/appraisal-rb/appraisal2](https://github.com/appraisal-rb/appraisal2) ✨ |
|
|
329
355
|
|
|
330
356
|
### Federated DVCS
|
|
331
357
|
|
|
332
358
|
<details markdown="1">
|
|
333
359
|
<summary>Find this repo on federated forges (Coming soon!)</summary>
|
|
334
360
|
|
|
335
|
-
| Federated [DVCS]
|
|
336
|
-
|
|
337
|
-
| 🧪 [kettle-rb/ast-merge on GitLab]
|
|
338
|
-
| 🧊 [kettle-rb/ast-merge on CodeBerg]
|
|
339
|
-
| 🐙 [kettle-rb/ast-merge on GitHub]
|
|
340
|
-
| 🎮️ [Discord Server]
|
|
361
|
+
| Federated [DVCS](https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/) Repository | Status | Issues | PRs | Wiki | CI | Discussions |
|
|
362
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
363
|
+
| 🧪 [kettle-rb/ast-merge on GitLab](https://gitlab.com/kettle-rb/ast-merge/) | The Truth | [💚](https://gitlab.com/kettle-rb/ast-merge/-/issues) | [💚](https://gitlab.com/kettle-rb/ast-merge/-/merge_requests) | [💚](https://gitlab.com/kettle-rb/ast-merge/-/wikis/home) | 🐭 Tiny Matrix | ➖ |
|
|
364
|
+
| 🧊 [kettle-rb/ast-merge on CodeBerg](https://codeberg.org/kettle-rb/ast-merge) | An Ethical Mirror ([Donate](https://donate.codeberg.org/)) | [💚](https://codeberg.org/kettle-rb/ast-merge/issues) | [💚](https://codeberg.org/kettle-rb/ast-merge/pulls) | ➖ | ⭕️ No Matrix | ➖ |
|
|
365
|
+
| 🐙 [kettle-rb/ast-merge on GitHub](https://github.com/kettle-rb/ast-merge) | Another Mirror | [💚](https://github.com/kettle-rb/ast-merge/issues) | [💚](https://github.com/kettle-rb/ast-merge/pulls) | [💚](https://github.com/kettle-rb/ast-merge/wiki) | 💯 Full Matrix | [💚](https://github.com/kettle-rb/ast-merge/discussions) |
|
|
366
|
+
| 🎮️ [Discord Server](https://discord.gg/3qme4XHNKN) | [](https://discord.gg/3qme4XHNKN) | [Let's](https://discord.gg/3qme4XHNKN) | [talk](https://discord.gg/3qme4XHNKN) | [about](https://discord.gg/3qme4XHNKN) | [this](https://discord.gg/3qme4XHNKN) | [library\!](https://discord.gg/3qme4XHNKN) |
|
|
341
367
|
|
|
342
368
|
</details>
|
|
343
369
|
|
|
@@ -352,31 +378,29 @@ Available as part of the Tidelift Subscription.
|
|
|
352
378
|
|
|
353
379
|
The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
|
|
354
380
|
|
|
355
|
-
[![Get help from me on Tidelift]
|
|
356
|
-
|
|
357
|
-
- 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies
|
|
358
|
-
- 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
|
|
359
|
-
- 💡Tidelift pays maintainers to maintain the software you depend on!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers
|
|
381
|
+
[](https://tidelift.com/subscription/pkg/rubygems-ast-merge?utm_source=rubygems-ast-merge&utm_medium=referral&utm_campaign=readme)
|
|
360
382
|
|
|
383
|
+
- 💡Subscribe for support guarantees covering *all* your FLOSS dependencies
|
|
384
|
+
- 💡Tidelift is part of [Sonar](https://blog.tidelift.com/tidelift-joins-sonar)
|
|
385
|
+
- 💡Tidelift pays maintainers to maintain the software you depend on\!<br/>📊`@`Pointy Haired Boss: An [enterprise support](https://tidelift.com/subscription/pkg/rubygems-ast-merge?utm_source=rubygems-ast-merge&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
|
|
361
386
|
Alternatively:
|
|
362
387
|
|
|
363
|
-
- [![Live Chat on Discord]
|
|
364
|
-
- [![Get help from me on Upwork]
|
|
365
|
-
- [![Get help from me on Codementor]
|
|
366
|
-
|
|
388
|
+
- [](https://discord.gg/3qme4XHNKN)
|
|
389
|
+
- [](https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share)
|
|
390
|
+
- [](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github)
|
|
367
391
|
</details>
|
|
368
392
|
|
|
369
393
|
## ✨ Installation
|
|
370
394
|
|
|
371
395
|
Install the gem and add to the application's Gemfile by executing:
|
|
372
396
|
|
|
373
|
-
```console
|
|
397
|
+
``` console
|
|
374
398
|
bundle add ast-merge
|
|
375
399
|
```
|
|
376
400
|
|
|
377
401
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
378
402
|
|
|
379
|
-
```console
|
|
403
|
+
``` console
|
|
380
404
|
gem install ast-merge
|
|
381
405
|
```
|
|
382
406
|
|
|
@@ -385,19 +409,19 @@ gem install ast-merge
|
|
|
385
409
|
<details markdown="1">
|
|
386
410
|
<summary>For Medium or High Security Installations</summary>
|
|
387
411
|
|
|
388
|
-
This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512]
|
|
389
|
-
[
|
|
412
|
+
This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512](https://gitlab.com/kettle-rb/ast-merge/-/tree/main/checksums) checksums by
|
|
413
|
+
[stone\_checksums](https://github.com/galtzo-floss/stone_checksums). Be sure the gem you install hasn’t been tampered with
|
|
390
414
|
by following the instructions below.
|
|
391
415
|
|
|
392
416
|
Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:
|
|
393
417
|
|
|
394
|
-
```console
|
|
418
|
+
``` console
|
|
395
419
|
gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem)
|
|
396
420
|
```
|
|
397
421
|
|
|
398
422
|
You only need to do that once. Then proceed to install with:
|
|
399
423
|
|
|
400
|
-
```console
|
|
424
|
+
``` console
|
|
401
425
|
gem install ast-merge -P HighSecurity
|
|
402
426
|
```
|
|
403
427
|
|
|
@@ -405,7 +429,7 @@ The `HighSecurity` trust profile will verify signed gems, and not allow the inst
|
|
|
405
429
|
|
|
406
430
|
If you want to up your security game full-time:
|
|
407
431
|
|
|
408
|
-
```console
|
|
432
|
+
``` console
|
|
409
433
|
bundle config set --global trust-policy MediumSecurity
|
|
410
434
|
```
|
|
411
435
|
|
|
@@ -424,7 +448,7 @@ Each implementation (like `prism-merge`, `psych-merge`, etc.) has its own SmartM
|
|
|
424
448
|
|
|
425
449
|
All SmartMerger implementations share these configuration options:
|
|
426
450
|
|
|
427
|
-
```ruby
|
|
451
|
+
``` ruby
|
|
428
452
|
merger = SomeFormat::Merge::SmartMerger.new(
|
|
429
453
|
template,
|
|
430
454
|
destination,
|
|
@@ -441,23 +465,21 @@ merger = SomeFormat::Merge::SmartMerger.new(
|
|
|
441
465
|
|
|
442
466
|
Control which source wins when both files have the same structural element:
|
|
443
467
|
|
|
444
|
-
- **`:template`** - Template values replace destination values
|
|
445
|
-
- **`:destination`** (default) - Destination values are preserved
|
|
446
|
-
- **Hash** - Per-node-type preference (see Advanced Configuration)
|
|
447
|
-
|
|
468
|
+
- **`:template`** - Template values replace destination values
|
|
469
|
+
- **`:destination`** (default) - Destination values are preserved
|
|
470
|
+
- **Hash** - Per-node-type preference (see Advanced Configuration)
|
|
448
471
|
### Template-Only Nodes
|
|
449
472
|
|
|
450
473
|
Control whether to add nodes that only exist in the template:
|
|
451
474
|
|
|
452
|
-
- **`true`** - Add all template-only nodes
|
|
453
|
-
- **`false`** (default) - Skip template-only nodes
|
|
454
|
-
- **Callable** - Filter which template-only nodes to add
|
|
455
|
-
|
|
475
|
+
- **`true`** - Add all template-only nodes
|
|
476
|
+
- **`false`** (default) - Skip template-only nodes
|
|
477
|
+
- **Callable** - Filter which template-only nodes to add
|
|
456
478
|
#### Callable Filter
|
|
457
479
|
|
|
458
480
|
When you need fine-grained control over which template-only nodes are added, pass a callable (Proc/Lambda) that receives `(node, entry)` and returns truthy to add or falsey to skip:
|
|
459
481
|
|
|
460
|
-
```ruby
|
|
482
|
+
``` ruby
|
|
461
483
|
# Only add nodes with gem_family signatures
|
|
462
484
|
merger = SomeFormat::Merge::SmartMerger.new(
|
|
463
485
|
template,
|
|
@@ -480,16 +502,15 @@ merger = Markly::Merge::SmartMerger.new(
|
|
|
480
502
|
```
|
|
481
503
|
|
|
482
504
|
The `entry` hash contains:
|
|
483
|
-
- `:template_node` - The node being considered for addition
|
|
484
|
-
- `:signature` - The node's signature (Array or other value)
|
|
485
|
-
- `:template_index` - Index in the template statements
|
|
486
|
-
- `:dest_index` - Always `nil` for template-only nodes
|
|
487
|
-
|
|
505
|
+
- `:template_node` - The node being considered for addition
|
|
506
|
+
- `:signature` - The node's signature (Array or other value)
|
|
507
|
+
- `:template_index` - Index in the template statements
|
|
508
|
+
- `:dest_index` - Always `nil` for template-only nodes
|
|
488
509
|
## 🔧 Basic Usage
|
|
489
510
|
|
|
490
511
|
### Using Shared Examples in Tests
|
|
491
512
|
|
|
492
|
-
```ruby
|
|
513
|
+
``` ruby
|
|
493
514
|
# spec/spec_helper.rb
|
|
494
515
|
require "ast/merge/rspec/shared_examples"
|
|
495
516
|
|
|
@@ -509,12 +530,11 @@ end
|
|
|
509
530
|
|
|
510
531
|
### Available Shared Examples
|
|
511
532
|
|
|
512
|
-
- `"Ast::Merge::FreezeNode"` - Tests for FreezeNode implementations
|
|
513
|
-
- `"Ast::Merge::MergeResult"` - Tests for MergeResult implementations
|
|
514
|
-
- `"Ast::Merge::DebugLogger"` - Tests for DebugLogger implementations
|
|
515
|
-
- `"Ast::Merge::FileAnalysisBase"` - Tests for FileAnalysis implementations
|
|
516
|
-
- `"Ast::Merge::MergerConfig"` - Tests for SmartMerger implementations
|
|
517
|
-
|
|
533
|
+
- `"Ast::Merge::FreezeNode"` - Tests for FreezeNode implementations
|
|
534
|
+
- `"Ast::Merge::MergeResult"` - Tests for MergeResult implementations
|
|
535
|
+
- `"Ast::Merge::DebugLogger"` - Tests for DebugLogger implementations
|
|
536
|
+
- `"Ast::Merge::FileAnalysisBase"` - Tests for FileAnalysis implementations
|
|
537
|
+
- `"Ast::Merge::MergerConfig"` - Tests for SmartMerger implementations
|
|
518
538
|
## 🎛️ Advanced Configuration
|
|
519
539
|
|
|
520
540
|
### Freeze Blocks
|
|
@@ -524,11 +544,12 @@ to preserve content exactly as-is, preventing any changes from the template.
|
|
|
524
544
|
This is useful for hand-edited customizations you never want overwritten.
|
|
525
545
|
|
|
526
546
|
A freeze block consists of:
|
|
527
|
-
- A **start marker** comment (e.g., `# mytoken:freeze`)
|
|
528
|
-
- The protected content
|
|
529
|
-
- An **end marker** comment (e.g., `# mytoken:unfreeze`)
|
|
547
|
+
- A **start marker** comment (e.g., `# mytoken:freeze`)
|
|
548
|
+
- The protected content
|
|
549
|
+
- An **end marker** comment (e.g., `# mytoken:unfreeze`)
|
|
530
550
|
|
|
531
|
-
|
|
551
|
+
<!-- end list -->
|
|
552
|
+
``` ruby
|
|
532
553
|
# In a Ruby file with prism-merge:
|
|
533
554
|
class MyApp
|
|
534
555
|
# prism-merge:freeze
|
|
@@ -550,16 +571,16 @@ Different file formats use different comment syntaxes. The merge tools detect fr
|
|
|
550
571
|
using the appropriate pattern for each format:
|
|
551
572
|
|
|
552
573
|
| Pattern Type | Start Marker | End Marker | Languages |
|
|
553
|
-
|
|
574
|
+
| --- | --- | --- | --- |
|
|
554
575
|
| `:hash_comment` | `# token:freeze` | `# token:unfreeze` | Ruby, Python, YAML, Bash, Shell |
|
|
555
576
|
| `:html_comment` | `<!-- token:freeze -->` | `<!-- token:unfreeze -->` | HTML, XML, Markdown |
|
|
556
|
-
| `:c_style_line` | `// token:freeze` | `// token:unfreeze` | C (C99+), C++, JavaScript, TypeScript, Java, C
|
|
557
|
-
| `:c_style_block` | `/* token:freeze */` | `/* token:unfreeze */` | C, C++, JavaScript, TypeScript, Java, C
|
|
577
|
+
| `:c_style_line` | `// token:freeze` | `// token:unfreeze` | C (C99+), C++, JavaScript, TypeScript, Java, C\#, Go, Rust, Swift, Kotlin, PHP, JSONC |
|
|
578
|
+
| `:c_style_block` | `/* token:freeze */` | `/* token:unfreeze */` | C, C++, JavaScript, TypeScript, Java, C\#, Go, Rust, Swift, Kotlin, PHP, CSS |
|
|
558
579
|
|
|
559
|
-
| 📍 NOTE
|
|
560
|
-
|
|
561
|
-
| CSS only supports block comments (`/* */`), not line comments.
|
|
562
|
-
| JSON does not support comments; use JSONC for JSON with comments.
|
|
580
|
+
| 📍 NOTE |
|
|
581
|
+
| --- |
|
|
582
|
+
| CSS only supports block comments (`/* */`), not line comments. |
|
|
583
|
+
| JSON does not support comments; use JSONC for JSON with comments. |
|
|
563
584
|
|
|
564
585
|
### Per-Node-Type Preference with `node_typing`
|
|
565
586
|
|
|
@@ -569,15 +590,18 @@ preferences for different types of nodes (e.g., prefer template for linter confi
|
|
|
569
590
|
|
|
570
591
|
#### How It Works
|
|
571
592
|
|
|
572
|
-
1.
|
|
573
|
-
|
|
574
|
-
|
|
593
|
+
1. **Define a `node_typing`**: A Hash mapping node type symbols to callables that receive a node and return either:
|
|
594
|
+
|
|
595
|
+
- The original node (no special handling)
|
|
596
|
+
- A wrapped node with a `merge_type` attribute (via `Ast::Merge::NodeTyping::Wrapper`)
|
|
575
597
|
|
|
576
|
-
2.
|
|
577
|
-
- `:default` key for the fallback preference
|
|
578
|
-
- Custom keys matching the `merge_type` values from your `node_typing`
|
|
598
|
+
2. **Use a Hash-based preference**: Instead of a simple `:destination` or `:template` Symbol, pass a Hash with:
|
|
579
599
|
|
|
580
|
-
|
|
600
|
+
- `:default` key for the fallback preference
|
|
601
|
+
- Custom keys matching the `merge_type` values from your `node_typing`
|
|
602
|
+
|
|
603
|
+
<!-- end list -->
|
|
604
|
+
``` ruby
|
|
581
605
|
# Example: Prefer template for lint gem configs, destination for everything else
|
|
582
606
|
node_typing = {
|
|
583
607
|
call_node: ->(node) {
|
|
@@ -605,7 +629,7 @@ merger = Prism::Merge::SmartMerger.new(
|
|
|
605
629
|
The `Ast::Merge::NodeTyping::Wrapper` class wraps an AST node and adds a `merge_type` attribute.
|
|
606
630
|
It delegates all method calls to the wrapped node, so it can be used transparently in place of the original node.
|
|
607
631
|
|
|
608
|
-
```ruby
|
|
632
|
+
``` ruby
|
|
609
633
|
# Wrap a node with a custom merge_type
|
|
610
634
|
wrapped = Ast::Merge::NodeTyping::Wrapper.new(original_node, :special_config)
|
|
611
635
|
wrapped.merge_type # => :special_config
|
|
@@ -615,7 +639,7 @@ wrapped.location # => delegates to original_node.location
|
|
|
615
639
|
|
|
616
640
|
#### NodeTyping Utility Methods
|
|
617
641
|
|
|
618
|
-
```ruby
|
|
642
|
+
``` ruby
|
|
619
643
|
# Process a node through the node_typing configuration
|
|
620
644
|
processed = Ast::Merge::NodeTyping.process(node, node_typing_config)
|
|
621
645
|
|
|
@@ -629,12 +653,12 @@ Ast::Merge::NodeTyping.merge_type_for(node) # => Symbol or nil
|
|
|
629
653
|
Ast::Merge::NodeTyping.unwrap(wrapped_node) # => original_node
|
|
630
654
|
```
|
|
631
655
|
|
|
632
|
-
### Hash-Based Preference (without
|
|
656
|
+
### Hash-Based Preference (without node\_typing)
|
|
633
657
|
|
|
634
658
|
Even without `node_typing`, you can use a Hash-based preference to set a default
|
|
635
659
|
and document your intention for future per-type customization:
|
|
636
660
|
|
|
637
|
-
```ruby
|
|
661
|
+
``` ruby
|
|
638
662
|
# Simple Hash preference (functionally equivalent to preference: :destination)
|
|
639
663
|
merger = MyMerger.new(
|
|
640
664
|
template_content,
|
|
@@ -647,7 +671,7 @@ merger = MyMerger.new(
|
|
|
647
671
|
|
|
648
672
|
The `MergerConfig` class provides factory methods that support all options:
|
|
649
673
|
|
|
650
|
-
```ruby
|
|
674
|
+
``` ruby
|
|
651
675
|
# Create config preferring destination
|
|
652
676
|
config = Ast::Merge::MergerConfig.destination_wins(
|
|
653
677
|
freeze_token: "my-freeze",
|
|
@@ -668,42 +692,42 @@ config = Ast::Merge::MergerConfig.template_wins(
|
|
|
668
692
|
While kettle-rb tools are free software and will always be, the project would benefit immensely from some funding.
|
|
669
693
|
Raising a monthly budget of... "dollars" would make the project more sustainable.
|
|
670
694
|
|
|
671
|
-
We welcome both individual and corporate sponsors
|
|
695
|
+
We welcome both individual and corporate sponsors\! We also offer a
|
|
672
696
|
wide array of funding channels to account for your preferences
|
|
673
|
-
(although currently [Open Collective]
|
|
697
|
+
(although currently [Open Collective](https://opencollective.com/kettle-rb) is our preferred funding platform).
|
|
674
698
|
|
|
675
699
|
**If you're working in a company that's making significant use of kettle-rb tools we'd
|
|
676
700
|
appreciate it if you suggest to your company to become a kettle-rb sponsor.**
|
|
677
701
|
|
|
678
702
|
You can support the development of kettle-rb tools via
|
|
679
|
-
[GitHub Sponsors]
|
|
680
|
-
[Liberapay]
|
|
681
|
-
[PayPal]
|
|
682
|
-
[Open Collective]
|
|
683
|
-
and [Tidelift]
|
|
684
|
-
|
|
685
|
-
| 📍 NOTE
|
|
686
|
-
|
|
703
|
+
[GitHub Sponsors](https://github.com/sponsors/pboling),
|
|
704
|
+
[Liberapay](https://liberapay.com/pboling/donate),
|
|
705
|
+
[PayPal](https://www.paypal.com/paypalme/peterboling),
|
|
706
|
+
[Open Collective](https://opencollective.com/kettle-rb)
|
|
707
|
+
and [Tidelift](https://tidelift.com/subscription/pkg/rubygems-ast-merge?utm_source=rubygems-ast-merge&utm_medium=referral&utm_campaign=readme).
|
|
708
|
+
|
|
709
|
+
| 📍 NOTE |
|
|
710
|
+
| --- |
|
|
687
711
|
| If doing a sponsorship in the form of donation is problematic for your company <br/> from an accounting standpoint, we'd recommend the use of Tidelift, <br/> where you can get a support-like subscription instead. |
|
|
688
712
|
|
|
689
713
|
### Open Collective for Individuals
|
|
690
714
|
|
|
691
|
-
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/kettle-rb#backer)]
|
|
715
|
+
Support us with a monthly donation and help us continue our activities. \[[Become a backer](https://opencollective.com/kettle-rb#backer)\]
|
|
692
716
|
|
|
693
|
-
NOTE: [kettle-readme-backers]
|
|
717
|
+
NOTE: [kettle-readme-backers](https://github.com/kettle-rb/ast-merge/blob/main/exe/kettle-readme-backers) updates this list every day, automatically.
|
|
694
718
|
|
|
695
719
|
<!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
|
|
696
|
-
No backers yet. Be the first
|
|
720
|
+
No backers yet. Be the first\!
|
|
697
721
|
<!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
|
|
698
722
|
|
|
699
723
|
### Open Collective for Organizations
|
|
700
724
|
|
|
701
|
-
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/kettle-rb#sponsor)]
|
|
725
|
+
Become a sponsor and get your logo on our README on GitHub with a link to your site. \[[Become a sponsor](https://opencollective.com/kettle-rb#sponsor)\]
|
|
702
726
|
|
|
703
|
-
NOTE: [kettle-readme-backers]
|
|
727
|
+
NOTE: [kettle-readme-backers](https://github.com/kettle-rb/ast-merge/blob/main/exe/kettle-readme-backers) updates this list every day, automatically.
|
|
704
728
|
|
|
705
729
|
<!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
|
|
706
|
-
No sponsors yet. Be the first
|
|
730
|
+
No sponsors yet. Be the first\!
|
|
707
731
|
<!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
|
|
708
732
|
|
|
709
733
|
[kettle-readme-backers]: https://github.com/kettle-rb/ast-merge/blob/main/exe/kettle-readme-backers
|
|
@@ -714,50 +738,50 @@ I’m driven by a passion to foster a thriving open-source community – a space
|
|
|
714
738
|
|
|
715
739
|
If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
|
|
716
740
|
|
|
717
|
-
I’m developing a new library, [
|
|
741
|
+
I’m developing a new library, [floss\_funding](https://github.com/galtzo-floss/floss_funding), designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
|
|
718
742
|
|
|
719
|
-
**[Floss-Funding.dev]
|
|
743
|
+
**[Floss-Funding.dev](https://floss-funding.dev): 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
|
|
720
744
|
|
|
721
|
-
[![OpenCollective Backers]
|
|
745
|
+
[](https://opencollective.com/kettle-rb#backer) [](https://opencollective.com/kettle-rb#sponsor) [](https://github.com/sponsors/pboling) [](https://liberapay.com/pboling/donate) [](https://www.paypal.com/paypalme/peterboling) [](https://www.buymeacoffee.com/pboling) [](https://polar.sh/pboling) [](https://ko-fi.com/O5O86SNP4) [](https://patreon.com/galtzo)
|
|
722
746
|
|
|
723
747
|
## 🔐 Security
|
|
724
748
|
|
|
725
|
-
See [SECURITY.md]
|
|
749
|
+
See [SECURITY.md](SECURITY.md).
|
|
726
750
|
|
|
727
751
|
## 🤝 Contributing
|
|
728
752
|
|
|
729
753
|
If you need some ideas of where to help, you could work on adding more code coverage,
|
|
730
|
-
or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues]
|
|
754
|
+
or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues](https://github.com/kettle-rb/ast-merge/issues), or [PRs](https://github.com/kettle-rb/ast-merge/pulls),
|
|
731
755
|
or use the gem and think about how it could be better.
|
|
732
756
|
|
|
733
|
-
We [![Keep A Changelog]
|
|
757
|
+
We [](https://keepachangelog.com/en/1.0.0/) so if you make changes, remember to update it.
|
|
734
758
|
|
|
735
|
-
See [CONTRIBUTING.md]
|
|
759
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for more detailed instructions.
|
|
736
760
|
|
|
737
761
|
### 🚀 Release Instructions
|
|
738
762
|
|
|
739
|
-
See [CONTRIBUTING.md]
|
|
763
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
740
764
|
|
|
741
765
|
### Code Coverage
|
|
742
766
|
|
|
743
|
-
[![Coverage Graph]
|
|
767
|
+
[](https://codecov.io/gh/kettle-rb/ast-merge)
|
|
744
768
|
|
|
745
|
-
[![Coveralls Test Coverage]
|
|
769
|
+
[](https://coveralls.io/github/kettle-rb/ast-merge?branch=main)
|
|
746
770
|
|
|
747
|
-
[![QLTY Test Coverage]
|
|
771
|
+
[](https://qlty.sh/gh/kettle-rb/projects/ast-merge/metrics/code?sort=coverageRating)
|
|
748
772
|
|
|
749
773
|
### 🪇 Code of Conduct
|
|
750
774
|
|
|
751
775
|
Everyone interacting with this project's codebases, issue trackers,
|
|
752
|
-
chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1]
|
|
776
|
+
chat rooms and mailing lists agrees to follow the [](CODE_OF_CONDUCT.md).
|
|
753
777
|
|
|
754
778
|
## 🌈 Contributors
|
|
755
779
|
|
|
756
|
-
[![Contributors]
|
|
780
|
+
[](https://github.com/kettle-rb/ast-merge/graphs/contributors)
|
|
757
781
|
|
|
758
|
-
Made with [contributors-img]
|
|
782
|
+
Made with [contributors-img](https://contrib.rocks).
|
|
759
783
|
|
|
760
|
-
Also see GitLab Contributors:
|
|
784
|
+
Also see GitLab Contributors: <https://gitlab.com/kettle-rb/ast-merge/-/graphs/main>
|
|
761
785
|
|
|
762
786
|
<details>
|
|
763
787
|
<summary>⭐️ Star History</summary>
|
|
@@ -774,24 +798,24 @@ Also see GitLab Contributors: [https://gitlab.com/kettle-rb/ast-merge/-/graphs/m
|
|
|
774
798
|
|
|
775
799
|
## 📌 Versioning
|
|
776
800
|
|
|
777
|
-
This Library adheres to [![Semantic Versioning 2.0.0]
|
|
801
|
+
This Library adheres to [](https://semver.org/spec/v2.0.0.html).
|
|
778
802
|
Violations of this scheme should be reported as bugs.
|
|
779
803
|
Specifically, if a minor or patch version is released that breaks backward compatibility,
|
|
780
804
|
a new version should be immediately released that restores compatibility.
|
|
781
805
|
Breaking changes to the public API will only be introduced with new major versions.
|
|
782
806
|
|
|
783
807
|
> dropping support for a platform is both obviously and objectively a breaking change <br/>
|
|
784
|
-
|
|
808
|
+
> —Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716](https://github.com/semver/semver/issues/716#issuecomment-869336139)
|
|
785
809
|
|
|
786
|
-
I understand that policy doesn't work universally ("exceptions to every rule
|
|
810
|
+
I understand that policy doesn't work universally ("exceptions to every rule\!"),
|
|
787
811
|
but it is the policy here.
|
|
788
812
|
As such, in many cases it is good to specify a dependency on this library using
|
|
789
|
-
the [Pessimistic Version Constraint]
|
|
813
|
+
the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/#pessimistic-version-constraint) with two digits of precision.
|
|
790
814
|
|
|
791
815
|
For example:
|
|
792
816
|
|
|
793
|
-
```ruby
|
|
794
|
-
spec.add_dependency("ast-merge", "~>
|
|
817
|
+
``` ruby
|
|
818
|
+
spec.add_dependency("ast-merge", "~> 2.0", ">= 2.0.1") # ruby >= 3.2.0
|
|
795
819
|
```
|
|
796
820
|
|
|
797
821
|
<details markdown="1">
|
|
@@ -803,17 +827,16 @@ is a *breaking change* to an API, and for that reason the bike shedding is endle
|
|
|
803
827
|
To get a better understanding of how SemVer is intended to work over a project's lifetime,
|
|
804
828
|
read this article from the creator of SemVer:
|
|
805
829
|
|
|
806
|
-
- ["Major Version Numbers are Not Sacred"]
|
|
807
|
-
|
|
830
|
+
- ["Major Version Numbers are Not Sacred"](https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html)
|
|
808
831
|
</details>
|
|
809
832
|
|
|
810
|
-
See [CHANGELOG.md]
|
|
833
|
+
See [CHANGELOG.md](CHANGELOG.md) for a list of releases.
|
|
811
834
|
|
|
812
835
|
## 📄 License
|
|
813
836
|
|
|
814
837
|
The gem is available as open source under the terms of
|
|
815
|
-
the [MIT License]
|
|
816
|
-
See [LICENSE.txt]
|
|
838
|
+
the [MIT License](LICENSE.txt) [](https://opensource.org/licenses/MIT).
|
|
839
|
+
See [LICENSE.txt](LICENSE.txt) for the official [Copyright Notice](https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year).
|
|
817
840
|
|
|
818
841
|
### © Copyright
|
|
819
842
|
|
|
@@ -840,11 +863,11 @@ Please consider sponsoring me or the project.
|
|
|
840
863
|
|
|
841
864
|
To join the community or get help 👇️ Join the Discord.
|
|
842
865
|
|
|
843
|
-
[![Live Chat on Discord]
|
|
866
|
+
[](https://discord.gg/3qme4XHNKN)
|
|
844
867
|
|
|
845
|
-
To say "thanks
|
|
868
|
+
To say "thanks\!" ☝️ Join the Discord or 👇️ send money.
|
|
846
869
|
|
|
847
|
-
[![Sponsor kettle-rb/ast-merge on Open Source Collective]
|
|
870
|
+
[](https://opencollective.com/kettle-rb) 💌 [](https://github.com/sponsors/pboling) 💌 [](https://liberapay.com/pboling/donate) 💌 [](https://www.paypal.com/paypalme/peterboling)
|
|
848
871
|
|
|
849
872
|
### Please give the project a star ⭐ ♥.
|
|
850
873
|
|
|
@@ -1009,7 +1032,7 @@ Thanks for RTFM. ☺️
|
|
|
1009
1032
|
[📌gitmoji]: https://gitmoji.dev
|
|
1010
1033
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1011
1034
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1012
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.
|
|
1035
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.272-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1013
1036
|
[🔐security]: SECURITY.md
|
|
1014
1037
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1015
1038
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -70,16 +70,15 @@ module Ast
|
|
|
70
70
|
#
|
|
71
71
|
# @note Shared examples require +silent_stream+ and +rspec-stubbed_env+ gems.
|
|
72
72
|
module DebugLogger
|
|
73
|
-
# Benchmark is optional - gracefully degrade if not available
|
|
74
|
-
#
|
|
73
|
+
# Benchmark is optional - gracefully degrade if not available.
|
|
74
|
+
# As of Ruby 4.0, benchmark is a bundled gem (not default), so it may not be available.
|
|
75
|
+
# We attempt to require it at load time and set a flag for later use.
|
|
75
76
|
BENCHMARK_AVAILABLE = begin
|
|
76
|
-
|
|
77
|
+
require "benchmark"
|
|
77
78
|
true
|
|
78
79
|
rescue LoadError
|
|
79
|
-
#
|
|
80
|
-
# Platform-specific: benchmark is part of Ruby stdlib, LoadError only on unusual Ruby builds
|
|
80
|
+
# benchmark gem not available (Ruby 4.0+ without explicit dependency, or unusual Ruby builds)
|
|
81
81
|
false
|
|
82
|
-
# :nocov:
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
class << self
|
data/lib/ast/merge/version.rb
CHANGED
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ast-merge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -63,20 +63,20 @@ dependencies:
|
|
|
63
63
|
requirements:
|
|
64
64
|
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '3.
|
|
66
|
+
version: '3.2'
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 3.
|
|
69
|
+
version: 3.2.0
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
73
|
requirements:
|
|
74
74
|
- - "~>"
|
|
75
75
|
- !ruby/object:Gem::Version
|
|
76
|
-
version: '3.
|
|
76
|
+
version: '3.2'
|
|
77
77
|
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: 3.
|
|
79
|
+
version: 3.2.0
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: kettle-dev
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -352,10 +352,10 @@ licenses:
|
|
|
352
352
|
- MIT
|
|
353
353
|
metadata:
|
|
354
354
|
homepage_uri: https://ast-merge.galtzo.com/
|
|
355
|
-
source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v2.0.
|
|
356
|
-
changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v2.0.
|
|
355
|
+
source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v2.0.3
|
|
356
|
+
changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v2.0.3/CHANGELOG.md
|
|
357
357
|
bug_tracker_uri: https://github.com/kettle-rb/ast-merge/issues
|
|
358
|
-
documentation_uri: https://www.rubydoc.info/gems/ast-merge/2.0.
|
|
358
|
+
documentation_uri: https://www.rubydoc.info/gems/ast-merge/2.0.3
|
|
359
359
|
funding_uri: https://github.com/sponsors/pboling
|
|
360
360
|
wiki_uri: https://github.com/kettle-rb/ast-merge/wiki
|
|
361
361
|
news_uri: https://www.railsbling.com/tags/ast-merge
|
metadata.gz.sig
CHANGED
|
Binary file
|