Module: Aura::Diagnostics
- Defined in:
- lib/aura/diagnostics.rb
Overview
Turns Parslet’s internal failure cause tree into a human-friendly Aura::ParseError with line/column information and a source snippet.
Class Method Summary collapse
-
.deepest_cause(cause) ⇒ Object
Walk to the most specific (deepest) cause so the reported position points at the actual offending token rather than the top-level rule.
- .from_parslet(error, source) ⇒ Aura::ParseError
- .location_for(cause) ⇒ Object
- .position_of(cause) ⇒ Object
- .snippet_for(source, line, column) ⇒ Object
Class Method Details
.deepest_cause(cause) ⇒ Object
Walk to the most specific (deepest) cause so the reported position points at the actual offending token rather than the top-level rule.
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/aura/diagnostics.rb', line 46 def deepest_cause(cause) return nil unless cause current = cause while current.respond_to?(:children) && current.children && !current.children.empty? # Prefer the child with the furthest source position. current = current.children.max_by { |c| position_of(c) || -1 } end current end |
.from_parslet(error, source) ⇒ Aura::ParseError
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/aura/diagnostics.rb', line 33 def from_parslet(error, source) cause = deepest_cause(error.parse_failure_cause) line, column = location_for(cause) = +"Parse error" << " at line #{line}, column #{column}" if line << ": #{cause.to_s}" if cause snippet = snippet_for(source, line, column) << "\n\n#{snippet}" if snippet ParseError.new(, line: line, column: column) end |
.location_for(cause) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/aura/diagnostics.rb', line 57 def location_for(cause) return [nil, nil] unless cause && cause.respond_to?(:source) && cause.source pos = cause.respond_to?(:pos) ? cause.pos : nil return [nil, nil] unless pos line, column = cause.source.line_and_column(pos) [line, column] rescue StandardError [nil, nil] end |
.position_of(cause) ⇒ Object
69 70 71 72 73 |
# File 'lib/aura/diagnostics.rb', line 69 def position_of(cause) cause.respond_to?(:pos) && cause.pos ? cause.pos.bytepos : nil rescue StandardError nil end |
.snippet_for(source, line, column) ⇒ Object
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/aura/diagnostics.rb', line 75 def snippet_for(source, line, column) return nil unless line && column src_line = source.lines[line - 1] return nil unless src_line src_line = src_line.chomp caret = "#{' ' * (column - 1)}^" " #{src_line}\n #{caret}" end |