errors: print more informative and pretty errors

pull/4267/head
Delyan Angelov 2020-04-06 19:39:58 +03:00
parent d865fc26eb
commit 7a99949f0e
3 changed files with 66 additions and 16 deletions

View File

@ -55,19 +55,10 @@ pub fn new_scanner_file(file_path string, comments_mode CommentsMode) &Scanner {
if !os.exists(file_path) {
verror("$file_path doesn't exist")
}
mut raw_text := os.read_file(file_path) or {
verror('scanner: failed to open $file_path')
raw_text := util.read_file( file_path ) or {
verror(err)
return 0
}
// BOM check
if raw_text.len >= 3 {
c_text := raw_text.str
if c_text[0] == 0xEF && c_text[1] == 0xBB && c_text[2] == 0xBF {
// skip three BOM bytes
offset_from_begin := 3
raw_text = tos(c_text[offset_from_begin], vstrlen(c_text) - offset_from_begin)
}
}
mut s := new_scanner(raw_text, comments_mode) // .skip_comments)
// s.init_fmt()
s.file_path = file_path

View File

@ -53,13 +53,56 @@ pub fn formated_error(kind string /*error or warn*/, emsg string, filepath strin
path = path.replace(workdir, '')
}
}
column := 0
position := '${path}:${pos.line_nr+1}:$column:'
// QTODO: retrieve source lines around pos.line_nr and add them here
//
mut column := 0
mut source_context := ''
source := util.read_file(filepath) or { '' }
source_lines := source.split_into_lines()
if source.len > pos.pos {
mut p := pos.pos
for ; p>=0; p-- {
if source[p] == `\r` || source[p] == `\n` {
break
}
}
column = pos.pos - p
}
position := '${path}:${pos.line_nr+1}:$column:'
//
bline := pos.line_nr - error_context_before
aline := pos.line_nr + error_context_after
mut clines := []string
for iline, sline in source_lines {
if iline >= bline && iline <= aline {
mut cline := '${iline+1:5d}| $sline'
if iline == pos.line_nr && emanager.support_color {
cline = term.red( cline )
}
clines << cline
//
if iline == pos.line_nr {
// The pointerline should have the same spaces/tabs as the offending
// line, so that it prints the ^ character exactly on the *same spot*
// where it is needed. That is the reason we can not just
// use strings.repeat(` `, col) to form it.
mut pointerline := []string
for i, c in cline {
if i < column {
x := if c.is_space() { c } else { ` ` }
pointerline << x.str()
continue
}
pointerline << if emanager.support_color { term.bold(term.blue('^')) } else { '^' }
break
}
clines << ' ' + pointerline.join('')
}
}
}
source_context += clines.join('\n')
//
final_position := if emanager.support_color {
term.bold(position) // term.white(position))
term.bold(position)
} else {
position
}
@ -71,7 +114,7 @@ pub fn formated_error(kind string /*error or warn*/, emsg string, filepath strin
term.bold(term.bright_blue(kind))
}
}
final_msg := emsg
final_msg := if emanager.support_color { term.bold(emsg) } else { emsg }
final_context := if source_context.len > 0 { '\n$source_context' } else { '' }
//
return '$final_position $final_kind $final_msg $final_context'.trim_space()

View File

@ -158,3 +158,19 @@ pub fn path_of_executable(path string) string {
}
return path
}
pub fn read_file(file_path string) ?string {
mut raw_text := os.read_file(file_path) or {
return error('failed to open $file_path')
}
// BOM check
if raw_text.len >= 3 {
c_text := raw_text.str
if c_text[0] == 0xEF && c_text[1] == 0xBB && c_text[2] == 0xBF {
// skip three BOM bytes
offset_from_begin := 3
raw_text = tos(c_text[offset_from_begin], vstrlen(c_text) - offset_from_begin)
}
}
return raw_text
}