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, the only nested key today is
source_inference:, listing gems whose Ruby implementation Rigor MAY walk during inference instead of
degrading to Dynamic[top] at the dependency boundary.
Parser for the dependencies: YAML section; consumed by Analysis::DependencySourceInference (ADR-10).
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- VALID_MODES =
Walking modes per ADR-10 § "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 consultsIndex#class_to_gemafter a catalog miss. When the receiver's class belongs to a budget-exceeded gem, the call resolves toDynamic[top]rather than falling through to user-class fallback. This silencescall.undefined-methodfor 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 viaConfiguration.deep_merge's special-case fordependencies.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.
70 71 72 73 74 75 76 77 |
# File 'lib/rigor/configuration/dependencies.rb', line 70 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.
53 54 55 |
# File 'lib/rigor/configuration/dependencies.rb', line 53 def budget_overrun_strategy @budget_overrun_strategy end |
#budget_per_gem ⇒ Object (readonly)
Returns the value of attribute budget_per_gem.
53 54 55 |
# File 'lib/rigor/configuration/dependencies.rb', line 53 def budget_per_gem @budget_per_gem end |
#source_inference ⇒ Object (readonly)
Returns the value of attribute source_inference.
53 54 55 |
# File 'lib/rigor/configuration/dependencies.rb', line 53 def source_inference @source_inference end |
#warnings ⇒ Object (readonly)
Returns the value of attribute warnings.
53 54 55 |
# File 'lib/rigor/configuration/dependencies.rb', line 53 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:warningso the user knows theirincludes: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.
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rigor/configuration/dependencies.rb', line 108 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.
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/rigor/configuration/dependencies.rb', line 57 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 = coerce_source_inference(data["source_inference"]) 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
122 123 124 125 126 127 128 129 130 |
# File 'lib/rigor/configuration/dependencies.rb', line 122 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
93 |
# File 'lib/rigor/configuration/dependencies.rb', line 93 def empty? = @source_inference.empty? |
#to_h ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/rigor/configuration/dependencies.rb', line 79 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 |