prism-merge 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +17 -1
- data/README.md +1 -1
- data/lib/prism/merge/file_aligner.rb +44 -6
- data/lib/prism/merge/file_analysis.rb +35 -8
- data/lib/prism/merge/smart_merger.rb +14 -3
- data/lib/prism/merge/version.rb +1 -1
- data.tar.gz.sig +0 -0
- 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: 421f226a53add89905b9160c76fd3f18130bb7ab65a9b2da410e29237d0ee0d9
|
|
4
|
+
data.tar.gz: 35a0b3a827749be34717d4e9c58842ae589fc8a0028c50175465fd99504f0bc7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31948037aa1cf05744a46649d0bddc73ed2920714c1c08d6f00c0bb337da25e479c77f80594b1a9ee0e2f32d16b58dcbd41c3dc1449408170d90095ef579081b
|
|
7
|
+
data.tar.gz: 8bdcc61811f3b70e338c3a34a1e2953b5eb81dd8186180c47d277dffe6cc5f944504ac2833c5d1f431593e9f221c726ed977b6120d43db7a744c6c1e07be06bf
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,20 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.1.6] - 2025-12-05
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.1.6][1.1.6t]
|
|
36
|
+
- COVERAGE: 98.31% -- 929/945 lines in 9 files
|
|
37
|
+
- BRANCH COVERAGE: 87.08% -- 391/449 branches in 9 files
|
|
38
|
+
- 100.00% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **Fixed duplicate content when freeze blocks precede nodes with leading comments**: When a freeze block appeared before a node that had leading comments attached from earlier in the file, the merge would output duplicate content. Fixed by:
|
|
43
|
+
- Filtering out comments inside freeze blocks from being attached as leading comments to subsequent nodes
|
|
44
|
+
- Not including leading comments in anchor ranges when other nodes exist between the comments and the node
|
|
45
|
+
- Extending `extract_node_body` to include content after the last statement up to the closing line, ensuring freeze blocks at the end of block bodies are preserved
|
|
46
|
+
|
|
33
47
|
## [1.1.5] - 2025-12-04
|
|
34
48
|
|
|
35
49
|
- TAG: [v1.1.5][1.1.5t]
|
|
@@ -223,7 +237,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
223
237
|
|
|
224
238
|
- Initial release
|
|
225
239
|
|
|
226
|
-
[Unreleased]: https://github.com/kettle-rb/prism-merge/compare/v1.1.
|
|
240
|
+
[Unreleased]: https://github.com/kettle-rb/prism-merge/compare/v1.1.6...HEAD
|
|
241
|
+
[1.1.6]: https://github.com/kettle-rb/prism-merge/compare/v1.1.5...v1.1.6
|
|
242
|
+
[1.1.6t]: https://github.com/kettle-rb/prism-merge/releases/tag/v1.1.6
|
|
227
243
|
[1.1.5]: https://github.com/kettle-rb/prism-merge/compare/v1.1.4...v1.1.5
|
|
228
244
|
[1.1.5t]: https://github.com/kettle-rb/prism-merge/releases/tag/v1.1.5
|
|
229
245
|
[1.1.4]: https://github.com/kettle-rb/prism-merge/compare/v1.1.3...v1.1.4
|
data/README.md
CHANGED
|
@@ -1194,7 +1194,7 @@ Thanks for RTFM. ☺️
|
|
|
1194
1194
|
[📌gitmoji]: https://gitmoji.dev
|
|
1195
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
|
|
1196
1196
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1197
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.
|
|
1197
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.945-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1198
1198
|
[🔐security]: SECURITY.md
|
|
1199
1199
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1200
1200
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -254,17 +254,28 @@ module Prism
|
|
|
254
254
|
d_node_info = dest_sig_map[sig].find { |d| !matched_dest.include?(d[:index]) }
|
|
255
255
|
next unless d_node_info
|
|
256
256
|
|
|
257
|
-
# Create anchor for this matched node
|
|
258
|
-
|
|
257
|
+
# Create anchor for this matched node
|
|
258
|
+
# Only include leading comments if they are immediately before the node
|
|
259
|
+
# (no other nodes/content between comments and this node)
|
|
260
|
+
t_start = calculate_anchor_start(t_node_info, template_nodes)
|
|
259
261
|
t_end = t_node_info[:line_range].end
|
|
260
|
-
d_start = d_node_info
|
|
262
|
+
d_start = calculate_anchor_start(d_node_info, dest_nodes)
|
|
261
263
|
d_end = d_node_info[:line_range].end
|
|
262
264
|
|
|
263
|
-
# Check if this would
|
|
264
|
-
#
|
|
265
|
+
# Check if this would overlap with existing anchors in BOTH template AND dest
|
|
266
|
+
# (same position in both files indicates a true overlap/conflict)
|
|
267
|
+
# Also check for exact match (already covered)
|
|
265
268
|
overlaps = @anchors.any? do |a|
|
|
266
|
-
|
|
269
|
+
# Exact match - already have this anchor
|
|
270
|
+
exact_match = a.template_start == t_start && a.template_end == t_end &&
|
|
267
271
|
a.dest_start == d_start && a.dest_end == d_end
|
|
272
|
+
|
|
273
|
+
# Check if the proposed anchor's range overlaps with existing anchor
|
|
274
|
+
# AND it's the same relative position (both template ranges overlap AND both dest ranges overlap)
|
|
275
|
+
template_overlaps = ranges_overlap?(t_start..t_end, a.template_start..a.template_end)
|
|
276
|
+
dest_overlaps = ranges_overlap?(d_start..d_end, a.dest_start..a.dest_end)
|
|
277
|
+
|
|
278
|
+
exact_match || (template_overlaps && dest_overlaps)
|
|
268
279
|
end
|
|
269
280
|
|
|
270
281
|
unless overlaps
|
|
@@ -281,6 +292,33 @@ module Prism
|
|
|
281
292
|
end
|
|
282
293
|
end
|
|
283
294
|
|
|
295
|
+
# Calculate the start line for an anchor, considering leading comments
|
|
296
|
+
# Only include leading comments if they are immediately adjacent to the node
|
|
297
|
+
# (no other nodes between the comments and this node)
|
|
298
|
+
def calculate_anchor_start(node_info, all_nodes)
|
|
299
|
+
node_start = node_info[:line_range].begin
|
|
300
|
+
leading_comments = node_info[:leading_comments]
|
|
301
|
+
|
|
302
|
+
return node_start if leading_comments.empty?
|
|
303
|
+
|
|
304
|
+
first_comment_line = leading_comments.first.location.start_line
|
|
305
|
+
|
|
306
|
+
# Check if any other node exists between the first comment and this node
|
|
307
|
+
# If so, don't include the leading comments in the anchor
|
|
308
|
+
has_intervening_node = all_nodes.any? do |other|
|
|
309
|
+
next false if other[:index] == node_info[:index]
|
|
310
|
+
other_range = other[:line_range]
|
|
311
|
+
# Check if other node is between first comment and this node
|
|
312
|
+
other_range.begin > first_comment_line && other_range.end < node_start
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
if has_intervening_node
|
|
316
|
+
node_start
|
|
317
|
+
else
|
|
318
|
+
first_comment_line
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
284
322
|
def add_freeze_block_anchors
|
|
285
323
|
# Freeze blocks in destination should always be preserved as anchors
|
|
286
324
|
# Match freeze blocks by their index/order in the file
|
|
@@ -319,9 +319,24 @@ module Prism
|
|
|
319
319
|
end
|
|
320
320
|
end
|
|
321
321
|
|
|
322
|
-
# Extract nodes with their comments and metadata
|
|
323
|
-
#
|
|
324
|
-
#
|
|
322
|
+
# Extract nodes with their comments and metadata.
|
|
323
|
+
#
|
|
324
|
+
# Uses Prism's native comment attachment via node.location. Leading comments
|
|
325
|
+
# are filtered to exclude:
|
|
326
|
+
# 1. Freeze/unfreeze marker comments (they belong to FreezeNode boundaries)
|
|
327
|
+
# 2. Comments inside freeze blocks (they belong to FreezeNode content)
|
|
328
|
+
#
|
|
329
|
+
# This filtering prevents duplicate content when freeze blocks precede other
|
|
330
|
+
# nodes, as Prism attaches ALL preceding comments to a node's leading_comments.
|
|
331
|
+
#
|
|
332
|
+
# @return [Array<Hash>] Array of node info hashes with keys:
|
|
333
|
+
# - :node [Prism::Node, FreezeNode] The AST node
|
|
334
|
+
# - :index [Integer] Position in statements array
|
|
335
|
+
# - :leading_comments [Array<Prism::Comment>] Filtered leading comments
|
|
336
|
+
# - :inline_comments [Array<Prism::Comment>] Trailing/inline comments
|
|
337
|
+
# - :signature [Array, nil] Structural signature for matching
|
|
338
|
+
# - :line_range [Range] Line range covered by the node
|
|
339
|
+
# @api private
|
|
325
340
|
def extract_nodes_with_comments
|
|
326
341
|
return [] unless valid?
|
|
327
342
|
|
|
@@ -330,6 +345,13 @@ module Prism
|
|
|
330
345
|
/#\s*#{Regexp.escape(@freeze_token)}:(freeze|unfreeze)/i
|
|
331
346
|
end
|
|
332
347
|
|
|
348
|
+
# Build a set of line numbers that are inside freeze blocks
|
|
349
|
+
# Comments on these lines should not be attached as leading comments to other nodes
|
|
350
|
+
freeze_block_lines = Set.new
|
|
351
|
+
freeze_blocks.each do |fb|
|
|
352
|
+
(fb.start_line..fb.end_line).each { |line| freeze_block_lines << line }
|
|
353
|
+
end
|
|
354
|
+
|
|
333
355
|
statements.map.with_index do |stmt, idx|
|
|
334
356
|
# FreezeNode doesn't have Prism location with comments
|
|
335
357
|
# It's a wrapper with custom Location struct
|
|
@@ -343,12 +365,17 @@ module Prism
|
|
|
343
365
|
line_range: stmt.location.start_line..stmt.location.end_line,
|
|
344
366
|
}
|
|
345
367
|
else
|
|
346
|
-
# Filter out
|
|
347
|
-
#
|
|
348
|
-
#
|
|
368
|
+
# Filter out comments that are:
|
|
369
|
+
# 1. Freeze/unfreeze markers (part of FreezeNode boundaries)
|
|
370
|
+
# 2. Inside freeze blocks (belong to FreezeNode content, not this node)
|
|
349
371
|
leading = stmt.location.leading_comments
|
|
350
|
-
if freeze_marker_pattern
|
|
351
|
-
leading = leading.reject
|
|
372
|
+
if freeze_marker_pattern || freeze_block_lines.any?
|
|
373
|
+
leading = leading.reject do |c|
|
|
374
|
+
comment_line = c.location.start_line
|
|
375
|
+
# Reject if it's a freeze marker OR if it's inside a freeze block
|
|
376
|
+
(freeze_marker_pattern && c.slice.match?(freeze_marker_pattern)) ||
|
|
377
|
+
freeze_block_lines.include?(comment_line)
|
|
378
|
+
end
|
|
352
379
|
end
|
|
353
380
|
|
|
354
381
|
{
|
|
@@ -708,7 +708,7 @@ module Prism
|
|
|
708
708
|
|
|
709
709
|
# Get the line range of the body
|
|
710
710
|
# Start from line after node opening (to include any leading comments/freeze markers)
|
|
711
|
-
#
|
|
711
|
+
# End at the line before the closing `end` (to include trailing comments/freeze markers)
|
|
712
712
|
body_start_line = case node
|
|
713
713
|
when Prism::CallNode
|
|
714
714
|
# Block body starts on line after the `do` or `{`
|
|
@@ -720,11 +720,22 @@ module Prism
|
|
|
720
720
|
body_statements.first.location.start_line
|
|
721
721
|
end
|
|
722
722
|
|
|
723
|
-
|
|
723
|
+
# End line should be the line before the closing keyword (end, }, etc.)
|
|
724
|
+
# This ensures we capture trailing comments and freeze blocks after the last statement
|
|
725
|
+
body_end_line = case node
|
|
726
|
+
when Prism::CallNode
|
|
727
|
+
# Block ends at the closing `end` or `}`
|
|
728
|
+
node.block.closing_loc ? node.block.closing_loc.start_line - 1 : body_statements.last.location.end_line
|
|
729
|
+
when Prism::ClassNode, Prism::ModuleNode, Prism::SingletonClassNode
|
|
730
|
+
# Body ends at the line before `end`
|
|
731
|
+
node.end_keyword_loc ? node.end_keyword_loc.start_line - 1 : body_statements.last.location.end_line
|
|
732
|
+
else
|
|
733
|
+
body_statements.last.location.end_line
|
|
734
|
+
end
|
|
724
735
|
|
|
725
736
|
# Extract the source lines for the body
|
|
726
737
|
lines = []
|
|
727
|
-
(body_start_line..
|
|
738
|
+
(body_start_line..body_end_line).each do |line_num|
|
|
728
739
|
lines << analysis.line_at(line_num).chomp
|
|
729
740
|
end
|
|
730
741
|
lines.join("\n") + "\n"
|
data/lib/prism/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: prism-merge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.6
|
|
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.6
|
|
269
|
+
changelog_uri: https://github.com/kettle-rb/prism-merge/blob/v1.1.6/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.6
|
|
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
|