Module: Rigor::Effects::SignatureSources
- Defined in:
- lib/rigor/effects/signature_sources.rb
Overview
Everything an effect envelope may be written in, as [buffer name, RBS source] pairs
(ADR-103 WD5 / WD6; #383 / #384).
Two strata, and the exclusion is the point: the project's own signature_paths: tree (or the
sig/ default Environment.for_project falls back to) plus the loader's virtual entries —
which is how rbs-inline's # @rbs %a{…} comments and a plugin's source_rbs synthesis arrive.
Gem-shipped and bundled RBS is deliberately absent: WD6 makes project-authored envelopes the
checked stratum, so a %a{pure} in rbs core cannot bound a project method that shares its key.
Shared by the two passes that read declarations — the envelope check and the annotations-unchecked residual — so the residual can never disagree with the check about what counts as "the project's own signatures".
Constant Summary collapse
- DEFAULT_ROOTS =
Where
Environment.for_projectlooks when nosignature_paths:is configured. Spelled again here rather than required, because the constant is private to Rigor::Environment and a walk over the project's own files has no business reaching into its builder. ["sig"].freeze
- ANNOTATION_HINT =
A cheap text pre-filter for "does this source carry an effect annotation at all". It matches the two spellings the envelope reader honours and nothing else, so a signature tree with no effect annotation is answered by one regex per file and never parsed. It is a ROUTING test, not the grammar —
RbsExtended.parse_effect_annotationis still what decides meaning. /%a\{\s*(?:pure\s*\}|rigor:v1:effect\b)/- VIRTUAL_BUFFER_PATTERN =
A
virtual:<plugin-id>:<source path>buffer is rbs-inline's (or a plugin's) synthesized RBS for a Ruby file the author actually wrote in. Naming that file is what a reader can act on, so the synthetic prefix comes off before the name is made project-relative. /\Avirtual:[^:]*:/
Class Method Summary collapse
-
.annotated_carrier(virtual_rbs) ⇒ Array<Array(String, String)>
The FIRST annotated virtual entry, as a
collect-shaped one-element array (or an empty one). - .collect(signature_paths:, virtual_rbs: nil) ⇒ Array<Array(String, String)>
-
.first_annotated(sources) ⇒ Object
The first
[name, content, line]carrying an effect annotation, or nil. - .roots(signature_paths) ⇒ Object
-
.source_path(name) ⇒ Object
The path a reader can open, for a buffer name from SignatureSources.collect: the
.rbsfile as configured, or the.rbfile behind avirtual:buffer, project-relative either way.
Class Method Details
.annotated_carrier(virtual_rbs) ⇒ Array<Array(String, String)>
The FIRST annotated virtual entry, as a collect-shaped one-element array (or an empty one).
#441 — the analysis paths use this to hand the annotations-unchecked residual the inline stratum of a run that resolved an environment but never stored it. Reduced to one entry on purpose: the residual reports one annotation per run, so the carrier a run holds past the environment's own lifetime is a single synthesized buffer rather than the project's whole virtual tree.
70 71 72 73 74 75 |
# File 'lib/rigor/effects/signature_sources.rb', line 70 def annotated_carrier(virtual_rbs) Array(virtual_rbs).each do |name, content| return [[name.to_s, content.to_s]] if ANNOTATION_HINT.match?(content) end [].freeze end |
.collect(signature_paths:, virtual_rbs: nil) ⇒ Array<Array(String, String)>
47 48 49 50 51 52 53 54 55 |
# File 'lib/rigor/effects/signature_sources.rb', line 47 def collect(signature_paths:, virtual_rbs: nil) files = roots(signature_paths).flat_map { |root| Dir.glob(File.join(root.to_s, "**", "*.rbs")).sort } sources = files.filter_map do |path| [path, File.read(path)] rescue StandardError nil end sources + Array(virtual_rbs).map { |name, content| [name.to_s, content.to_s] } end |
.first_annotated(sources) ⇒ Object
The first [name, content, line] carrying an effect annotation, or nil. Line numbers are
1-based and count into content, which for a virtual: buffer is the SYNTHESIZED text — the
caller re-anchors it against the Ruby file when that matters.
80 81 82 83 84 85 86 87 |
# File 'lib/rigor/effects/signature_sources.rb', line 80 def first_annotated(sources) sources.each do |name, content| content.each_line.with_index(1) do |line, number| return [name, content, number] if ANNOTATION_HINT.match?(line) end end nil end |
.roots(signature_paths) ⇒ Object
57 58 59 |
# File 'lib/rigor/effects/signature_sources.rb', line 57 def roots(signature_paths) signature_paths.nil? || signature_paths.empty? ? DEFAULT_ROOTS : signature_paths end |
.source_path(name) ⇒ Object
The path a reader can open, for a buffer name from collect: the .rbs file as configured,
or the .rb file behind a virtual: buffer, project-relative either way.
38 39 40 41 42 |
# File 'lib/rigor/effects/signature_sources.rb', line 38 def source_path(name) stripped = name.to_s.sub(VIRTUAL_BUFFER_PATTERN, "") root = "#{Dir.pwd}#{File::SEPARATOR}" stripped.start_with?(root) ? stripped[root.length..] : stripped end |