Class: Epuber::Compiler::Problem

Inherits:
Object
  • Object
show all
Defined in:
lib/epuber/compiler/problem.rb

Defined Under Namespace

Classes: Location

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(level, message, source, location: nil, line: nil, column: nil, length: nil, file_path: nil) ⇒ Problem

Returns a new instance of Problem.



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/epuber/compiler/problem.rb', line 25

def initialize(level, message, source, location: nil, line: nil, column: nil, length: nil, file_path: nil)
  @level = level
  @message = message
  @source = source
  @location = location
  if @location.nil? && line && column
    @location = Location.new(line, column, length)
  end

  @file_path = file_path
end

Instance Attribute Details

#file_pathObject (readonly)

Returns the value of attribute file_path.



23
24
25
# File 'lib/epuber/compiler/problem.rb', line 23

def file_path
  @file_path
end

#levelObject (readonly)

Returns the value of attribute level.



19
20
21
# File 'lib/epuber/compiler/problem.rb', line 19

def level
  @level
end

#locationObject (readonly)

Returns the value of attribute location.



22
23
24
# File 'lib/epuber/compiler/problem.rb', line 22

def location
  @location
end

#messageObject (readonly)

Returns the value of attribute message.



20
21
22
# File 'lib/epuber/compiler/problem.rb', line 20

def message
  @message
end

#sourceObject (readonly)

Returns the value of attribute source.



21
22
23
# File 'lib/epuber/compiler/problem.rb', line 21

def source
  @source
end

Class Method Details

.caret_symbol(indent) ⇒ String

Formats caret symbol with space indent

Parameters:

  • indent (Fixnum)

Returns:

  • (String)


43
44
45
# File 'lib/epuber/compiler/problem.rb', line 43

def self.caret_symbol(indent)
  ' ' * indent + '^'
end

.caret_symbols(indent, length) ⇒ String

Formats caret symbols for indent and length

Parameters:

  • length (Fixnum)
  • indent (Fixnum)

Returns:

  • (String)


54
55
56
57
58
59
60
61
62
63
# File 'lib/epuber/compiler/problem.rb', line 54

def self.caret_symbols(indent, length)
  start_sign = caret_symbol(indent)
  end_sign = if length > 1
               caret_symbol(length-2)
             else
               ''
             end

  "#{start_sign}#{end_sign}"
end

.formatted_match_line(text, location) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/epuber/compiler/problem.rb', line 86

def self.formatted_match_line(text, location)
  pre, matched, post = text_at(text, location)

  pre_line = pre.split("\n").last || ''
  post_line = post.split("\n").first || ''

  pre = match_pre_line = pre_line
  if remove_tabs(match_pre_line).length > 100
    pre = "#{match_pre_line.first(20)}...#{match_pre_line.last(30)}"
  end

  pre = remove_tabs(pre)

  post = if post_line.length > 50
           "#{post_line.first(50)}..."
         else
           post_line
         end

  [pre, matched, post]
end

.remove_tabs(text) ⇒ Object



65
66
67
# File 'lib/epuber/compiler/problem.rb', line 65

def self.remove_tabs(text)
  text.gsub("\t", ' ' * 4)
end

.text_at(text, location) ⇒ Object

Parameters:



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/epuber/compiler/problem.rb', line 71

def self.text_at(text, location)
  line_index = location.line - 1
  column_index = location.column - 1

  lines = text.split("\n")

  line = lines[line_index] || ''
  matched_text = line[column_index ... column_index + location.length] || ''

  pre = (lines[0 ... line_index] + [line[0 ... column_index]]).join("\n")
  post = ([line[column_index + location.length .. line.length]] + (lines[location.line .. lines.count] || [])).join("\n")

  [pre, matched_text, post]
end

Instance Method Details

#to_sObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/epuber/compiler/problem.rb', line 108

def to_s
  pre, match_text, post = self.class.formatted_match_line(@source, @location)

  pointers = self.class.caret_symbols(pre.length, @location.length)
  colored_match_text = match_text.empty? ? match_text : match_text.ansi.red
  column = @location.column
  line = [@location.line, 1].max

  [
    "#{@file_path}:#{line} column: #{column} --- #{@message}",
    '  ' + pre + colored_match_text + post,
    '  ' + pointers,
  ].join("\n")
end