prism-merge 1.1.3 → 1.1.4
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 +28 -1
- data/README.md +64 -4
- data/lib/prism/merge/conflict_resolver.rb +0 -22
- data/lib/prism/merge/debug_logger.rb +3 -1
- data/lib/prism/merge/file_analysis.rb +88 -14
- data/lib/prism/merge/smart_merger.rb +18 -7
- data/lib/prism/merge/version.rb +1 -1
- data/sig/prism/merge.rbs +15 -2
- data.tar.gz.sig +3 -2
- metadata +4 -4
- 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: fd04362b7a3dcb058e1ddf48683905944ba9cd11bf2a3e16ffc977a286cbf707
|
|
4
|
+
data.tar.gz: 9cee5de60fd6c3d1e28737135d5003cf6c7604780906efed2c2b861a9559e46c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ba7baf55a05e4512c81a5ac78aa0c26eab48576de335659dbffd46fd9b235197132eb85f056591a8b7d7e4bbffa50142c5027ced44db2aca9e320de613ca977
|
|
7
|
+
data.tar.gz: 495250d6a19a1f0d5893afa191e9ecf1bc8e499f66a401efa93cf6f8efc045d207ceefebf7d889bfe97cbe844f441da6867bec0405aefe303a0bd6974e067703
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,31 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.1.4] - 2025-12-04
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.1.4][1.1.4t]
|
|
36
|
+
- COVERAGE: 98.26% -- 902/918 lines in 9 files
|
|
37
|
+
- BRANCH COVERAGE: 87.59% -- 381/435 branches in 9 files
|
|
38
|
+
- 100.00% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- **Custom signature generator fallthrough support**: Custom signature generators can now return a `Prism::Node` or `FreezeNode` to fall through to the default signature computation. This allows custom generators to only override specific node types while delegating others to the built-in logic. Previously, returning `nil` was the only way to skip custom handling, but that prevented proper matching for unhandled node types.
|
|
43
|
+
- **Variable assignment node signatures**: Added signature support for all variable write node types:
|
|
44
|
+
- `LocalVariableWriteNode` → `[:local_var, name]`
|
|
45
|
+
- `InstanceVariableWriteNode` → `[:ivar, name]`
|
|
46
|
+
- `ClassVariableWriteNode` → `[:cvar, name]`
|
|
47
|
+
- `GlobalVariableWriteNode` → `[:gvar, name]`
|
|
48
|
+
- `MultiWriteNode` → `[:multi_write, [target_names]]`
|
|
49
|
+
|
|
50
|
+
### Removed
|
|
51
|
+
|
|
52
|
+
- Removed pre-prism code in `ConflictResolver` that compared template node line numbers against destination freeze block line numbers (cross-file line comparison makes no sense)
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **Fixed template-only nodes not being added when destination has freeze blocks**: When `add_template_only_nodes: true`, template nodes with no matching signature in destination were incorrectly skipped if the destination contained freeze blocks. The bug was caused by comparing template node line numbers against destination freeze block line numbers, which is a meaningless cross-file comparison. Template-only nodes are now correctly added regardless of freeze block presence.
|
|
57
|
+
|
|
33
58
|
## [1.1.3] - 2025-12-04
|
|
34
59
|
|
|
35
60
|
- TAG: [v1.1.3][1.1.3t]
|
|
@@ -182,7 +207,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
182
207
|
|
|
183
208
|
- Initial release
|
|
184
209
|
|
|
185
|
-
[Unreleased]: https://github.com/kettle-rb/prism-merge/compare/v1.1.
|
|
210
|
+
[Unreleased]: https://github.com/kettle-rb/prism-merge/compare/v1.1.4...HEAD
|
|
211
|
+
[1.1.4]: https://github.com/kettle-rb/prism-merge/compare/v1.1.3...v1.1.4
|
|
212
|
+
[1.1.4t]: https://github.com/kettle-rb/prism-merge/releases/tag/v1.1.4
|
|
186
213
|
[1.1.3]: https://github.com/kettle-rb/prism-merge/compare/v1.1.2...v1.1.3
|
|
187
214
|
[1.1.3t]: https://github.com/kettle-rb/prism-merge/releases/tag/v1.1.3
|
|
188
215
|
[1.1.2]: https://github.com/kettle-rb/prism-merge/compare/v1.1.1...v1.1.2
|
data/README.md
CHANGED
|
@@ -338,6 +338,12 @@ By default, Prism::Merge uses intelligent structural signatures to match nodes.
|
|
|
338
338
|
| `ModuleNode` | `[:module, name]` | Modules match by name |
|
|
339
339
|
| `SingletonClassNode` | `[:singleton_class, expr]` | Singleton classes match by expression (`class << self`) |
|
|
340
340
|
| `ConstantWriteNode` | `[:const, name]` | Constants match by name only (not value) |
|
|
341
|
+
| `ConstantPathWriteNode` | `[:const, target]` | Namespaced constants match by full path |
|
|
342
|
+
| `LocalVariableWriteNode` | `[:local_var, name]` | Local variables match by name |
|
|
343
|
+
| `InstanceVariableWriteNode` | `[:ivar, name]` | Instance variables match by name |
|
|
344
|
+
| `ClassVariableWriteNode` | `[:cvar, name]` | Class variables match by name |
|
|
345
|
+
| `GlobalVariableWriteNode` | `[:gvar, name]` | Global variables match by name |
|
|
346
|
+
| `MultiWriteNode` | `[:multi_write, targets]` | Multiple assignment matches by target names |
|
|
341
347
|
| `IfNode` / `UnlessNode` | `[:if, condition]` | Conditionals match by condition expression |
|
|
342
348
|
| `CaseNode` | `[:case, predicate]` | Case statements match by the expression being switched |
|
|
343
349
|
| `CaseMatchNode` | `[:case_match, predicate]` | Pattern matching cases match by expression |
|
|
@@ -364,7 +370,15 @@ The following node types support **recursive body merging**, where nested conten
|
|
|
364
370
|
|
|
365
371
|
#### Custom Signature Generator
|
|
366
372
|
|
|
367
|
-
You can provide a custom signature generator to control
|
|
373
|
+
You can provide a custom signature generator to control how nodes are matched between template and destination files. The signature generator is a callable (lambda/proc) that receives a `Prism::Node` (or `FreezeNode`) and returns one of three types of values:
|
|
374
|
+
|
|
375
|
+
| Return Value | Behavior |
|
|
376
|
+
|--------------|----------|
|
|
377
|
+
| **Array** (e.g., `[:gem, "foo"]`) | Used as the node's signature for matching. Nodes with identical signatures are considered matches. |
|
|
378
|
+
| **`nil`** | The node gets no signature and won't be matched by signature. Useful for nodes you want to skip or handle specially. |
|
|
379
|
+
| **`Prism::Node` or `FreezeNode`** | Falls through to the default signature computation using the returned node. Return the original node unchanged for simple fallthrough, or return a modified node to influence default matching. |
|
|
380
|
+
|
|
381
|
+
##### Basic Example
|
|
368
382
|
|
|
369
383
|
```ruby
|
|
370
384
|
signature_generator = lambda do |node|
|
|
@@ -379,10 +393,36 @@ signature_generator = lambda do |node|
|
|
|
379
393
|
# Match classes by name
|
|
380
394
|
[:class, node.constant_path.slice]
|
|
381
395
|
else
|
|
382
|
-
# Default matching
|
|
383
|
-
|
|
396
|
+
# Default matching - return node to fall through
|
|
397
|
+
node
|
|
384
398
|
end
|
|
385
399
|
end
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
##### Fallthrough Example (Recommended Pattern)
|
|
403
|
+
|
|
404
|
+
The fallthrough pattern allows you to customize only specific node types while delegating everything else to the built-in signature logic:
|
|
405
|
+
|
|
406
|
+
```ruby
|
|
407
|
+
signature_generator = ->(node) {
|
|
408
|
+
# Only customize CallNode signatures for specific methods
|
|
409
|
+
if node.is_a?(Prism::CallNode)
|
|
410
|
+
# source() calls - match by method name only (there's usually just one)
|
|
411
|
+
return [:source] if node.name == :source
|
|
412
|
+
|
|
413
|
+
# gem() calls - match by gem name (first argument)
|
|
414
|
+
if node.name == :gem
|
|
415
|
+
first_arg = node.arguments&.arguments&.first
|
|
416
|
+
if first_arg.is_a?(Prism::StringNode)
|
|
417
|
+
return [:gem, first_arg.unescaped]
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Return the node to fall through to default signature computation
|
|
423
|
+
# This preserves correct handling for FreezeNodes, classes, modules, etc.
|
|
424
|
+
node
|
|
425
|
+
}
|
|
386
426
|
|
|
387
427
|
merger = Prism::Merge::SmartMerger.new(
|
|
388
428
|
template_content,
|
|
@@ -393,6 +433,26 @@ merger = Prism::Merge::SmartMerger.new(
|
|
|
393
433
|
)
|
|
394
434
|
```
|
|
395
435
|
|
|
436
|
+
##### Why Fallthrough Matters
|
|
437
|
+
|
|
438
|
+
When you provide a custom signature generator, it's called for **all** node types, including internal types like `FreezeNode`. If your generator returns `nil` for node types it doesn't recognize, those nodes won't be matched properly:
|
|
439
|
+
|
|
440
|
+
```ruby
|
|
441
|
+
# ❌ Bad: Returns nil for unrecognized nodes
|
|
442
|
+
signature_generator = ->(node) {
|
|
443
|
+
return unless node.is_a?(Prism::CallNode) # FreezeNodes get nil!
|
|
444
|
+
[:call, node.name]
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
# ✅ Good: Falls through for unrecognized nodes
|
|
448
|
+
signature_generator = ->(node) {
|
|
449
|
+
if node.is_a?(Prism::CallNode)
|
|
450
|
+
return [:call, node.name]
|
|
451
|
+
end
|
|
452
|
+
node # FreezeNodes and others use default signatures
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
396
456
|
### Freeze Blocks
|
|
397
457
|
|
|
398
458
|
Protect sections in the destination file from being overwritten by the template using freeze markers.
|
|
@@ -1134,7 +1194,7 @@ Thanks for RTFM. ☺️
|
|
|
1134
1194
|
[📌gitmoji]: https://gitmoji.dev
|
|
1135
1195
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1136
1196
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1137
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
1197
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.918-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1138
1198
|
[🔐security]: SECURITY.md
|
|
1139
1199
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1140
1200
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -168,16 +168,6 @@ module Prism
|
|
|
168
168
|
source_analysis: @dest_analysis,
|
|
169
169
|
)
|
|
170
170
|
matched_dest_indices << freeze_node_info[:index]
|
|
171
|
-
|
|
172
|
-
# Mark any template nodes within this freeze block range as processed
|
|
173
|
-
freeze_range = freeze_node_info[:line_range]
|
|
174
|
-
template_nodes.each do |t_node_info|
|
|
175
|
-
if freeze_range.cover?(t_node_info[:line_range].begin) &&
|
|
176
|
-
freeze_range.cover?(t_node_info[:line_range].end)
|
|
177
|
-
# Template node is inside freeze block, skip it
|
|
178
|
-
# (we'll handle this by checking if it overlaps with a freeze block)
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
171
|
end
|
|
182
172
|
end
|
|
183
173
|
|
|
@@ -207,18 +197,6 @@ module Prism
|
|
|
207
197
|
node_start = t_node_info[:line_range].begin
|
|
208
198
|
node_end = t_node_info[:line_range].end
|
|
209
199
|
|
|
210
|
-
# Skip template nodes that overlap with destination freeze blocks
|
|
211
|
-
overlaps_freeze = dest_freeze_nodes.any? do |freeze_info|
|
|
212
|
-
freeze_range = freeze_info[:line_range]
|
|
213
|
-
node_start.between?(freeze_range.begin, freeze_range.end) ||
|
|
214
|
-
node_end.between?(freeze_range.begin, freeze_range.end)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
if overlaps_freeze
|
|
218
|
-
current_line = node_end + 1
|
|
219
|
-
next
|
|
220
|
-
end
|
|
221
|
-
|
|
222
200
|
# Check if this node will be matched or is template-only
|
|
223
201
|
sig = t_node_info[:signature]
|
|
224
202
|
is_matched = dest_sig_map[sig]&.any?
|
|
@@ -8,7 +8,9 @@ module Prism
|
|
|
8
8
|
# rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
9
9
|
module DebugLogger
|
|
10
10
|
@logger = nil
|
|
11
|
+
# :nocov:
|
|
11
12
|
@enabled = ENV.fetch("PRISM_MERGE_DEBUG", "false").casecmp?("true")
|
|
13
|
+
# :nocov:
|
|
12
14
|
|
|
13
15
|
class << self
|
|
14
16
|
attr_reader :enabled
|
|
@@ -17,7 +19,7 @@ module Prism
|
|
|
17
19
|
# @param message [String] The message to log
|
|
18
20
|
# @param context [Hash] Optional context information
|
|
19
21
|
def debug(message, context = {})
|
|
20
|
-
return unless
|
|
22
|
+
return unless enabled
|
|
21
23
|
|
|
22
24
|
if logger_available?
|
|
23
25
|
ensure_logger
|
|
@@ -89,12 +89,38 @@ module Prism
|
|
|
89
89
|
generate_signature(statements[index])
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# Generate signature for a node
|
|
93
|
-
#
|
|
92
|
+
# Generate signature for a node.
|
|
93
|
+
#
|
|
94
|
+
# If a custom signature_generator is provided, it is called first. The custom
|
|
95
|
+
# generator can return:
|
|
96
|
+
# - An array signature (e.g., `[:gem, "foo"]`) - used as the signature
|
|
97
|
+
# - `nil` - the node gets no signature (won't be matched by signature)
|
|
98
|
+
# - A `Prism::Node` or `FreezeNode` - falls through to default computation using
|
|
99
|
+
# the returned node. This allows the custom generator to optionally modify the
|
|
100
|
+
# node before default processing, or simply return the original node unchanged
|
|
101
|
+
# for fallthrough.
|
|
102
|
+
#
|
|
103
|
+
# @param node [Prism::Node, FreezeNode] Node to generate signature for
|
|
94
104
|
# @return [Array, nil] Signature array
|
|
105
|
+
#
|
|
106
|
+
# @example Custom generator with fallthrough
|
|
107
|
+
# signature_generator = ->(node) {
|
|
108
|
+
# case node
|
|
109
|
+
# when Prism::CallNode
|
|
110
|
+
# return [:gem, node.arguments.arguments.first.unescaped] if node.name == :gem
|
|
111
|
+
# end
|
|
112
|
+
# node # Return original node for default signature computation
|
|
113
|
+
# }
|
|
95
114
|
def generate_signature(node)
|
|
96
115
|
result = if @signature_generator
|
|
97
|
-
@signature_generator.call(node)
|
|
116
|
+
custom_result = @signature_generator.call(node)
|
|
117
|
+
if custom_result.is_a?(Prism::Node) || custom_result.is_a?(FreezeNode)
|
|
118
|
+
# Custom generator returned a node - use default computation on it
|
|
119
|
+
compute_node_signature(custom_result)
|
|
120
|
+
else
|
|
121
|
+
# Custom result is either an array signature or nil
|
|
122
|
+
custom_result
|
|
123
|
+
end
|
|
98
124
|
else
|
|
99
125
|
compute_node_signature(node)
|
|
100
126
|
end
|
|
@@ -145,6 +171,7 @@ module Prism
|
|
|
145
171
|
# so we need to explicitly require it
|
|
146
172
|
def attach_comments_safely!
|
|
147
173
|
@parse_result.attach_comments!
|
|
174
|
+
# :nocov:
|
|
148
175
|
rescue NameError => e
|
|
149
176
|
if e.message.include?("Comments")
|
|
150
177
|
# On JRuby, the Comments class needs to be explicitly required
|
|
@@ -153,6 +180,7 @@ module Prism
|
|
|
153
180
|
else
|
|
154
181
|
raise
|
|
155
182
|
end
|
|
183
|
+
# :nocov:
|
|
156
184
|
end
|
|
157
185
|
|
|
158
186
|
# Extract all nodes: freeze blocks + statements outside freeze blocks
|
|
@@ -342,6 +370,13 @@ module Prism
|
|
|
342
370
|
# - `ConstantWriteNode` → `[:const, name]`
|
|
343
371
|
# - `ConstantPathWriteNode` → `[:const, target]`
|
|
344
372
|
#
|
|
373
|
+
# **Variable Assignments:**
|
|
374
|
+
# - `LocalVariableWriteNode` → `[:local_var, name]`
|
|
375
|
+
# - `InstanceVariableWriteNode` → `[:ivar, name]`
|
|
376
|
+
# - `ClassVariableWriteNode` → `[:cvar, name]`
|
|
377
|
+
# - `GlobalVariableWriteNode` → `[:gvar, name]`
|
|
378
|
+
# - `MultiWriteNode` → `[:multi_write, [target_names]]`
|
|
379
|
+
#
|
|
345
380
|
# **Conditionals:**
|
|
346
381
|
# - `IfNode` → `[:if, condition_source]`
|
|
347
382
|
# - `UnlessNode` → `[:unless, condition_source]`
|
|
@@ -437,15 +472,25 @@ module Prism
|
|
|
437
472
|
when Prism::DefNode
|
|
438
473
|
# Extract parameter names from ParametersNode
|
|
439
474
|
params = if node.parameters
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
475
|
+
# Handle forwarding parameters (def foo(...)) specially
|
|
476
|
+
if node.parameters.is_a?(Prism::ForwardingParameterNode)
|
|
477
|
+
[:forwarding]
|
|
478
|
+
else
|
|
479
|
+
param_names = []
|
|
480
|
+
param_names.concat(node.parameters.requireds.map(&:name)) if node.parameters.requireds
|
|
481
|
+
param_names.concat(node.parameters.optionals.map(&:name)) if node.parameters.optionals
|
|
482
|
+
param_names << node.parameters.rest.name if node.parameters.rest&.respond_to?(:name)
|
|
483
|
+
param_names.concat(node.parameters.posts.map(&:name)) if node.parameters.posts
|
|
484
|
+
param_names.concat(node.parameters.keywords.map(&:name)) if node.parameters.keywords
|
|
485
|
+
# keyword_rest can be KeywordRestParameterNode (has name) or ForwardingParameterNode (no name)
|
|
486
|
+
if node.parameters.keyword_rest&.respond_to?(:name)
|
|
487
|
+
param_names << node.parameters.keyword_rest.name
|
|
488
|
+
elsif node.parameters.keyword_rest.is_a?(Prism::ForwardingParameterNode)
|
|
489
|
+
param_names << :forwarding
|
|
490
|
+
end
|
|
491
|
+
param_names << node.parameters.block.name if node.parameters.block
|
|
492
|
+
param_names
|
|
493
|
+
end
|
|
449
494
|
else
|
|
450
495
|
[]
|
|
451
496
|
end
|
|
@@ -466,8 +511,37 @@ module Prism
|
|
|
466
511
|
[:singleton_class, expr]
|
|
467
512
|
|
|
468
513
|
# === Constants ===
|
|
469
|
-
when Prism::ConstantWriteNode
|
|
470
|
-
[:const, node.name
|
|
514
|
+
when Prism::ConstantWriteNode
|
|
515
|
+
[:const, node.name]
|
|
516
|
+
when Prism::ConstantPathWriteNode
|
|
517
|
+
[:const, node.target.slice]
|
|
518
|
+
|
|
519
|
+
# === Variable assignments ===
|
|
520
|
+
when Prism::LocalVariableWriteNode
|
|
521
|
+
[:local_var, node.name]
|
|
522
|
+
when Prism::InstanceVariableWriteNode
|
|
523
|
+
[:ivar, node.name]
|
|
524
|
+
when Prism::ClassVariableWriteNode
|
|
525
|
+
[:cvar, node.name]
|
|
526
|
+
when Prism::GlobalVariableWriteNode
|
|
527
|
+
[:gvar, node.name]
|
|
528
|
+
when Prism::MultiWriteNode
|
|
529
|
+
# Multiple assignment: a, b = 1, 2
|
|
530
|
+
targets = node.lefts.map do |target|
|
|
531
|
+
case target
|
|
532
|
+
when Prism::LocalVariableTargetNode
|
|
533
|
+
target.name
|
|
534
|
+
when Prism::InstanceVariableTargetNode
|
|
535
|
+
target.name
|
|
536
|
+
when Prism::ClassVariableTargetNode
|
|
537
|
+
target.name
|
|
538
|
+
when Prism::GlobalVariableTargetNode
|
|
539
|
+
target.name
|
|
540
|
+
else
|
|
541
|
+
target.slice
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
[:multi_write, targets]
|
|
471
545
|
|
|
472
546
|
# === Conditionals ===
|
|
473
547
|
when Prism::IfNode, Prism::UnlessNode
|
|
@@ -68,9 +68,17 @@ module Prism
|
|
|
68
68
|
# @param dest_content [String] Destination Ruby source code
|
|
69
69
|
#
|
|
70
70
|
# @param signature_generator [Proc, nil] Optional proc to generate custom node signatures.
|
|
71
|
-
# The proc receives a Prism node and should return
|
|
71
|
+
# The proc receives a Prism node (or FreezeNode) and should return one of:
|
|
72
|
+
# - An array representing the node's signature (e.g., `[:gem, "foo"]`)
|
|
73
|
+
# - `nil` to indicate the node should have no signature (won't be matched)
|
|
74
|
+
# - A `Prism::Node` or `FreezeNode` to fall through to default signature computation
|
|
75
|
+
# using that node. This allows custom generators to only override specific node
|
|
76
|
+
# types while delegating others to the built-in logic. Return the original node
|
|
77
|
+
# unchanged for simple fallthrough, or return a modified node to influence
|
|
78
|
+
# default matching.
|
|
79
|
+
#
|
|
72
80
|
# Nodes with identical signatures are considered matches during merge.
|
|
73
|
-
# Default: Uses {FileAnalysis#
|
|
81
|
+
# Default: Uses {FileAnalysis#compute_node_signature} which matches:
|
|
74
82
|
# - Conditionals by condition only (not body)
|
|
75
83
|
# - Assignments by name only (not value)
|
|
76
84
|
# - Method calls by name and args (not block)
|
|
@@ -122,14 +130,17 @@ module Prism
|
|
|
122
130
|
# add_template_only_nodes: false
|
|
123
131
|
# )
|
|
124
132
|
#
|
|
125
|
-
# @example Custom signature matching
|
|
133
|
+
# @example Custom signature matching with fallthrough
|
|
126
134
|
# sig_gen = lambda do |node|
|
|
127
135
|
# case node
|
|
128
|
-
# when Prism::
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
136
|
+
# when Prism::CallNode
|
|
137
|
+
# # Custom handling for gem calls - match by gem name
|
|
138
|
+
# if node.name == :gem
|
|
139
|
+
# return [:gem, node.arguments&.arguments&.first&.unescaped]
|
|
140
|
+
# end
|
|
132
141
|
# end
|
|
142
|
+
# # Return the node to fall through to default signature computation
|
|
143
|
+
# node
|
|
133
144
|
# end
|
|
134
145
|
#
|
|
135
146
|
# merger = SmartMerger.new(
|
data/lib/prism/merge/version.rb
CHANGED
data/sig/prism/merge.rbs
CHANGED
|
@@ -107,7 +107,11 @@ module Prism
|
|
|
107
107
|
attr_reader statements: Array[untyped]
|
|
108
108
|
attr_reader freeze_blocks: Array[freeze_block]
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
# Custom signature generator return types:
|
|
111
|
+
# - Array[untyped]: Used as the node's signature for matching
|
|
112
|
+
# - nil: Node gets no signature (won't be matched by signature)
|
|
113
|
+
# - Prism::Node or FreezeNode: Falls through to default signature computation
|
|
114
|
+
def initialize: (String content, ?signature_generator: (^(untyped) -> (Array[untyped] | untyped | nil))?, ?freeze_token: String?) -> void
|
|
111
115
|
|
|
112
116
|
def valid?: () -> bool
|
|
113
117
|
|
|
@@ -158,6 +162,11 @@ module Prism
|
|
|
158
162
|
# [:module, String] - module definitions
|
|
159
163
|
# [:singleton_class, String] - singleton class definitions
|
|
160
164
|
# [:const, Symbol | String] - constant assignments
|
|
165
|
+
# [:local_var, Symbol] - local variable assignments
|
|
166
|
+
# [:ivar, Symbol] - instance variable assignments
|
|
167
|
+
# [:cvar, Symbol] - class variable assignments
|
|
168
|
+
# [:gvar, Symbol] - global variable assignments
|
|
169
|
+
# [:multi_write, Array[Symbol | String]] - multiple assignment
|
|
161
170
|
# [:if, String] | [:unless, String] - conditionals
|
|
162
171
|
# [:case, String] | [:case_match, String] - case statements
|
|
163
172
|
# [:while, String] | [:until, String] - while/until loops
|
|
@@ -318,10 +327,14 @@ module Prism
|
|
|
318
327
|
statistics: Hash[Symbol, Integer]
|
|
319
328
|
}
|
|
320
329
|
|
|
330
|
+
# Custom signature generator return types:
|
|
331
|
+
# - Array[untyped]: Used as the node's signature for matching
|
|
332
|
+
# - nil: Node gets no signature (won't be matched by signature)
|
|
333
|
+
# - Prism::Node or FreezeNode: Falls through to default signature computation
|
|
321
334
|
def initialize: (
|
|
322
335
|
String template_content,
|
|
323
336
|
String dest_content,
|
|
324
|
-
?signature_generator: (^(untyped) -> Array[untyped])?,
|
|
337
|
+
?signature_generator: (^(untyped) -> (Array[untyped] | untyped | nil))?,
|
|
325
338
|
?signature_match_preference: Symbol,
|
|
326
339
|
?add_template_only_nodes: bool,
|
|
327
340
|
?freeze_token: String?,
|
data.tar.gz.sig
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
��'���ӾP�5t#9ġ_�$`�Z:JH)�M� ���Te���4��͓���V�zLY9�`�)�{�MAȴN2�o�Y�[�n���X
|
|
2
|
+
-CR�jf�a������
|
|
3
|
+
�ܐ_S]VƑ����bq�D�}�J��<����B��U�Z�=�VBb��]y�ӟP�sN�Xn���y��d� ���g]�������}���]�1&���"rX������;����M��X{�t)E���)Ά�IM�^P�̓G'v���pKzQW �m�r��bYr#���iGZ_��o���Նݼ1��OJ s��#��ʳ`_��q��Y�w���'ӮW��D9S|���>��Huu]�-�C��d/3dR�A�i#���s�s��2p�
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prism-merge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -265,10 +265,10 @@ licenses:
|
|
|
265
265
|
- MIT
|
|
266
266
|
metadata:
|
|
267
267
|
homepage_uri: https://prism-merge.galtzo.com/
|
|
268
|
-
source_code_uri: https://github.com/kettle-rb/prism-merge/tree/v1.1.
|
|
269
|
-
changelog_uri: https://github.com/kettle-rb/prism-merge/blob/v1.1.
|
|
268
|
+
source_code_uri: https://github.com/kettle-rb/prism-merge/tree/v1.1.4
|
|
269
|
+
changelog_uri: https://github.com/kettle-rb/prism-merge/blob/v1.1.4/CHANGELOG.md
|
|
270
270
|
bug_tracker_uri: https://github.com/kettle-rb/prism-merge/issues
|
|
271
|
-
documentation_uri: https://www.rubydoc.info/gems/prism-merge/1.1.
|
|
271
|
+
documentation_uri: https://www.rubydoc.info/gems/prism-merge/1.1.4
|
|
272
272
|
funding_uri: https://github.com/sponsors/pboling
|
|
273
273
|
wiki_uri: https://github.com/kettle-rb/prism-merge/wiki
|
|
274
274
|
news_uri: https://www.railsbling.com/tags/prism-merge
|
metadata.gz.sig
CHANGED
|
Binary file
|