Module: LcpRuby::Dsl::SourceLocationCapture
- Included in:
- AdvancedFilterBuilder, FormBuilder, IndexBuilder, ModelBuilder, NestedSectionBuilder, PresenterBuilder, SearchBuilder, SectionBuilder, ShowBuilder, ViewGroupBuilder, WorkflowBuilder
- Defined in:
- lib/lcp_ruby/dsl/source_location_capture.rb
Overview
Mixin used by DSL builders to capture the source location (file + line) of the caller when a labeled DSL setter executes.
The captured info travels with the parsed Definition into ‘LcpRuby.loader.*_definitions` so the `i18n_check` walker can point at the exact DSL line that introduced a literal label. YAML-loaded definitions never enter a builder, so they carry `source: nil`; the walker falls back to `definition.source_path` (file context, line nil) for those.
Why ‘caller_locations(2, 1)`: builders are usually called from a `define_*` block, where the call stack at the setter site is `[ setter_method, dsl_block, define_*_loader ]`. We want the DSL block’s frame — the file/line in the host’s ‘config/lcp_ruby/*.rb` source — which sits one frame above the immediate caller.
Class Method Summary collapse
-
.capture_source_loc(skip: 1) ⇒ Object
Returns ‘{ “file” => <abs path>, “line” => <1-based int> }` for the nearest user-DSL frame on the stack, or `nil` when called outside a DSL context.
Class Method Details
.capture_source_loc(skip: 1) ⇒ Object
Returns ‘{ “file” => <abs path>, “line” => <1-based int> }` for the nearest user-DSL frame on the stack, or `nil` when called outside a DSL context.
**String keys are deliberate** — captured source locations travel with the rest of the builder hash through ‘to_hash` →`HashUtils.stringify_deep` → `from_hash`, where Symbol keys get converted to strings anyway. Using strings from the start keeps the iterator-yield shape stable across DSL-loaded vs YAML-loaded definitions.
‘skip` is the number of internal frames between this helper and the DSL block — most builder setters call `capture_source_loc` directly, so the default `skip: 1` puts us one frame above the setter and into the DSL block. Builders calling through a private helper should bump this.
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/lcp_ruby/dsl/source_location_capture.rb', line 39 def capture_source_loc(skip: 1) # `caller_locations(skip + 1, 1)` — the +1 is for the call frame # of `capture_source_loc` itself. location = caller_locations(skip + 1, 1)&.first return nil unless location { "file" => location.absolute_path || location.path, "line" => location.lineno } end |