Class: LexerKit::Core::Diagnostic
- Inherits:
-
Object
- Object
- LexerKit::Core::Diagnostic
- Defined in:
- lib/lexer_kit/core/diagnostic.rb
Overview
Diagnostic holds error information with position and notes. It can render a human-readable error message with source context.
Constant Summary collapse
- LEVEL_LABELS =
{ error: "error", warning: "warning", note: "note" }.freeze
- LEVEL_COLORS =
{ error: "\e[1;31m", # bold red warning: "\e[1;33m", # bold yellow note: "\e[1;36m" # bold cyan }.freeze
- RESET =
"\e[0m"- BOLD =
"\e[1m"- BLUE =
"\e[34m"
Instance Attribute Summary collapse
-
#level ⇒ Object
readonly
Returns the value of attribute level.
-
#message ⇒ Object
readonly
Returns the value of attribute message.
-
#notes ⇒ Object
readonly
Returns the value of attribute notes.
-
#span ⇒ Object
readonly
Returns the value of attribute span.
Instance Method Summary collapse
-
#initialize(level:, message:, span:, notes: nil) ⇒ Diagnostic
constructor
A new instance of Diagnostic.
- #inspect ⇒ Object
-
#render(source, color: $stdout.tty?) ⇒ String
Render the diagnostic with source context.
- #to_s ⇒ Object
Constructor Details
#initialize(level:, message:, span:, notes: nil) ⇒ Diagnostic
Returns a new instance of Diagnostic.
30 31 32 33 34 35 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 30 def initialize(level:, message:, span:, notes: nil) @level = level @message = @span = span @notes = notes&.freeze end |
Instance Attribute Details
#level ⇒ Object (readonly)
Returns the value of attribute level.
8 9 10 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 8 def level @level end |
#message ⇒ Object (readonly)
Returns the value of attribute message.
8 9 10 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 8 def @message end |
#notes ⇒ Object (readonly)
Returns the value of attribute notes.
8 9 10 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 8 def notes @notes end |
#span ⇒ Object (readonly)
Returns the value of attribute span.
8 9 10 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 8 def span @span end |
Instance Method Details
#inspect ⇒ Object
98 99 100 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 98 def inspect "#<LexerKit::Core::Diagnostic #{@level} #{@span}: #{@message.inspect}>" end |
#render(source, color: $stdout.tty?) ⇒ String
Render the diagnostic with source context
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 41 def render(source, color: $stdout.tty?) lines = [] line_num, col = source.line_col(@span.start) # Header: filename:line:col: level: message loc = source.filename ? "#{source.filename}:" : "" loc += "#{line_num}:#{col}" if color level_str = "#{LEVEL_COLORS[@level]}#{LEVEL_LABELS[@level]}#{RESET}" lines << "#{BOLD}#{loc}:#{RESET} #{level_str}: #{BOLD}#{@message}#{RESET}" else lines << "#{loc}: #{LEVEL_LABELS[@level]}: #{@message}" end # Source line line_content = source.line_slice(line_num) if line_content line_num_str = line_num.to_s gutter_width = line_num_str.length # Line number gutter lines << if color " #{BLUE}#{line_num_str} |#{RESET} #{line_content}" else " #{line_num_str} | #{line_content}" end # Caret line highlight_len = [@span.len, line_content.length - col + 1].min highlight_len = 1 if highlight_len < 1 carets = "^" + ("~" * (highlight_len - 1)) # rubocop:disable Style/StringConcatenation padding = " " * (col - 1) lines << if color " #{' ' * gutter_width} #{BLUE}|#{RESET} #{padding}#{LEVEL_COLORS[@level]}#{carets}#{RESET}" else " #{' ' * gutter_width} | #{padding}#{carets}" end end # Notes @notes&.each do |note| lines << if color " #{BOLD}note:#{RESET} #{note}" else " note: #{note}" end end lines.join("\n") end |
#to_s ⇒ Object
94 95 96 |
# File 'lib/lexer_kit/core/diagnostic.rb', line 94 def to_s "#{LEVEL_LABELS[@level]}: #{@message} at #{@span}" end |