Class: Rigor::Configuration::Dependencies
- Inherits:
-
Object
- Object
- Rigor::Configuration::Dependencies
- Defined in:
- lib/rigor/configuration/dependencies.rb
Overview
Parsed ‘dependencies:` section of `.rigor.yml`. Per [ADR-10](../../../docs/adr/10-dependency-source-inference.md), the only nested key today is `source_inference:`, listing gems whose Ruby implementation Rigor MAY walk during inference instead of degrading to `Dynamic` at the dependency boundary.
Slice 1 lands the parser only — ‘Configuration#dependencies` is read, but no analyzer machinery consumes it yet. Slice 2 wires `Analysis::DependencySourceInference` against this value object.
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- VALID_MODES =
Walking modes per [ADR-10 § “Decision”](../../../docs/adr/10-dependency-source-inference.md#decision).
%i[disabled when_missing full].freeze
- DEFAULT_ROOTS =
Default ‘roots:` for an entry that does not supply one. The hard-excluded directories (`spec/` / `test/` / `bin/` / C extensions) are enforced by the walker, not the parser — see ADR-10 § “Hard exclusions”.
%w[lib].freeze
- DEFAULT_BUDGET_PER_GEM =
Default per-gem catalog cap. ADR-10 slice 4 picks 5000 method definitions: it covers Rack (~1500), Faraday (~500), Sidekiq (~800) and other realistic opt-in targets, while still surfacing a diagnostic for ActiveSupport-class libraries (~10 000+ methods) where the user should ship RBS or de-list the gem instead.
5000- MIN_BUDGET_PER_GEM =
Range bounds per ADR-10 § “Budget interaction” (“range 0.25× – 4×”). Configured against the default, this lands at 1250 – 20 000.
(DEFAULT_BUDGET_PER_GEM * 0.25).to_i
- MAX_BUDGET_PER_GEM =
(DEFAULT_BUDGET_PER_GEM * 4).to_i
- VALID_BUDGET_OVERRUN_STRATEGIES =
ADR-10 5b — budget-overrun strategy enum.
-
‘:walker_cap` (default): the (α) semantics. The walker stops harvesting at the cap; methods past the cap fall through to the existing user-class fallback path. Existing v0.1.3 behaviour.
-
‘:dependency_silence`: the (β) semantics. Same walker behaviour, but the dispatcher additionally consults `Index#class_to_gem` after a catalog miss. When the receiver’s class belongs to a budget- exceeded gem, the call resolves to ‘Dynamic` rather than falling through to user-class fallback. This silences `call.undefined-method` for unrecorded methods at the cost of weaker static checking on that gem’s surface.
-
%i[walker_cap dependency_silence].freeze
- DEFAULT_BUDGET_OVERRUN_STRATEGY =
:walker_cap
Instance Attribute Summary collapse
-
#budget_overrun_strategy ⇒ Object
readonly
Returns the value of attribute budget_overrun_strategy.
-
#budget_per_gem ⇒ Object
readonly
Returns the value of attribute budget_per_gem.
-
#source_inference ⇒ Object
readonly
Returns the value of attribute source_inference.
-
#warnings ⇒ Object
readonly
Returns the value of attribute warnings.
Class Method Summary collapse
-
.dedupe_entries(entries) ⇒ Object
ADR-10 § “config-conflict diagnostic” — merges a potentially-duplicated entry list (the ‘includes:` chain produces concatenated arrays via `Configuration.deep_merge`’s special-case for ‘dependencies.source_inference`) into a single canonical entry per gem name.
-
.from_h(data) ⇒ Object
Parse the YAML-shaped ‘dependencies:` value into a frozen Dependencies.
- .merge_entry_pair(existing, incoming, warnings) ⇒ Object
Instance Method Summary collapse
- #empty? ⇒ Boolean
-
#initialize(source_inference, budget_per_gem = DEFAULT_BUDGET_PER_GEM, warnings = [], budget_overrun_strategy = DEFAULT_BUDGET_OVERRUN_STRATEGY) ⇒ Dependencies
constructor
A new instance of Dependencies.
- #to_h ⇒ Object
Constructor Details
#initialize(source_inference, budget_per_gem = DEFAULT_BUDGET_PER_GEM, warnings = [], budget_overrun_strategy = DEFAULT_BUDGET_OVERRUN_STRATEGY) ⇒ Dependencies
Returns a new instance of Dependencies.
89 90 91 92 93 94 95 96 |
# File 'lib/rigor/configuration/dependencies.rb', line 89 def initialize(source_inference, budget_per_gem = DEFAULT_BUDGET_PER_GEM, warnings = [], budget_overrun_strategy = DEFAULT_BUDGET_OVERRUN_STRATEGY) @source_inference = source_inference.freeze @budget_per_gem = budget_per_gem @warnings = warnings.freeze @budget_overrun_strategy = budget_overrun_strategy freeze end |
Instance Attribute Details
#budget_overrun_strategy ⇒ Object (readonly)
Returns the value of attribute budget_overrun_strategy.
70 71 72 |
# File 'lib/rigor/configuration/dependencies.rb', line 70 def budget_overrun_strategy @budget_overrun_strategy end |
#budget_per_gem ⇒ Object (readonly)
Returns the value of attribute budget_per_gem.
70 71 72 |
# File 'lib/rigor/configuration/dependencies.rb', line 70 def budget_per_gem @budget_per_gem end |
#source_inference ⇒ Object (readonly)
Returns the value of attribute source_inference.
70 71 72 |
# File 'lib/rigor/configuration/dependencies.rb', line 70 def source_inference @source_inference end |
#warnings ⇒ Object (readonly)
Returns the value of attribute warnings.
70 71 72 |
# File 'lib/rigor/configuration/dependencies.rb', line 70 def warnings @warnings end |
Class Method Details
.dedupe_entries(entries) ⇒ Object
ADR-10 § “config-conflict diagnostic” — merges a potentially-duplicated entry list (the ‘includes:` chain produces concatenated arrays via `Configuration.deep_merge`’s special-case for ‘dependencies.source_inference`) into a single canonical entry per gem name. The merge rules:
-
Same gem, same all fields → idempotent collapse (no warning).
-
Same gem, different ‘mode:` → keep the LAST entry (matches existing right-wins semantics elsewhere) AND emit a `:warning` so the user knows their `includes:` chain is ambiguous.
-
Same gem, different ‘roots:` → union the roots silently (no warning). The walker is happy to visit the union.
Returns ‘[entries, warnings]` so the caller can plumb the warning list through to the Runner for diagnostic emission.
135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/rigor/configuration/dependencies.rb', line 135 def dedupe_entries(entries) warnings = [] by_gem = {} entries.each do |entry| existing = by_gem[entry.gem] by_gem[entry.gem] = if existing.nil? entry else merge_entry_pair(existing, entry, warnings) end end [by_gem.values, warnings] end |
.from_h(data) ⇒ Object
Parse the YAML-shaped ‘dependencies:` value into a frozen Rigor::Configuration::Dependencies. Accepts `nil` / `{}` / a Hash with `source_inference:` and / or `budget_per_gem:` / `budget_overrun_strategy:` present.
76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/rigor/configuration/dependencies.rb', line 76 def self.from_h(data) return new([]) if data.nil? raise ArgumentError, "dependencies: must be a Hash, got #{data.inspect}" unless data.is_a?(Hash) raw_entries = Array(data["source_inference"]).map { |raw| coerce_entry(raw) } entries, warnings = dedupe_entries(raw_entries) budget = coerce_budget_per_gem(data.fetch("budget_per_gem", DEFAULT_BUDGET_PER_GEM)) strategy = coerce_budget_overrun_strategy( data.fetch("budget_overrun_strategy", DEFAULT_BUDGET_OVERRUN_STRATEGY) ) new(entries, budget, warnings, strategy) end |
.merge_entry_pair(existing, incoming, warnings) ⇒ Object
149 150 151 152 153 154 155 156 157 |
# File 'lib/rigor/configuration/dependencies.rb', line 149 def merge_entry_pair(existing, incoming, warnings) if existing.mode != incoming.mode warnings << "dependencies.source_inference[].gem #{incoming.gem.inspect} declared with " \ "conflicting modes (#{existing.mode.inspect} vs #{incoming.mode.inspect}); " \ "the later (#{incoming.mode.inspect}) wins." end merged_roots = (existing.roots + incoming.roots).uniq.freeze Entry.new(gem: incoming.gem, mode: incoming.mode, roots: merged_roots) end |
Instance Method Details
#empty? ⇒ Boolean
112 |
# File 'lib/rigor/configuration/dependencies.rb', line 112 def empty? = @source_inference.empty? |
#to_h ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rigor/configuration/dependencies.rb', line 98 def to_h { "source_inference" => @source_inference.map do |entry| { "gem" => entry.gem, "mode" => entry.mode.to_s, "roots" => entry.roots } end, "budget_per_gem" => @budget_per_gem, "budget_overrun_strategy" => @budget_overrun_strategy.to_s } end |