Module: MilkTea::ErrorFormatter

Defined in:
lib/milk_tea/tooling/error_formatter.rb

Class Method Summary collapse

Class Method Details

.error_suggestion_lines(error, color, bold, reset) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/milk_tea/tooling/error_formatter.rb', line 59

def self.error_suggestion_lines(error, color, bold, reset)
  suggestion = error.respond_to?(:suggestion) ? error.suggestion : nil
  return [] unless suggestion

  suggestions = suggestion.is_a?(Array) ? suggestion : [suggestion]
  suggestions.map do |s|
    label = color ? "#{bold}= help:#{reset}" : "= help:"
    "  #{label} #{s}"
  end
end

.format(error, path: nil, source: nil, color: true) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/milk_tea/tooling/error_formatter.rb', line 5

def self.format(error, path: nil, source: nil, color: true)
  error_message = error.respond_to?(:message) ? error.message : error.to_s
  return error_message unless error.respond_to?(:line) && error.line
  return error_message unless error.respond_to?(:column) && error.column

  path ||= error.respond_to?(:path) ? error.path : nil
  return error_message unless path

  line = error.line.to_i
  column = error.column.to_i
  length = error.respond_to?(:length) ? error.length.to_i : 0
  severity = error.respond_to?(:severity) ? error.severity : :error
  code = error.respond_to?(:code) ? error.code : nil

  source ||= read_source(path)
  return "#{severity_label(severity)}: #{error_message} at #{path}:#{line}:#{column}" unless source

  source_lines = source.split("\n", -1)
  source_line = source_lines[line - 1] || ""
  stripped = source_line.gsub(/\t/, " ")

  indent = " " * [column - 1, 0].max
  highlight = if length && length > 1
                "^" + "~" * (length - 1)
              else
                "^"
              end

  bold  = color ? "\e[1m"  : ""
  red   = color ? "\e[31m" : ""
  yellow = color ? "\e[33m" : ""
  cyan  = color ? "\e[36m" : ""
  reset = color ? "\e[0m"  : ""

  sev_color, sev_text = case severity
                        when :error   then [red,    "error"]
                        when :warning then [yellow, "warning"]
                        when :info    then [cyan,   "info"]
                        when :hint    then [cyan,   "hint"]
                        else               [red,    "error"]
                        end

  code_text = code ? "#{cyan}[#{code}]#{reset}" : ""

  [
    "#{bold}#{sev_color}#{sev_text}#{code_text}#{reset}: #{error_message}",
    "  #{bold}-->#{reset} #{path}:#{line}:#{column}",
    "   #{bold}|#{reset}",
    "#{line.to_s.rjust(5)} #{bold}|#{reset} #{stripped}",
    "      #{bold}|#{reset} #{sev_color}#{indent}#{highlight}#{reset}",
    *error_suggestion_lines(error, color, bold, reset),
  ].join("\n")
end

.read_source(path) ⇒ Object



70
71
72
73
74
# File 'lib/milk_tea/tooling/error_formatter.rb', line 70

def self.read_source(path)
  File.read(path)
rescue Errno::ENOENT, Errno::EISDIR
  nil
end

.severity_label(severity) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/milk_tea/tooling/error_formatter.rb', line 76

def self.severity_label(severity)
  case severity
  when :error   then "error"
  when :warning then "warning"
  when :info    then "info"
  when :hint    then "hint"
  else               "error"
  end
end