v.util: improve formatted_error by adding cached_file2sourcelines, so .split_into_lines is called just once (important for long source files with many errors)

pull/11187/head
Delyan Angelov 2021-08-14 22:56:01 +03:00
parent f6d7170e77
commit d540b3f1a8
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
3 changed files with 41 additions and 8 deletions

View File

@ -83,12 +83,11 @@ fn (mut b Builder) myfree() {
// for file in b.parsed_files {
// }
unsafe { b.parsed_files.free() }
unsafe { util.cached_read_source_file('') or {} }
util.free_caches()
}
fn (b &Builder) exit_on_invalid_syntax() {
// clear the source file cache, since it will not be needed anymore
unsafe { util.cached_read_source_file('') or {} }
util.free_caches()
// V should exit with an exit code of 1, when there are errors,
// even when -silent is passed in combination to -check-syntax:
if b.pref.only_check_syntax {

View File

@ -83,9 +83,8 @@ pub fn formatted_error(kind string, omsg string, filepath string, pos token.Posi
}
}
//
source := read_file(filepath) or { '' }
position := '$path:${pos.line_nr + 1}:${mu.max(1, pos.col + 1)}:'
scontext := source_context(kind, source, pos).join('\n')
scontext := source_file_context(kind, filepath, pos).join('\n')
final_position := bold(position)
final_kind := bold(color(kind, kind))
final_msg := emsg
@ -94,12 +93,39 @@ pub fn formatted_error(kind string, omsg string, filepath string, pos token.Posi
return '$final_position $final_kind $final_msg$final_context'.trim_space()
}
pub fn source_context(kind string, source string, pos token.Position) []string {
[heap]
struct LinesCache {
mut:
lines map[string][]string
}
[unsafe]
pub fn cached_file2sourcelines(path string) []string {
mut static cache := &LinesCache(0)
if isnil(cache) {
cache = &LinesCache{}
}
if path.len == 0 {
unsafe { cache.lines.free() }
unsafe { free(cache) }
cache = &LinesCache(0)
return []string{}
}
if res := cache.lines[path] {
return res
}
source := read_file(path) or { '' }
res := source.split_into_lines()
cache.lines[path] = res
return res
}
pub fn source_file_context(kind string, filepath string, pos token.Position) []string {
mut clines := []string{}
if source.len == 0 {
source_lines := unsafe { cached_file2sourcelines(filepath) }
if source_lines.len == 0 {
return clines
}
source_lines := source.split_into_lines()
bline := mu.max(0, pos.line_nr - util.error_context_before)
aline := mu.max(0, mu.min(source_lines.len - 1, pos.line_nr + util.error_context_after))
tab_spaces := ' '

View File

@ -514,3 +514,11 @@ pub fn find_all_v_files(roots []string) ?[]string {
}
return files
}
// free_caches knows about all `util` caches and makes sure that they are freed
// if you add another cached unsafe function using static, do not forget to add
// a mechanism to clear its cache, and call it here.
pub fn free_caches() {
unsafe { cached_read_source_file('') or {} }
unsafe { cached_file2sourcelines('') }
}