diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-04-07 20:36:01 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-04-07 20:36:01 -0700 |
| commit | 12087d4cbaab39acadc29716e92765c92b92e28c (patch) | |
| tree | bb5447848ff6bdd3477aac5ab193363fd666abcf /src/Compilation.zig | |
| parent | 4996c2b6a94b042d86b50eb61c9d8d98e63415af (diff) | |
| download | zig-12087d4cbaab39acadc29716e92765c92b92e28c.tar.gz zig-12087d4cbaab39acadc29716e92765c92b92e28c.zip | |
stage2: fix incremental compilation handling of parse errors
Before, incremental compilation would crash when trying to emit compile
errors for the update after introducing a parse error.
Parse errors are handled by not invalidating any existing semantic
analysis. However, only the parse error must be reported, with all the
other errors suppressed. Once the parse error is fixed, the new file can
be treated as an update to the previously-succeeded update.
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 6bf0e004f3..080d4bddaa 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1346,9 +1346,9 @@ pub fn update(self: *Compilation) !void { module.generation += 1; // TODO Detect which source files changed. - // Until then we simulate a full cache miss. Source files could have been loaded for any reason; - // to force a refresh we unload now. - module.root_scope.unload(module.gpa); + // Until then we simulate a full cache miss. Source files could have been loaded + // for any reason; to force a refresh we unload now. + module.unloadFile(module.root_scope); module.failed_root_src_file = null; module.analyzeContainer(&module.root_scope.root_container) catch |err| switch (err) { error.AnalysisFail => { @@ -1362,7 +1362,7 @@ pub fn update(self: *Compilation) !void { // TODO only analyze imports if they are still referenced for (module.import_table.items()) |entry| { - entry.value.unload(module.gpa); + module.unloadFile(entry.value); module.analyzeContainer(&entry.value.root_container) catch |err| switch (err) { error.AnalysisFail => { assert(self.totalErrorCount() != 0); @@ -1432,11 +1432,25 @@ pub fn totalErrorCount(self: *Compilation) usize { var total: usize = self.failed_c_objects.items().len; if (self.bin_file.options.module) |module| { - total += module.failed_decls.count() + - module.emit_h_failed_decls.count() + - module.failed_exports.items().len + + total += module.failed_exports.items().len + module.failed_files.items().len + @boolToInt(module.failed_root_src_file != null); + // Skip errors for Decls within files that failed parsing. + // When a parse error is introduced, we keep all the semantic analysis for + // the previous parse success, including compile errors, but we cannot + // emit them until the file succeeds parsing. + for (module.failed_decls.items()) |entry| { + if (entry.key.container.file_scope.status == .unloaded_parse_failure) { + continue; + } + total += 1; + } + for (module.emit_h_failed_decls.items()) |entry| { + if (entry.key.container.file_scope.status == .unloaded_parse_failure) { + continue; + } + total += 1; + } } // The "no entry point found" error only counts if there are no other errors. @@ -1483,9 +1497,19 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { try AllErrors.add(module, &arena, &errors, entry.value.*); } for (module.failed_decls.items()) |entry| { + if (entry.key.container.file_scope.status == .unloaded_parse_failure) { + // Skip errors for Decls within files that had a parse failure. + // We'll try again once parsing succeeds. + continue; + } try AllErrors.add(module, &arena, &errors, entry.value.*); } for (module.emit_h_failed_decls.items()) |entry| { + if (entry.key.container.file_scope.status == .unloaded_parse_failure) { + // Skip errors for Decls within files that had a parse failure. + // We'll try again once parsing succeeds. + continue; + } try AllErrors.add(module, &arena, &errors, entry.value.*); } for (module.failed_exports.items()) |entry| { |
