Class: Lilac::CLI::CrossRefLinter
- Inherits:
-
Object
- Object
- Lilac::CLI::CrossRefLinter
- Defined in:
- lib/lilac/cli/lint/cross_ref_linter.rb
Overview
Build-time cross-reference linter. Compares identifiers used in
template directives (ivars in data-text, methods in
data-on-X, etc.) against the declarations extracted from
<script type="text/ruby"> by ScriptAnalyzer (AST-based).
Undeclared references emit a diagnostic to stderr (or any
caller-provided IO).
Pure scan: never raises. Returns a Result(warnings:, errors:)
struct — the caller fails the build when errors > 0. All
current checks are warning-level; errors is retained for the
Result contract so future fatal checks can fail the build
without reshaping the API.
Class-shaped (instead of a module of self.lint_* methods) so
the per-call state — analysis, directives, refs_map, component
name, file, IO — lives in ivars rather than being threaded
through every helper as 5 positional arguments.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- SUGGESTION_MAX_DISTANCE =
Tunable: maximum Levenshtein distance for the "Did you mean?" suggestion to be offered. 2 keeps it useful for typos without surfacing unrelated names.
2- LIFECYCLE_METHODS =
Methods the framework calls without an explicit
def name→data-on-Xwiring; never flag them as dead even if no template directive references them. %w[ setup initialize bind_template_hook prepare_setup ].freeze
- RESERVED_REF_NAMES =
data-refnames that collide with Object / Kernel methods —refs.Xthen dispatches to the Ruby method instead ofRefs#method_missing, producing a confusing NoMethodError or silent wrong behaviour. %w[ p puts print pp format sprintf printf gets getc raise throw catch fail exit abort lambda proc method methods caller inspect class send public_send tap then itself nil? frozen? is_a? kind_of? respond_to? object_id hash eql? to_s freeze ].freeze
Class Method Summary collapse
-
.lint(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) ⇒ Object
Public entry.
Instance Method Summary collapse
-
#initialize(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) ⇒ CrossRefLinter
constructor
A new instance of CrossRefLinter.
- #run ⇒ Object
Constructor Details
#initialize(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) ⇒ CrossRefLinter
Returns a new instance of CrossRefLinter.
78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/lilac/cli/lint/cross_ref_linter.rb', line 78 def initialize(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) # Narrow the AST walk to the named class so a multi-class # script (e.g. a page-inline page with sibling components, or # a `.lil` that declares helper classes alongside the # component) doesn't bleed sibling-class declarations into # this component's dead-signal / dead-method checks. @analysis = ScriptAnalyzer.analyze(script_text, class_name: component_name) @directives = directives @component_name = component_name @file = file @refs_map = refs_map @out = out end |
Class Method Details
.lint(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) ⇒ Object
Public entry. Keeps the kwargs-only call shape from before the class refactor so existing callers (PageCompiler's assembler, tests) are unchanged.
70 71 72 73 74 75 76 |
# File 'lib/lilac/cli/lint/cross_ref_linter.rb', line 70 def self.lint(script_text:, directives:, component_name:, file:, refs_map: {}, out: $stderr) new( script_text: script_text, directives: directives, component_name: component_name, file: file, refs_map: refs_map, out: out ).run end |
Instance Method Details
#run ⇒ Object
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/lilac/cli/lint/cross_ref_linter.rb', line 92 def run warnings = 0 warnings += lint_undeclared_signals warnings += lint_undefined_methods warnings += lint_each_without_key warnings += lint_reserved_ref_names warnings += lint_dead_signals warnings += lint_dead_methods Result.new(warnings: warnings, errors: 0) end |