ast-merge 4.0.2 → 4.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29e3c1eb54812e59b30a8ae0dc42792486ef2e4992dbd43234452cfce0f2b1ab
4
- data.tar.gz: bb1b200aa2a2d8a48c127952510984cf2ccd71e2517ced1d422fe542a7969c78
3
+ metadata.gz: e10cc78b855b0a28a19d476767d5cb49b880e0101b940a8846be8cb01c736882
4
+ data.tar.gz: 03dde93b3c46ceec1859268a538c917162f3737eb719a2138e9923fe4f3b05e6
5
5
  SHA512:
6
- metadata.gz: b0823b5b64b77947faa3213463c18289a4275b5b8fd7d5a0dcf258c1ae4088dcc50a34923f459944473cfae67e7c18dd646e3236f7ff6eb0898edfdb8b5d9ab2
7
- data.tar.gz: 0f8dafa6c932a75504c898793fb0f51dfa9977d288f70e6e8e9fc8aff9f0f3452742a0302dbdd23aee33db8ab4528834048322af37d7c4d44ec9fb473e682855
6
+ metadata.gz: 5e0715a8946d00becd61e3e8cf6418f6fcb57b89d735dacf60728e62db78e9ea95691fe55b96c30bb7e7bb14255de1919bb4962af4bef2e66460988db9242bd9
7
+ data.tar.gz: 04f7fde08c4419a7b5fa086d0575bf4cdbe5bcd748519eda89dcb7c161a8b6aa322521bbe5d9ca008dc1875186c0a2795b5976621449c8c864ca2b6640b6209b
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,75 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [4.0.4] - 2026-01-20
34
+
35
+ - TAG: [v4.0.4][4.0.4t]
36
+ - COVERAGE: 96.37% -- 2552/2648 lines in 50 files
37
+ - BRANCH COVERAGE: 87.22% -- 812/931 branches in 50 files
38
+ - 98.81% documented
39
+
40
+ ### Added
41
+
42
+ - **RSpec Split Loading Pattern**: New files for granular RSpec dependency tag loading
43
+ - `lib/ast/merge/rspec/setup.rb` - Loads only registry and helper classes (no RSpec configuration)
44
+ - `lib/ast/merge/rspec/dependency_tags_helpers.rb` - DependencyTags helper module
45
+ - `lib/ast/merge/rspec/dependency_tags_config.rb` - RSpec.configure block with exclusion filters
46
+ - Enables registering known gems before RSpec.configure runs (solving catch-22 problem)
47
+ - Required for ast-merge test suite to preserve SimpleCov coverage
48
+ - Required for merge gems that register other merge gems as dependencies
49
+ - **`Ast::Merge::RSpec::MergeGemRegistry.force_check_availability!`**: Deferred availability checking for accurate test coverage
50
+ - Called automatically in `before(:suite)` hook AFTER SimpleCov is loaded
51
+ - Prevents premature gem loading that would bypass coverage instrumentation
52
+ - Ensures accurate coverage reporting in merge gem test suites
53
+
54
+ ### Changed
55
+
56
+ - **RSpec Dependency Tags**: Fixed exclusion filter setup to properly skip tests when optional gems unavailable
57
+ - Exclusion filters now set during `RSpec.configure` (not in `before(:suite)` which runs too late)
58
+ - Fixed RSpec API usage: `config.filter_run_excluding tag => true` (not `[tag] = true`)
59
+ - `ast-merge` uses split loading pattern in `spec/spec_helper.rb` and `spec/config/tree_haver.rb`
60
+ - `markdown-merge` uses split pattern (registers `:commonmarker_merge`, `:markly_merge`)
61
+ - `markly-merge` uses split pattern (registers `:prism_merge`)
62
+ - `commonmarker-merge` uses simple pattern (no registrations needed)
63
+
64
+ ### Fixed
65
+
66
+ - **Test coverage accuracy**: Fixed premature gem loading that bypassed SimpleCov instrumentation
67
+ - `MergeGemRegistry.registered_gems` now returns ONLY explicitly registered gems, not all KNOWN_GEMS
68
+ - RSpec exclusion filters are configured in `before(:suite)` hook after `force_check_availability!` runs
69
+ - This ensures gems are loaded AFTER SimpleCov sets up coverage instrumentation
70
+ - Previously, commonmarker-merge reported only 11 lines covered when it should have been far more
71
+ - **RSpec Dependency Tags**: Tests with tags like `:markdown_merge`, `:markly_merge` now properly skip when those gems aren't available
72
+ - Fixed 141 test failures caused by tests running without required gems loaded
73
+ - Removed `require` statements from integration specs - dependency tags handle gem loading
74
+ - Fixed tag usage: Tests using `Markdown::Merge::PartialTemplateMerger` with `:markly` backend now correctly tagged with both `:markdown_merge` and `:markly_merge`
75
+ - **Thread-Safety Spec**: Fixed JRuby concurrency test failure in `NodeTyping::Normalizer#canonical_type`
76
+ - Changed from unsynchronized `Array` to thread-safe `Queue` for collecting results from concurrent threads
77
+ - Eliminates `ConcurrencyError: Detected invalid array contents due to unsynchronized modifications`
78
+
79
+ ## [4.0.3] - 2026-01-19
80
+
81
+ - TAG: [v4.0.3][4.0.3t]
82
+ - COVERAGE: 97.30% -- 2739/2815 lines in 53 files
83
+ - BRANCH COVERAGE: 89.84% -- 893/994 branches in 53 files
84
+ - 98.81% documented
85
+
86
+ ### Added
87
+
88
+ - **`Ast::Merge::RSpec::MergeGemRegistry.register_known_gems`**: Selective registration of known merge gems for RSpec dependency tags
89
+ - Allows test suites to explicitly register only the merge gems they need, avoiding overhead of registering all known gems
90
+ - Usage in `spec/config/tree_haver.rb`: `MergeGemRegistry.register_known_gems(:prism_merge, :commonmarker_merge)`
91
+ - Enables proper RSpec tag-based test skipping for optional merge gem dependencies
92
+ - Example: Tests tagged with `:prism_merge` are automatically skipped when prism-merge isn't available
93
+
94
+ ### Changed
95
+
96
+ - Upgrade to [tree_haver v5.0.2](https://github.com/kettle-rb/tree_haver/releases/tag/v5.0.2)
97
+ - **RSpec dependency tag load order pattern**: Merge gems now load tree_haver and dependency tags early via `spec/config/tree_haver.rb`
98
+ - Ensures `TreeHaver::RSpec::DependencyTags` is loaded before gems register themselves
99
+ - Pattern: Load tree_haver/rspec → Load ast/merge/rspec → Register known gems → Load library
100
+ - Applied to markdown-merge and markly-merge; other merge gems should follow this pattern
101
+
33
102
  ## [4.0.2] - 2026-01-12
34
103
 
35
104
  - TAG: [v4.0.2][4.0.2t]
@@ -664,7 +733,11 @@ Please file a bug if you notice a violation of semantic versioning.
664
733
 
665
734
  - Initial release
666
735
 
667
- [Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.3...HEAD
736
+ [Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.4...HEAD
737
+ [4.0.5]: https://github.com/kettle-rb/ast-merge/compare/v4.0.4...v4.0.5
738
+ [4.0.5t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.5
739
+ [4.0.4]: https://github.com/kettle-rb/ast-merge/compare/v4.0.3...v4.0.4
740
+ [4.0.4t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.4
668
741
  [4.0.3]: https://github.com/kettle-rb/ast-merge/compare/v4.0.2...v4.0.3
669
742
  [4.0.3t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.3
670
743
  [4.0.2]: https://github.com/kettle-rb/ast-merge/compare/v4.0.1...v4.0.2
data/README.md CHANGED
@@ -62,7 +62,7 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
62
62
 
63
63
  | Gem | Version | CI | | Language<br>/ Format | Parser Backend(s) | Description |
64
64
  |------------------------------------------|----------------------------------------------------------------|--------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|-------------|
65
- | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] | [![Version][tree_haver-ci-i]][tree_haver-ci] | Multi | MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
65
+ | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] | [![Version][tree_haver-ci-i]][tree_haver-ci] | Multi | Supported Backends: MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
66
66
  | [ast-merge][ast-merge] | [![Version][ast-merge-gem-i]][ast-merge-gem] | [![Version][ast-merge-ci-i]][ast-merge-ci] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
67
67
  | [bash-merge][bash-merge] | [![Version][bash-merge-gem-i]][bash-merge-gem] | [![Version][bash-merge-ci-i]][bash-merge-ci] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
68
68
  | [commonmarker-merge][commonmarker-merge] | [![Version][commonmarker-merge-gem-i]][commonmarker-merge-gem] | [![Version][commonmarker-merge-ci-i]][commonmarker-merge-ci] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
@@ -80,18 +80,18 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
80
80
 
81
81
  tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
82
82
 
83
- | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
84
- |------------------------------------------------|:---:|:-----:|:-----------:|-----------------------------------------------------|
85
- | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
86
- | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
87
- | **FFI** | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
88
- | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
89
- | **Prism** | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
90
- | **Psych** | ✅ | ✅ | ✅ | YAML parsing, stdlib |
91
- | **Citrus** | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
92
- | **Parslet** | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
93
- | **Commonmarker** | ✅ | ❌ | ❓ | Rust extension for Markdown |
94
- | **Markly** | ✅ | ❌ | ❓ | C extension for Markdown |
83
+ | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
84
+ |-------------------------------------------------|:---:|:-----:|:-----------:|----------------------------------------------------------------------------|
85
+ | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
86
+ | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
87
+ | **FFI** ([ffi][ffi]) | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
88
+ | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
89
+ | **Prism** ([prism][prism]) | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
90
+ | **Psych** ([psych][psych]) | ✅ | ✅ | ✅ | YAML parsing, stdlib |
91
+ | **Citrus** ([citrus][citrus]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
92
+ | **Parslet** ([parslet][parslet]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
93
+ | **Commonmarker** ([commonmarker][commonmarker]) | ✅ | ❌ | ❓ | Rust extension for Markdown (via [commonmarker-merge][commonmarker-merge]) |
94
+ | **Markly** ([markly][markly]) | ✅ | ❌ | ❓ | C extension for Markdown (via [markly-merge][markly-merge]) |
95
95
 
96
96
  **Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
97
97
 
@@ -185,6 +185,7 @@ tree_haver supports multiple parsing backends, but not all backends work on all
185
185
  [kettle-jem-ci]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml
186
186
  [prism]: https://github.com/ruby/prism
187
187
  [psych]: https://github.com/ruby/psych
188
+ [ffi]: https://github.com/ffi/ffi
188
189
  [ts-json]: https://github.com/tree-sitter/tree-sitter-json
189
190
  [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
190
191
  [ts-bash]: https://github.com/tree-sitter/tree-sitter-bash
@@ -199,6 +200,8 @@ tree_haver supports multiple parsing backends, but not all backends work on all
199
200
  [ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
200
201
  [tree_stump]: https://github.com/joker1007/tree_stump
201
202
  [jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
203
+ [citrus]: https://github.com/mjackson/citrus
204
+ [parslet]: https://github.com/kschiess/parslet
202
205
 
203
206
  ### Architecture: tree\_haver + ast-merge
204
207
 
@@ -788,7 +791,7 @@ Support us with a monthly donation and help us continue our activities. \[[Becom
788
791
  NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
789
792
 
790
793
  <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
791
- No backers yet. Be the first\!
794
+ No backers yet. Be the first!
792
795
  <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
793
796
 
794
797
  ### Open Collective for Organizations
@@ -798,7 +801,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
798
801
  NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
799
802
 
800
803
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
801
- No sponsors yet. Be the first\!
804
+ No sponsors yet. Be the first!
802
805
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
803
806
 
804
807
  [kettle-readme-backers]: https://github.com/kettle-rb/ast-merge/blob/main/exe/kettle-readme-backers
@@ -1103,7 +1106,7 @@ Thanks for RTFM. ☺️
1103
1106
  [📌gitmoji]: https://gitmoji.dev
1104
1107
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1105
1108
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1106
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.815-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1109
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.648-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1107
1110
  [🔐security]: SECURITY.md
1108
1111
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1109
1112
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -1,125 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "merge_gem_registry"
4
-
5
- # Ast::Merge RSpec Dependency Tags
3
+ # Ast::Merge RSpec Dependency Tags - Combined Loader
4
+ #
5
+ # This file provides the standard entry point for RSpec dependency tags.
6
+ # It loads both the helper module and the RSpec configuration.
7
+ #
8
+ # **When to use the split loading pattern:**
9
+ # - ast-merge: MUST use split pattern (to preserve SimpleCov coverage of ast-merge itself)
10
+ # - Merge gems that register other merge gems: MUST use split pattern (to avoid catch-22)
11
+ # - Other gems: Can use simple `require "ast/merge/rspec"` (this file)
6
12
  #
7
- # This module provides dependency detection helpers for conditional test execution
8
- # in the ast-merge gem family. It uses MergeGemRegistry for dynamic merge gem detection.
13
+ # @example Simple pattern (for gems that DON'T register other gems)
14
+ # # In spec/config/tree_haver.rb:
15
+ # require "ast-merge"
16
+ # require "ast/merge/rspec" # Loads everything
9
17
  #
10
- # @example Loading in spec_helper.rb
11
- # require "ast/merge/rspec/dependency_tags"
18
+ # @example Split pattern (for ast-merge or gems that register other merge gems)
19
+ # # In spec/config/tree_haver.rb:
20
+ # require "ast-merge"
21
+ # require "ast/merge/rspec/setup" # Load registry/helpers only
22
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:markly_merge)
23
+ # require "ast/merge/rspec/dependency_tags_config" # Load RSpec config
24
+ # require "ast/merge/rspec/shared_examples"
12
25
  #
13
26
  # @example Usage in specs
14
27
  # it "requires markly-merge", :markly_merge do
15
28
  # # This test only runs when markly-merge is available
16
29
  # end
17
- #
18
- # it "requires prism-merge", :prism_merge do
19
- # # This test only runs when prism-merge is available
20
- # end
21
- #
22
- # == Dynamic Tag Registration
23
- #
24
- # Merge gems register themselves with MergeGemRegistry, which automatically:
25
- # - Defines `*_available?` methods on DependencyTags
26
- # - Configures RSpec exclusion filters for the tag
27
- # - Supports negated tags (`:not_*`)
28
- #
29
- # @example How merge gems register (in their lib file)
30
- # Ast::Merge::RSpec::MergeGemRegistry.register(
31
- # :markly_merge,
32
- # require_path: "markly/merge",
33
- # merger_class: "Markly::Merge::SmartMerger",
34
- # test_source: "# Test\n\nParagraph",
35
- # category: :markdown
36
- # )
37
- #
38
- # == Built-in Composite Tags
39
- #
40
- # [:any_markdown_merge]
41
- # At least one markdown merge gem is available (category: :markdown).
42
-
43
- module Ast
44
- module Merge
45
- module RSpec
46
- # Dependency detection helpers for conditional test execution
47
- module DependencyTags
48
- class << self
49
- # ============================================================
50
- # Composite Availability Checks
51
- # ============================================================
52
-
53
- # Check if at least one markdown merge gem is available
54
- #
55
- # @return [Boolean] true if any markdown merge gem works
56
- def any_markdown_merge_available?
57
- MergeGemRegistry.gems_by_category(:markdown).any? do |tag|
58
- MergeGemRegistry.available?(tag)
59
- end
60
- end
61
-
62
- # ============================================================
63
- # Summary and Reset
64
- # ============================================================
65
-
66
- # Get a summary of available dependencies (for debugging)
67
- #
68
- # @return [Hash{Symbol => Boolean}] map of dependency name to availability
69
- def summary
70
- result = MergeGemRegistry.summary
71
- result[:any_markdown_merge] = any_markdown_merge_available?
72
- result
73
- end
74
-
75
- # Reset all memoized availability checks
76
- #
77
- # @return [void]
78
- def reset!
79
- MergeGemRegistry.reset_availability!
80
- end
81
- end
82
- end
83
- end
84
- end
85
- end
86
-
87
- # Configure RSpec with dependency-based exclusion filters
88
- RSpec.configure do |config|
89
- deps = Ast::Merge::RSpec::DependencyTags
90
- registry = Ast::Merge::RSpec::MergeGemRegistry
91
-
92
- config.before(:suite) do
93
- # Print dependency summary if AST_MERGE_DEBUG is set
94
- unless ENV.fetch("AST_MERGE_DEBUG", "false").casecmp?("false")
95
- puts "\n=== Ast::Merge Test Dependencies ==="
96
- deps.summary.each do |dep, available|
97
- status = available ? "✓ available" : "✗ not available"
98
- puts " #{dep}: #{status}"
99
- end
100
- puts "=====================================\n"
101
- end
102
- end
103
-
104
- # ============================================================
105
- # Dynamic Merge Gem Tags
106
- # ============================================================
107
- # Tags are configured dynamically based on what's registered in MergeGemRegistry.
108
- # Each merge gem registers itself, and exclusion filters are set up automatically.
109
-
110
- registry.registered_gems.each do |tag|
111
- # Positive tag: run when gem IS available
112
- config.filter_run_excluding(tag => true) unless registry.available?(tag)
113
-
114
- # Negated tag: run when gem is NOT available
115
- negated_tag = :"not_#{tag}"
116
- config.filter_run_excluding(negated_tag => true) if registry.available?(tag)
117
- end
118
30
 
119
- # ============================================================
120
- # Composite Tags
121
- # ============================================================
31
+ # Load the helper module (DependencyTags methods)
32
+ require_relative "dependency_tags_helpers"
122
33
 
123
- config.filter_run_excluding(any_markdown_merge: true) unless deps.any_markdown_merge_available?
124
- config.filter_run_excluding(not_any_markdown_merge: true) if deps.any_markdown_merge_available?
125
- end
34
+ # Load the RSpec configuration (exclusion filters)
35
+ require_relative "dependency_tags_config"
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "dependency_tags_helpers"
4
+
5
+ # Ast::Merge RSpec Dependency Tags - RSpec Configuration
6
+ #
7
+ # This file configures RSpec with dependency-based exclusion filters.
8
+ # It should be loaded AFTER gems have been registered with MergeGemRegistry.
9
+ #
10
+ # @example Loading in spec_helper.rb (for merge gem test suites)
11
+ # require "ast/merge/rspec" # Loads this file automatically
12
+ #
13
+ # @example For ast-merge test suite (split loading)
14
+ # # In spec_helper.rb BEFORE requiring ast-merge:
15
+ # require "ast/merge/rspec/setup"
16
+ #
17
+ # # Register known gems:
18
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:markly_merge)
19
+ #
20
+ # # Then AFTER requiring ast-merge, load config:
21
+ # require "ast/merge/rspec/dependency_tags_config"
22
+
23
+ # Configure RSpec with dependency-based exclusion filters
24
+ RSpec.configure do |config|
25
+ deps = Ast::Merge::RSpec::DependencyTags
26
+ registry = Ast::Merge::RSpec::MergeGemRegistry
27
+
28
+ # CRITICAL: Exclusion filters MUST be set during RSpec.configure, not in before(:suite)
29
+ # because RSpec filters tests before before(:suite) runs!
30
+
31
+ # Force availability checking for all registered gems
32
+ # This loads the gems NOW during configuration, which is after SimpleCov has instrumented
33
+ # the code (since this file is required AFTER ast-merge loads in spec_helper.rb)
34
+ registry.force_check_availability!
35
+
36
+ # Now configure exclusion filters based on actual availability
37
+ registry.registered_gems.each do |tag|
38
+ if registry.available?(tag)
39
+ # Gem is available - exclude tests tagged with :not_tag
40
+ negated_tag = :"not_#{tag}"
41
+ config.filter_run_excluding(negated_tag => true)
42
+ else
43
+ # Gem is NOT available - exclude tests tagged with :tag
44
+ config.filter_run_excluding(tag => true)
45
+ end
46
+ end
47
+
48
+ # Configure composite tags (these also trigger gem loading, so must be here)
49
+ if deps.any_markdown_merge_available?
50
+ config.filter_run_excluding(not_any_markdown_merge: true)
51
+ else
52
+ config.filter_run_excluding(any_markdown_merge: true)
53
+ end
54
+
55
+ # Print dependency summary if AST_MERGE_DEBUG is set
56
+ config.before(:suite) do
57
+ unless ENV.fetch("AST_MERGE_DEBUG", "false").casecmp?("false")
58
+ puts "\n=== Ast::Merge Test Dependencies ==="
59
+ deps.summary.each do |dep, available|
60
+ status = available ? "✓ available" : "✗ not available"
61
+ puts " #{dep}: #{status}"
62
+ end
63
+ puts "=====================================\n"
64
+ end
65
+ end
66
+
67
+ # ============================================================
68
+ # Dynamic Merge Gem Tags - Initial Setup
69
+ # ============================================================
70
+ # Note: We don't set exclusions here because that would require checking
71
+ # availability (loading gems) before SimpleCov. The actual exclusions are
72
+ # set in the before(:suite) hook above after force_check_availability! runs.
73
+ # This includes composite tags like :any_markdown_merge.
74
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "merge_gem_registry"
4
+
5
+ # Ast::Merge RSpec Dependency Tags - Helper Module Only
6
+ #
7
+ # This module provides dependency detection helpers for conditional test execution
8
+ # in the ast-merge gem family. It uses MergeGemRegistry for dynamic merge gem detection.
9
+ #
10
+ # NOTE: This file contains ONLY the helper module, not the RSpec configuration.
11
+ # The RSpec configuration is in dependency_tags_config.rb and is loaded by
12
+ # ast/merge/rspec (the full entry point).
13
+
14
+ module Ast
15
+ module Merge
16
+ module RSpec
17
+ # Dependency detection helpers for conditional test execution
18
+ module DependencyTags
19
+ class << self
20
+ # ============================================================
21
+ # Composite Availability Checks
22
+ # ============================================================
23
+
24
+ # Check if at least one markdown merge gem is available
25
+ #
26
+ # @return [Boolean] true if any markdown merge gem works
27
+ def any_markdown_merge_available?
28
+ MergeGemRegistry.gems_by_category(:markdown).any? do |tag|
29
+ MergeGemRegistry.available?(tag)
30
+ end
31
+ end
32
+
33
+ # ============================================================
34
+ # Summary and Reset
35
+ # ============================================================
36
+
37
+ # Get a summary of available dependencies (for debugging)
38
+ #
39
+ # @return [Hash{Symbol => Boolean}] map of dependency name to availability
40
+ def summary
41
+ result = MergeGemRegistry.summary
42
+ result[:any_markdown_merge] = any_markdown_merge_available?
43
+ result
44
+ end
45
+
46
+ # Reset all memoized availability checks
47
+ #
48
+ # @return [void]
49
+ def reset!
50
+ MergeGemRegistry.reset_availability!
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -253,12 +253,59 @@ module Ast
253
253
  end
254
254
  end
255
255
 
256
- # Get all registered gem tag names (including pre-configured known gems)
256
+ # Register one or more known gems for RSpec dependency tag support
257
+ #
258
+ # This allows test suites to explicitly register only the merge gems they need
259
+ # for their tests, avoiding the overhead of registering all known gems.
260
+ #
261
+ # @param gem_names [Array<Symbol>] list of gem names from KNOWN_GEMS to register
262
+ # @return [void]
263
+ #
264
+ # @example In spec/config/tree_haver.rb
265
+ # # Only register the markdown merge gems that markly-merge tests depend on
266
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:prism_merge)
267
+ #
268
+ # @example Register multiple gems
269
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(
270
+ # :commonmarker_merge,
271
+ # :markly_merge
272
+ # )
273
+ def register_known_gems(*gem_names)
274
+ gem_names.each do |tag_name|
275
+ tag_sym = tag_name.to_sym
276
+
277
+ # Skip if not in KNOWN_GEMS
278
+ unless KNOWN_GEMS.key?(tag_sym)
279
+ warn("Unknown gem: #{tag_name}. Available: #{KNOWN_GEMS.keys.join(", ")}")
280
+ next
281
+ end
282
+
283
+ # Skip if already registered
284
+ next if registered?(tag_sym)
285
+
286
+ metadata = KNOWN_GEMS[tag_sym]
287
+ register(
288
+ tag_sym,
289
+ require_path: metadata[:require_path],
290
+ merger_class: metadata[:merger_class],
291
+ test_source: metadata[:test_source],
292
+ category: metadata[:category],
293
+ skip_instantiation: metadata[:skip_instantiation],
294
+ )
295
+ end
296
+ end
297
+
298
+ # Get all explicitly registered gem tag names
299
+ #
300
+ # This returns ONLY gems that were explicitly registered via register() or
301
+ # register_known_gems(), NOT all gems in KNOWN_GEMS. This prevents premature
302
+ # loading of gems during RSpec tag setup, which would happen before SimpleCov
303
+ # and ruin coverage reporting.
257
304
  #
258
305
  # @return [Array<Symbol>] list of registered tag names
259
306
  def registered_gems
260
307
  @mutex.synchronize do
261
- (KNOWN_GEMS.keys + @registry.keys).uniq
308
+ @registry.keys
262
309
  end
263
310
  end
264
311
 
@@ -274,6 +321,31 @@ module Ast
274
321
  end
275
322
  end
276
323
 
324
+ # Force availability checking for all registered gems
325
+ #
326
+ # This method should be called AFTER SimpleCov is loaded (typically at the end
327
+ # of spec_helper.rb) to trigger gem loading and availability checking. Calling
328
+ # this ensures RSpec exclusion filters are properly configured based on which
329
+ # gems are actually available.
330
+ #
331
+ # This is necessary because register_known_gems() only registers gems without
332
+ # checking availability. The actual availability check (which requires loading
333
+ # the gem) must happen AFTER coverage instrumentation is set up.
334
+ #
335
+ # @return [void]
336
+ #
337
+ # @example At the end of spec_helper.rb (after SimpleCov loads)
338
+ # # Force availability checking now that coverage is instrumented
339
+ # Ast::Merge::RSpec::MergeGemRegistry.force_check_availability!
340
+ def force_check_availability!
341
+ registered_gems.each do |tag|
342
+ # This will trigger gem_works? which loads the gem
343
+ # Results are cached, so subsequent calls are fast
344
+ available?(tag)
345
+ end
346
+ nil
347
+ end
348
+
277
349
  # Get registration info for a gem
278
350
  #
279
351
  # @param tag_name [Symbol] the tag name
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ast::Merge RSpec Setup (Registry Only)
4
+ #
5
+ # This file loads ONLY the registry and helper classes without configuring RSpec.
6
+ # It's used in the ast-merge test suite to allow registering known gems before
7
+ # SimpleCov loads the library code.
8
+ #
9
+ # DO NOT load this in merge gem test suites - they should use require "ast/merge/rspec"
10
+ # which includes the full RSpec configuration.
11
+ #
12
+ # @example Loading in ast-merge's spec_helper.rb (BEFORE requiring ast-merge)
13
+ # require "ast/merge/rspec/setup"
14
+ #
15
+ # # Now you can register known gems:
16
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:markly_merge, :prism_merge)
17
+ #
18
+ # @example For merge gem test suites (normal pattern)
19
+ # # Don't use this file! Use the full loader instead:
20
+ # require "ast/merge/rspec" # Loads setup + RSpec configuration
21
+
22
+ # Load only the registry - no RSpec configuration
23
+ require_relative "merge_gem_registry"
24
+ require_relative "dependency_tags_helpers"
@@ -5,7 +5,7 @@ module Ast
5
5
  # Version information for Ast::Merge
6
6
  module Version
7
7
  # Current version of the ast-merge gem
8
- VERSION = "4.0.2"
8
+ VERSION = "4.0.4"
9
9
  end
10
10
  VERSION = Version::VERSION # traditional location
11
11
  end
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: 4.0.2
4
+ version: 4.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '5.0'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 5.0.1
69
+ version: 5.0.2
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '5.0'
77
77
  - - ">="
78
78
  - !ruby/object:Gem::Version
79
- version: 5.0.1
79
+ version: 5.0.2
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: kettle-dev
82
82
  requirement: !ruby/object:Gem::Requirement
@@ -355,7 +355,10 @@ files:
355
355
  - lib/ast/merge/recipe/script_loader.rb
356
356
  - lib/ast/merge/rspec.rb
357
357
  - lib/ast/merge/rspec/dependency_tags.rb
358
+ - lib/ast/merge/rspec/dependency_tags_config.rb
359
+ - lib/ast/merge/rspec/dependency_tags_helpers.rb
358
360
  - lib/ast/merge/rspec/merge_gem_registry.rb
361
+ - lib/ast/merge/rspec/setup.rb
359
362
  - lib/ast/merge/rspec/shared_examples.rb
360
363
  - lib/ast/merge/rspec/shared_examples/conflict_resolver_base.rb
361
364
  - lib/ast/merge/rspec/shared_examples/debug_logger.rb
@@ -382,10 +385,10 @@ licenses:
382
385
  - MIT
383
386
  metadata:
384
387
  homepage_uri: https://ast-merge.galtzo.com/
385
- source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.2
386
- changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.2/CHANGELOG.md
388
+ source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.4
389
+ changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.4/CHANGELOG.md
387
390
  bug_tracker_uri: https://github.com/kettle-rb/ast-merge/issues
388
- documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.2
391
+ documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.4
389
392
  funding_uri: https://github.com/sponsors/pboling
390
393
  wiki_uri: https://github.com/kettle-rb/ast-merge/wiki
391
394
  news_uri: https://www.railsbling.com/tags/ast-merge
@@ -414,7 +417,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
414
417
  - !ruby/object:Gem::Version
415
418
  version: '0'
416
419
  requirements: []
417
- rubygems_version: 4.0.3
420
+ rubygems_version: 4.0.4
418
421
  specification_version: 4
419
422
  summary: "☯️ Shared infrastructure for the *-merge gem family"
420
423
  test_files: []
metadata.gz.sig CHANGED
Binary file