mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-10 19:19:19 +00:00
check for parse/token errors and print them on run (#8586)
* check for parse/token errors and print them on run * return early on parse fail if errors are not allowed * fix merge issue
This commit is contained in:
parent
c1b088e870
commit
ea76b7b1ee
4 changed files with 67 additions and 9 deletions
|
|
@ -1106,7 +1106,7 @@ fn rocRun(allocs: *Allocators, args: cli_args.RunArgs) !void {
|
||||||
|
|
||||||
// Set up shared memory with ModuleEnv
|
// Set up shared memory with ModuleEnv
|
||||||
std.log.debug("Setting up shared memory for Roc file: {s}", .{args.path});
|
std.log.debug("Setting up shared memory for Roc file: {s}", .{args.path});
|
||||||
const shm_result = setupSharedMemoryWithModuleEnv(allocs, args.path) catch |err| {
|
const shm_result = setupSharedMemoryWithModuleEnv(allocs, args.path, args.allow_errors) catch |err| {
|
||||||
std.log.err("Failed to set up shared memory with ModuleEnv: {}", .{err});
|
std.log.err("Failed to set up shared memory with ModuleEnv: {}", .{err});
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
@ -1461,7 +1461,7 @@ fn writeToWindowsSharedMemory(data: []const u8, total_size: usize) !SharedMemory
|
||||||
/// This parses, canonicalizes, and type-checks all modules, with the resulting ModuleEnvs
|
/// This parses, canonicalizes, and type-checks all modules, with the resulting ModuleEnvs
|
||||||
/// ending up in shared memory because all allocations were done into shared memory.
|
/// ending up in shared memory because all allocations were done into shared memory.
|
||||||
/// Platform type modules have their e_anno_only expressions converted to e_hosted_lambda.
|
/// Platform type modules have their e_anno_only expressions converted to e_hosted_lambda.
|
||||||
pub fn setupSharedMemoryWithModuleEnv(allocs: *Allocators, roc_file_path: []const u8) !SharedMemoryResult {
|
pub fn setupSharedMemoryWithModuleEnv(allocs: *Allocators, roc_file_path: []const u8, allow_errors: bool) !SharedMemoryResult {
|
||||||
// Create shared memory with SharedMemoryAllocator
|
// Create shared memory with SharedMemoryAllocator
|
||||||
const page_size = try SharedMemoryAllocator.getSystemPageSize();
|
const page_size = try SharedMemoryAllocator.getSystemPageSize();
|
||||||
var shm = try SharedMemoryAllocator.create(SHARED_MEMORY_SIZE, page_size);
|
var shm = try SharedMemoryAllocator.create(SHARED_MEMORY_SIZE, page_size);
|
||||||
|
|
@ -1692,10 +1692,39 @@ pub fn setupSharedMemoryWithModuleEnv(allocs: *Allocators, roc_file_path: []cons
|
||||||
app_env.module_name = app_module_name;
|
app_env.module_name = app_module_name;
|
||||||
try app_env.common.calcLineStarts(shm_allocator);
|
try app_env.common.calcLineStarts(shm_allocator);
|
||||||
|
|
||||||
|
var error_count: usize = 0;
|
||||||
|
|
||||||
var app_parse_ast = try parse.parse(&app_env.common, allocs.gpa);
|
var app_parse_ast = try parse.parse(&app_env.common, allocs.gpa);
|
||||||
defer app_parse_ast.deinit(allocs.gpa);
|
defer app_parse_ast.deinit(allocs.gpa);
|
||||||
app_parse_ast.store.emptyScratch();
|
if (app_parse_ast.hasErrors()) {
|
||||||
|
const stderr = stderrWriter();
|
||||||
|
defer stderr.flush() catch {};
|
||||||
|
for (app_parse_ast.tokenize_diagnostics.items) |diagnostic| {
|
||||||
|
error_count += 1;
|
||||||
|
var report = app_parse_ast.tokenizeDiagnosticToReport(diagnostic, allocs.gpa, roc_file_path) catch continue;
|
||||||
|
defer report.deinit();
|
||||||
|
reporting.renderReportToTerminal(&report, stderr, ColorPalette.ANSI, reporting.ReportingConfig.initColorTerminal()) catch continue;
|
||||||
|
}
|
||||||
|
for (app_parse_ast.parse_diagnostics.items) |diagnostic| {
|
||||||
|
error_count += 1;
|
||||||
|
var report = app_parse_ast.parseDiagnosticToReport(&app_env.common, diagnostic, allocs.gpa, roc_file_path) catch continue;
|
||||||
|
defer report.deinit();
|
||||||
|
reporting.renderReportToTerminal(&report, stderr, ColorPalette.ANSI, reporting.ReportingConfig.initColorTerminal()) catch continue;
|
||||||
|
}
|
||||||
|
// If errors are not allowed then we should not move past parsing. return early and let caller handle error/exit
|
||||||
|
if (!allow_errors) {
|
||||||
|
return SharedMemoryResult{
|
||||||
|
.handle = SharedMemoryHandle{
|
||||||
|
.fd = shm.handle,
|
||||||
|
.ptr = shm.base_ptr,
|
||||||
|
.size = shm.getUsedSize(),
|
||||||
|
},
|
||||||
|
.error_count = error_count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app_parse_ast.store.emptyScratch();
|
||||||
try app_env.initCIRFields(app_module_name);
|
try app_env.initCIRFields(app_module_name);
|
||||||
|
|
||||||
var app_module_envs_map = std.AutoHashMap(base.Ident.Idx, Can.AutoImportedType).init(allocs.gpa);
|
var app_module_envs_map = std.AutoHashMap(base.Ident.Idx, Can.AutoImportedType).init(allocs.gpa);
|
||||||
|
|
@ -1851,7 +1880,7 @@ pub fn setupSharedMemoryWithModuleEnv(allocs: *Allocators, roc_file_path: []cons
|
||||||
// Render all type problems (errors and warnings) exactly as roc check would
|
// Render all type problems (errors and warnings) exactly as roc check would
|
||||||
// Count errors so the caller can decide whether to proceed with execution
|
// Count errors so the caller can decide whether to proceed with execution
|
||||||
// Skip rendering in test mode to avoid polluting test output
|
// Skip rendering in test mode to avoid polluting test output
|
||||||
const error_count = if (!builtin.is_test)
|
error_count += if (!builtin.is_test)
|
||||||
renderTypeProblems(allocs.gpa, &app_checker, &app_env, roc_file_path)
|
renderTypeProblems(allocs.gpa, &app_checker, &app_env, roc_file_path)
|
||||||
else
|
else
|
||||||
0;
|
0;
|
||||||
|
|
|
||||||
|
|
@ -1018,7 +1018,7 @@ test "fx platform issue8433" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "run aborts on errors by default" {
|
test "run aborts on type errors by default" {
|
||||||
// Tests that roc run aborts when there are type errors (without --allow-errors)
|
// Tests that roc run aborts when there are type errors (without --allow-errors)
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
|
@ -1039,7 +1039,28 @@ test "run aborts on errors by default" {
|
||||||
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "UNDEFINED VARIABLE") != null);
|
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "UNDEFINED VARIABLE") != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "run with --allow-errors attempts execution despite errors" {
|
test "run aborts on parse errors by default" {
|
||||||
|
// Tests that roc run aborts when there are parse errors (without --allow-errors)
|
||||||
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const run_result = try std.process.Child.run(.{
|
||||||
|
.allocator = allocator,
|
||||||
|
.argv = &[_][]const u8{
|
||||||
|
"./zig-out/bin/roc",
|
||||||
|
"test/fx/parse_error.roc",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defer allocator.free(run_result.stdout);
|
||||||
|
defer allocator.free(run_result.stderr);
|
||||||
|
|
||||||
|
// Should fail with type errors
|
||||||
|
try checkFailure(run_result);
|
||||||
|
|
||||||
|
// Should show the errors
|
||||||
|
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "PARSE ERROR") != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "run with --allow-errors attempts execution despite type errors" {
|
||||||
// Tests that roc run --allow-errors attempts to execute even with type errors
|
// Tests that roc run --allow-errors attempts to execute even with type errors
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ test "integration - shared memory setup and parsing" {
|
||||||
const roc_path = "test/int/app.roc";
|
const roc_path = "test/int/app.roc";
|
||||||
|
|
||||||
// Test that we can set up shared memory with ModuleEnv
|
// Test that we can set up shared memory with ModuleEnv
|
||||||
const shm_result = try main.setupSharedMemoryWithModuleEnv(&allocs, roc_path);
|
const shm_result = try main.setupSharedMemoryWithModuleEnv(&allocs, roc_path, true);
|
||||||
const shm_handle = shm_result.handle;
|
const shm_handle = shm_result.handle;
|
||||||
|
|
||||||
// Clean up shared memory resources
|
// Clean up shared memory resources
|
||||||
|
|
@ -170,7 +170,7 @@ test "integration - compilation pipeline for different platforms" {
|
||||||
|
|
||||||
for (test_apps) |roc_path| {
|
for (test_apps) |roc_path| {
|
||||||
// Test the full compilation pipeline (parse -> canonicalize -> typecheck)
|
// Test the full compilation pipeline (parse -> canonicalize -> typecheck)
|
||||||
const shm_result = main.setupSharedMemoryWithModuleEnv(&allocs, roc_path) catch |err| {
|
const shm_result = main.setupSharedMemoryWithModuleEnv(&allocs, roc_path, true) catch |err| {
|
||||||
std.log.warn("Failed to set up shared memory for {s}: {}\n", .{ roc_path, err });
|
std.log.warn("Failed to set up shared memory for {s}: {}\n", .{ roc_path, err });
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
@ -212,7 +212,7 @@ test "integration - error handling for non-existent file" {
|
||||||
const roc_path = "test/nonexistent/app.roc";
|
const roc_path = "test/nonexistent/app.roc";
|
||||||
|
|
||||||
// This should fail because the file doesn't exist
|
// This should fail because the file doesn't exist
|
||||||
const result = main.setupSharedMemoryWithModuleEnv(&allocs, roc_path);
|
const result = main.setupSharedMemoryWithModuleEnv(&allocs, roc_path, true);
|
||||||
|
|
||||||
// We expect this to fail - the important thing is that it doesn't crash
|
// We expect this to fail - the important thing is that it doesn't crash
|
||||||
if (result) |shm_result| {
|
if (result) |shm_result| {
|
||||||
|
|
|
||||||
8
test/fx/parse_error.roc
Normal file
8
test/fx/parse_error.roc
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
app [main!] {
|
||||||
|
pf: platform "./platform/main.roc",
|
||||||
|
}
|
||||||
|
import pf.Stdout
|
||||||
|
main! = |_args| {
|
||||||
|
Stdout.line!("Hello world")
|
||||||
|
Ok({})
|
||||||
|
}}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue