| author | |
| committer | |
| log | d661f0f35ba5c5600c3547b52e6fbca34991702b |
| tree | 76d76dbd62943e749a73936631e62159784e2a02 |
| parent | b116063e02bf2bb1975f5ae862fcd25f8fbeda09 |
See #190639 files changed, 778 insertions(+), 670 deletions(-)
lib/build_runner.zig+1-1| ... | @@ -13,7 +13,7 @@ const Step = std.Build.Step; | ... | @@ -13,7 +13,7 @@ const Step = std.Build.Step; |
| 13 | pub const dependencies = @import("@dependencies"); | 13 | pub const dependencies = @import("@dependencies"); |
| 14 | 14 | ||
| 15 | pub fn main() !void { | 15 | pub fn main() !void { |
| 16 | // Here we use an ArenaAllocator backed by a DirectAllocator because a build is a short-lived, | 16 | // Here we use an ArenaAllocator backed by a page allocator because a build is a short-lived, |
| 17 | // one shot program. We don't need to waste time freeing memory and finding places to squish | 17 | // one shot program. We don't need to waste time freeing memory and finding places to squish |
| 18 | // bytes into. So we free everything all at once at the very end. | 18 | // bytes into. So we free everything all at once at the very end. |
| 19 | var single_threaded_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 19 | var single_threaded_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
lib/std/zig.zig+106-4| ... | @@ -1,6 +1,3 @@ | ... | @@ -1,6 +1,3 @@ |
| 1 | /// Implementation of `zig fmt`. | ||
| 2 | pub const fmt = @import("zig/fmt.zig"); | ||
| 3 | |||
| 4 | pub const ErrorBundle = @import("zig/ErrorBundle.zig"); | 1 | pub const ErrorBundle = @import("zig/ErrorBundle.zig"); |
| 5 | pub const Server = @import("zig/Server.zig"); | 2 | pub const Server = @import("zig/Server.zig"); |
| 6 | pub const Client = @import("zig/Client.zig"); | 3 | pub const Client = @import("zig/Client.zig"); |
| ... | @@ -30,6 +27,36 @@ pub const c_translation = @import("zig/c_translation.zig"); | ... | @@ -30,6 +27,36 @@ pub const c_translation = @import("zig/c_translation.zig"); |
| 30 | pub const SrcHasher = std.crypto.hash.Blake3; | 27 | pub const SrcHasher = std.crypto.hash.Blake3; |
| 31 | pub const SrcHash = [16]u8; | 28 | pub const SrcHash = [16]u8; |
| 32 | 29 | ||
| 30 | pub const Color = enum { | ||
| 31 | /// Determine whether stderr is a terminal or not automatically. | ||
| 32 | auto, | ||
| 33 | /// Assume stderr is not a terminal. | ||
| 34 | off, | ||
| 35 | /// Assume stderr is a terminal. | ||
| 36 | on, | ||
| 37 | |||
| 38 | pub fn get_tty_conf(color: Color) std.io.tty.Config { | ||
| 39 | return switch (color) { | ||
| 40 | .auto => std.io.tty.detectConfig(std.io.getStdErr()), | ||
| 41 | .on => .escape_codes, | ||
| 42 | .off => .no_color, | ||
| 43 | }; | ||
| 44 | } | ||
| 45 | |||
| 46 | pub fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { | ||
| 47 | const ttyconf = get_tty_conf(color); | ||
| 48 | return .{ | ||
| 49 | .ttyconf = ttyconf, | ||
| 50 | .include_source_line = ttyconf != .no_color, | ||
| 51 | .include_reference_trace = ttyconf != .no_color, | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | }; | ||
| 55 | |||
| 56 | /// There are many assumptions in the entire codebase that Zig source files can | ||
| 57 | /// be byte-indexed with a u32 integer. | ||
| 58 | pub const max_src_size = std.math.maxInt(u32); | ||
| 59 | |||
| 33 | pub fn hashSrc(src: []const u8) SrcHash { | 60 | pub fn hashSrc(src: []const u8) SrcHash { |
| 34 | var out: SrcHash = undefined; | 61 | var out: SrcHash = undefined; |
| 35 | SrcHasher.hash(src, &out, .{}); | 62 | SrcHasher.hash(src, &out, .{}); |
| ... | @@ -801,6 +828,78 @@ test isValidId { | ... | @@ -801,6 +828,78 @@ test isValidId { |
| 801 | try std.testing.expect(isValidId("i386")); | 828 | try std.testing.expect(isValidId("i386")); |
| 802 | } | 829 | } |
| 803 | 830 | ||
| 831 | pub fn readSourceFileToEndAlloc( | ||
| 832 | allocator: Allocator, | ||
| 833 | input: std.fs.File, | ||
| 834 | size_hint: ?usize, | ||
| 835 | ) ![:0]u8 { | ||
| 836 | const source_code = input.readToEndAllocOptions( | ||
| 837 | allocator, | ||
| 838 | max_src_size, | ||
| 839 | size_hint, | ||
| 840 | @alignOf(u16), | ||
| 841 | 0, | ||
| 842 | ) catch |err| switch (err) { | ||
| 843 | error.ConnectionResetByPeer => unreachable, | ||
| 844 | error.ConnectionTimedOut => unreachable, | ||
| 845 | error.NotOpenForReading => unreachable, | ||
| 846 | else => |e| return e, | ||
| 847 | }; | ||
| 848 | errdefer allocator.free(source_code); | ||
| 849 | |||
| 850 | // Detect unsupported file types with their Byte Order Mark | ||
| 851 | const unsupported_boms = [_][]const u8{ | ||
| 852 | "\xff\xfe\x00\x00", // UTF-32 little endian | ||
| 853 | "\xfe\xff\x00\x00", // UTF-32 big endian | ||
| 854 | "\xfe\xff", // UTF-16 big endian | ||
| 855 | }; | ||
| 856 | for (unsupported_boms) |bom| { | ||
| 857 | if (std.mem.startsWith(u8, source_code, bom)) { | ||
| 858 | return error.UnsupportedEncoding; | ||
| 859 | } | ||
| 860 | } | ||
| 861 | |||
| 862 | // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 | ||
| 863 | if (std.mem.startsWith(u8, source_code, "\xff\xfe")) { | ||
| 864 | const source_code_utf16_le = std.mem.bytesAsSlice(u16, source_code); | ||
| 865 | const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(allocator, source_code_utf16_le) catch |err| switch (err) { | ||
| 866 | error.DanglingSurrogateHalf => error.UnsupportedEncoding, | ||
| 867 | error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, | ||
| 868 | error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, | ||
| 869 | else => |e| return e, | ||
| 870 | }; | ||
| 871 | |||
| 872 | allocator.free(source_code); | ||
| 873 | return source_code_utf8; | ||
| 874 | } | ||
| 875 | |||
| 876 | return source_code; | ||
| 877 | } | ||
| 878 | |||
| 879 | pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { | ||
| 880 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 881 | try wip_errors.init(gpa); | ||
| 882 | defer wip_errors.deinit(); | ||
| 883 | |||
| 884 | try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); | ||
| 885 | |||
| 886 | var error_bundle = try wip_errors.toOwnedBundle(""); | ||
| 887 | defer error_bundle.deinit(gpa); | ||
| 888 | error_bundle.renderToStdErr(color.renderOptions()); | ||
| 889 | } | ||
| 890 | |||
| 891 | pub fn putAstErrorsIntoBundle( | ||
| 892 | gpa: Allocator, | ||
| 893 | tree: Ast, | ||
| 894 | path: []const u8, | ||
| 895 | wip_errors: *std.zig.ErrorBundle.Wip, | ||
| 896 | ) Allocator.Error!void { | ||
| 897 | var zir = try AstGen.generate(gpa, tree); | ||
| 898 | defer zir.deinit(gpa); | ||
| 899 | |||
| 900 | try wip_errors.addZirErrorMessages(zir, tree, tree.source, path); | ||
| 901 | } | ||
| 902 | |||
| 804 | test { | 903 | test { |
| 805 | _ = Ast; | 904 | _ = Ast; |
| 806 | _ = AstRlAnnotate; | 905 | _ = AstRlAnnotate; |
| ... | @@ -808,9 +907,12 @@ test { | ... | @@ -808,9 +907,12 @@ test { |
| 808 | _ = Client; | 907 | _ = Client; |
| 809 | _ = ErrorBundle; | 908 | _ = ErrorBundle; |
| 810 | _ = Server; | 909 | _ = Server; |
| 811 | _ = fmt; | ||
| 812 | _ = number_literal; | 910 | _ = number_literal; |
| 813 | _ = primitives; | 911 | _ = primitives; |
| 814 | _ = string_literal; | 912 | _ = string_literal; |
| 815 | _ = system; | 913 | _ = system; |
| 914 | |||
| 915 | // This is not standard library API; it is the standalone executable | ||
| 916 | // implementation of `zig fmt`. | ||
| 917 | _ = @import("zig/fmt.zig"); | ||
| 816 | } | 918 | } |
lib/std/zig/Ast.zig+41-1| ... | @@ -32,6 +32,12 @@ pub const Location = struct { | ... | @@ -32,6 +32,12 @@ pub const Location = struct { |
| 32 | line_end: usize, | 32 | line_end: usize, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | pub const Span = struct { | ||
| 36 | start: u32, | ||
| 37 | end: u32, | ||
| 38 | main: u32, | ||
| 39 | }; | ||
| 40 | |||
| 35 | pub fn deinit(tree: *Ast, gpa: Allocator) void { | 41 | pub fn deinit(tree: *Ast, gpa: Allocator) void { |
| 36 | tree.tokens.deinit(gpa); | 42 | tree.tokens.deinit(gpa); |
| 37 | tree.nodes.deinit(gpa); | 43 | tree.nodes.deinit(gpa); |
| ... | @@ -3533,6 +3539,39 @@ pub const Node = struct { | ... | @@ -3533,6 +3539,39 @@ pub const Node = struct { |
| 3533 | }; | 3539 | }; |
| 3534 | }; | 3540 | }; |
| 3535 | 3541 | ||
| 3542 | pub fn nodeToSpan(tree: *const Ast, node: u32) Span { | ||
| 3543 | return tokensToSpan( | ||
| 3544 | tree, | ||
| 3545 | tree.firstToken(node), | ||
| 3546 | tree.lastToken(node), | ||
| 3547 | tree.nodes.items(.main_token)[node], | ||
| 3548 | ); | ||
| 3549 | } | ||
| 3550 | |||
| 3551 | pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { | ||
| 3552 | return tokensToSpan(tree, token, token, token); | ||
| 3553 | } | ||
| 3554 | |||
| 3555 | pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { | ||
| 3556 | const token_starts = tree.tokens.items(.start); | ||
| 3557 | var start_tok = start; | ||
| 3558 | var end_tok = end; | ||
| 3559 | |||
| 3560 | if (tree.tokensOnSameLine(start, end)) { | ||
| 3561 | // do nothing | ||
| 3562 | } else if (tree.tokensOnSameLine(start, main)) { | ||
| 3563 | end_tok = main; | ||
| 3564 | } else if (tree.tokensOnSameLine(main, end)) { | ||
| 3565 | start_tok = main; | ||
| 3566 | } else { | ||
| 3567 | start_tok = main; | ||
| 3568 | end_tok = main; | ||
| 3569 | } | ||
| 3570 | const start_off = token_starts[start_tok]; | ||
| 3571 | const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | ||
| 3572 | return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; | ||
| 3573 | } | ||
| 3574 | |||
| 3536 | const std = @import("../std.zig"); | 3575 | const std = @import("../std.zig"); |
| 3537 | const assert = std.debug.assert; | 3576 | const assert = std.debug.assert; |
| 3538 | const testing = std.testing; | 3577 | const testing = std.testing; |
| ... | @@ -3544,5 +3583,6 @@ const Parse = @import("Parse.zig"); | ... | @@ -3544,5 +3583,6 @@ const Parse = @import("Parse.zig"); |
| 3544 | const private_render = @import("./render.zig"); | 3583 | const private_render = @import("./render.zig"); |
| 3545 | 3584 | ||
| 3546 | test { | 3585 | test { |
| 3547 | testing.refAllDecls(@This()); | 3586 | _ = Parse; |
| 3587 | _ = private_render; | ||
| 3548 | } | 3588 | } |
lib/std/zig/ErrorBundle.zig+84| ... | @@ -459,6 +459,90 @@ pub const Wip = struct { | ... | @@ -459,6 +459,90 @@ pub const Wip = struct { |
| 459 | return @intCast(wip.extra.items.len - notes_len); | 459 | return @intCast(wip.extra.items.len - notes_len); |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | pub fn addZirErrorMessages( | ||
| 463 | eb: *ErrorBundle.Wip, | ||
| 464 | zir: std.zig.Zir, | ||
| 465 | tree: std.zig.Ast, | ||
| 466 | source: [:0]const u8, | ||
| 467 | src_path: []const u8, | ||
| 468 | ) !void { | ||
| 469 | const Zir = std.zig.Zir; | ||
| 470 | const payload_index = zir.extra[@intFromEnum(Zir.ExtraIndex.compile_errors)]; | ||
| 471 | assert(payload_index != 0); | ||
| 472 | |||
| 473 | const header = zir.extraData(Zir.Inst.CompileErrors, payload_index); | ||
| 474 | const items_len = header.data.items_len; | ||
| 475 | var extra_index = header.end; | ||
| 476 | for (0..items_len) |_| { | ||
| 477 | const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); | ||
| 478 | extra_index = item.end; | ||
| 479 | const err_span = blk: { | ||
| 480 | if (item.data.node != 0) { | ||
| 481 | break :blk tree.nodeToSpan(item.data.node); | ||
| 482 | } | ||
| 483 | const token_starts = tree.tokens.items(.start); | ||
| 484 | const start = token_starts[item.data.token] + item.data.byte_offset; | ||
| 485 | const end = start + @as(u32, @intCast(tree.tokenSlice(item.data.token).len)) - item.data.byte_offset; | ||
| 486 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | ||
| 487 | }; | ||
| 488 | const err_loc = std.zig.findLineColumn(source, err_span.main); | ||
| 489 | |||
| 490 | { | ||
| 491 | const msg = zir.nullTerminatedString(item.data.msg); | ||
| 492 | try eb.addRootErrorMessage(.{ | ||
| 493 | .msg = try eb.addString(msg), | ||
| 494 | .src_loc = try eb.addSourceLocation(.{ | ||
| 495 | .src_path = try eb.addString(src_path), | ||
| 496 | .span_start = err_span.start, | ||
| 497 | .span_main = err_span.main, | ||
| 498 | .span_end = err_span.end, | ||
| 499 | .line = @intCast(err_loc.line), | ||
| 500 | .column = @intCast(err_loc.column), | ||
| 501 | .source_line = try eb.addString(err_loc.source_line), | ||
| 502 | }), | ||
| 503 | .notes_len = item.data.notesLen(zir), | ||
| 504 | }); | ||
| 505 | } | ||
| 506 | |||
| 507 | if (item.data.notes != 0) { | ||
| 508 | const notes_start = try eb.reserveNotes(item.data.notes); | ||
| 509 | const block = zir.extraData(Zir.Inst.Block, item.data.notes); | ||
| 510 | const body = zir.extra[block.end..][0..block.data.body_len]; | ||
| 511 | for (notes_start.., body) |note_i, body_elem| { | ||
| 512 | const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); | ||
| 513 | const msg = zir.nullTerminatedString(note_item.data.msg); | ||
| 514 | const span = blk: { | ||
| 515 | if (note_item.data.node != 0) { | ||
| 516 | break :blk tree.nodeToSpan(note_item.data.node); | ||
| 517 | } | ||
| 518 | const token_starts = tree.tokens.items(.start); | ||
| 519 | const start = token_starts[note_item.data.token] + note_item.data.byte_offset; | ||
| 520 | const end = start + @as(u32, @intCast(tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset; | ||
| 521 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | ||
| 522 | }; | ||
| 523 | const loc = std.zig.findLineColumn(source, span.main); | ||
| 524 | |||
| 525 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | ||
| 526 | .msg = try eb.addString(msg), | ||
| 527 | .src_loc = try eb.addSourceLocation(.{ | ||
| 528 | .src_path = try eb.addString(src_path), | ||
| 529 | .span_start = span.start, | ||
| 530 | .span_main = span.main, | ||
| 531 | .span_end = span.end, | ||
| 532 | .line = @intCast(loc.line), | ||
| 533 | .column = @intCast(loc.column), | ||
| 534 | .source_line = if (loc.eql(err_loc)) | ||
| 535 | 0 | ||
| 536 | else | ||
| 537 | try eb.addString(loc.source_line), | ||
| 538 | }), | ||
| 539 | .notes_len = 0, // TODO rework this function to be recursive | ||
| 540 | })); | ||
| 541 | } | ||
| 542 | } | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 462 | fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { | 546 | fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { |
| 463 | const other_msg = other.getErrorMessage(msg_index); | 547 | const other_msg = other.getErrorMessage(msg_index); |
| 464 | const src_loc = try wip.addOtherSourceLocation(other, other_msg.src_loc); | 548 | const src_loc = try wip.addOtherSourceLocation(other, other_msg.src_loc); |
lib/std/zig/fmt.zig+342-1| ... | @@ -1 +1,342 @@ | ... | @@ -1 +1,342 @@ |
| 1 | const std = @import("../std.zig"); | 1 | const std = @import("std"); |
| 2 | const mem = std.mem; | ||
| 3 | const fs = std.fs; | ||
| 4 | const process = std.process; | ||
| 5 | const Allocator = std.mem.Allocator; | ||
| 6 | const warn = std.log.warn; | ||
| 7 | const Color = std.zig.Color; | ||
| 8 | |||
| 9 | const usage_fmt = | ||
| 10 | \\Usage: zig fmt [file]... | ||
| 11 | \\ | ||
| 12 | \\ Formats the input files and modifies them in-place. | ||
| 13 | \\ Arguments can be files or directories, which are searched | ||
| 14 | \\ recursively. | ||
| 15 | \\ | ||
| 16 | \\Options: | ||
| 17 | \\ -h, --help Print this help and exit | ||
| 18 | \\ --color [auto|off|on] Enable or disable colored error messages | ||
| 19 | \\ --stdin Format code from stdin; output to stdout | ||
| 20 | \\ --check List non-conforming files and exit with an error | ||
| 21 | \\ if the list is non-empty | ||
| 22 | \\ --ast-check Run zig ast-check on every file | ||
| 23 | \\ --exclude [file] Exclude file or directory from formatting | ||
| 24 | \\ | ||
| 25 | \\ | ||
| 26 | ; | ||
| 27 | |||
| 28 | const Fmt = struct { | ||
| 29 | seen: SeenMap, | ||
| 30 | any_error: bool, | ||
| 31 | check_ast: bool, | ||
| 32 | color: Color, | ||
| 33 | gpa: Allocator, | ||
| 34 | arena: Allocator, | ||
| 35 | out_buffer: std.ArrayList(u8), | ||
| 36 | |||
| 37 | const SeenMap = std.AutoHashMap(fs.File.INode, void); | ||
| 38 | }; | ||
| 39 | |||
| 40 | pub fn main() !void { | ||
| 41 | var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); | ||
| 42 | defer arena_instance.deinit(); | ||
| 43 | const arena = arena_instance.allocator(); | ||
| 44 | const gpa = arena; | ||
| 45 | |||
| 46 | const args = try process.argsAlloc(arena); | ||
| 47 | |||
| 48 | var color: Color = .auto; | ||
| 49 | var stdin_flag: bool = false; | ||
| 50 | var check_flag: bool = false; | ||
| 51 | var check_ast_flag: bool = false; | ||
| 52 | var input_files = std.ArrayList([]const u8).init(gpa); | ||
| 53 | defer input_files.deinit(); | ||
| 54 | var excluded_files = std.ArrayList([]const u8).init(gpa); | ||
| 55 | defer excluded_files.deinit(); | ||
| 56 | |||
| 57 | { | ||
| 58 | var i: usize = 1; | ||
| 59 | while (i < args.len) : (i += 1) { | ||
| 60 | const arg = args[i]; | ||
| 61 | if (mem.startsWith(u8, arg, "-")) { | ||
| 62 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { | ||
| 63 | const stdout = std.io.getStdOut().writer(); | ||
| 64 | try stdout.writeAll(usage_fmt); | ||
| 65 | return process.cleanExit(); | ||
| 66 | } else if (mem.eql(u8, arg, "--color")) { | ||
| 67 | if (i + 1 >= args.len) { | ||
| 68 | fatal("expected [auto|on|off] after --color", .{}); | ||
| 69 | } | ||
| 70 | i += 1; | ||
| 71 | const next_arg = args[i]; | ||
| 72 | color = std.meta.stringToEnum(Color, next_arg) orelse { | ||
| 73 | fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); | ||
| 74 | }; | ||
| 75 | } else if (mem.eql(u8, arg, "--stdin")) { | ||
| 76 | stdin_flag = true; | ||
| 77 | } else if (mem.eql(u8, arg, "--check")) { | ||
| 78 | check_flag = true; | ||
| 79 | } else if (mem.eql(u8, arg, "--ast-check")) { | ||
| 80 | check_ast_flag = true; | ||
| 81 | } else if (mem.eql(u8, arg, "--exclude")) { | ||
| 82 | if (i + 1 >= args.len) { | ||
| 83 | fatal("expected parameter after --exclude", .{}); | ||
| 84 | } | ||
| 85 | i += 1; | ||
| 86 | const next_arg = args[i]; | ||
| 87 | try excluded_files.append(next_arg); | ||
| 88 | } else { | ||
| 89 | fatal("unrecognized parameter: '{s}'", .{arg}); | ||
| 90 | } | ||
| 91 | } else { | ||
| 92 | try input_files.append(arg); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | if (stdin_flag) { | ||
| 98 | if (input_files.items.len != 0) { | ||
| 99 | fatal("cannot use --stdin with positional arguments", .{}); | ||
| 100 | } | ||
| 101 | |||
| 102 | const stdin = std.io.getStdIn(); | ||
| 103 | const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| { | ||
| 104 | fatal("unable to read stdin: {}", .{err}); | ||
| 105 | }; | ||
| 106 | defer gpa.free(source_code); | ||
| 107 | |||
| 108 | var tree = std.zig.Ast.parse(gpa, source_code, .zig) catch |err| { | ||
| 109 | fatal("error parsing stdin: {}", .{err}); | ||
| 110 | }; | ||
| 111 | defer tree.deinit(gpa); | ||
| 112 | |||
| 113 | if (check_ast_flag) { | ||
| 114 | var zir = try std.zig.AstGen.generate(gpa, tree); | ||
| 115 | |||
| 116 | if (zir.hasCompileErrors()) { | ||
| 117 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 118 | try wip_errors.init(gpa); | ||
| 119 | defer wip_errors.deinit(); | ||
| 120 | try wip_errors.addZirErrorMessages(zir, tree, source_code, "<stdin>"); | ||
| 121 | var error_bundle = try wip_errors.toOwnedBundle(""); | ||
| 122 | defer error_bundle.deinit(gpa); | ||
| 123 | error_bundle.renderToStdErr(color.renderOptions()); | ||
| 124 | process.exit(2); | ||
| 125 | } | ||
| 126 | } else if (tree.errors.len != 0) { | ||
| 127 | try std.zig.printAstErrorsToStderr(gpa, tree, "<stdin>", color); | ||
| 128 | process.exit(2); | ||
| 129 | } | ||
| 130 | const formatted = try tree.render(gpa); | ||
| 131 | defer gpa.free(formatted); | ||
| 132 | |||
| 133 | if (check_flag) { | ||
| 134 | const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code)); | ||
| 135 | process.exit(code); | ||
| 136 | } | ||
| 137 | |||
| 138 | return std.io.getStdOut().writeAll(formatted); | ||
| 139 | } | ||
| 140 | |||
| 141 | if (input_files.items.len == 0) { | ||
| 142 | fatal("expected at least one source file argument", .{}); | ||
| 143 | } | ||
| 144 | |||
| 145 | var fmt = Fmt{ | ||
| 146 | .gpa = gpa, | ||
| 147 | .arena = arena, | ||
| 148 | .seen = Fmt.SeenMap.init(gpa), | ||
| 149 | .any_error = false, | ||
| 150 | .check_ast = check_ast_flag, | ||
| 151 | .color = color, | ||
| 152 | .out_buffer = std.ArrayList(u8).init(gpa), | ||
| 153 | }; | ||
| 154 | defer fmt.seen.deinit(); | ||
| 155 | defer fmt.out_buffer.deinit(); | ||
| 156 | |||
| 157 | // Mark any excluded files/directories as already seen, | ||
| 158 | // so that they are skipped later during actual processing | ||
| 159 | for (excluded_files.items) |file_path| { | ||
| 160 | const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { | ||
| 161 | error.FileNotFound => continue, | ||
| 162 | // On Windows, statFile does not work for directories | ||
| 163 | error.IsDir => dir: { | ||
| 164 | var dir = try fs.cwd().openDir(file_path, .{}); | ||
| 165 | defer dir.close(); | ||
| 166 | break :dir try dir.stat(); | ||
| 167 | }, | ||
| 168 | else => |e| return e, | ||
| 169 | }; | ||
| 170 | try fmt.seen.put(stat.inode, {}); | ||
| 171 | } | ||
| 172 | |||
| 173 | for (input_files.items) |file_path| { | ||
| 174 | try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); | ||
| 175 | } | ||
| 176 | if (fmt.any_error) { | ||
| 177 | process.exit(1); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | const FmtError = error{ | ||
| 182 | SystemResources, | ||
| 183 | OperationAborted, | ||
| 184 | IoPending, | ||
| 185 | BrokenPipe, | ||
| 186 | Unexpected, | ||
| 187 | WouldBlock, | ||
| 188 | FileClosed, | ||
| 189 | DestinationAddressRequired, | ||
| 190 | DiskQuota, | ||
| 191 | FileTooBig, | ||
| 192 | InputOutput, | ||
| 193 | NoSpaceLeft, | ||
| 194 | AccessDenied, | ||
| 195 | OutOfMemory, | ||
| 196 | RenameAcrossMountPoints, | ||
| 197 | ReadOnlyFileSystem, | ||
| 198 | LinkQuotaExceeded, | ||
| 199 | FileBusy, | ||
| 200 | EndOfStream, | ||
| 201 | Unseekable, | ||
| 202 | NotOpenForWriting, | ||
| 203 | UnsupportedEncoding, | ||
| 204 | ConnectionResetByPeer, | ||
| 205 | SocketNotConnected, | ||
| 206 | LockViolation, | ||
| 207 | NetNameDeleted, | ||
| 208 | InvalidArgument, | ||
| 209 | } || fs.File.OpenError; | ||
| 210 | |||
| 211 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { | ||
| 212 | fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { | ||
| 213 | error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), | ||
| 214 | else => { | ||
| 215 | warn("unable to format '{s}': {s}", .{ file_path, @errorName(err) }); | ||
| 216 | fmt.any_error = true; | ||
| 217 | return; | ||
| 218 | }, | ||
| 219 | }; | ||
| 220 | } | ||
| 221 | |||
| 222 | fn fmtPathDir( | ||
| 223 | fmt: *Fmt, | ||
| 224 | file_path: []const u8, | ||
| 225 | check_mode: bool, | ||
| 226 | parent_dir: fs.Dir, | ||
| 227 | parent_sub_path: []const u8, | ||
| 228 | ) FmtError!void { | ||
| 229 | var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); | ||
| 230 | defer dir.close(); | ||
| 231 | |||
| 232 | const stat = try dir.stat(); | ||
| 233 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; | ||
| 234 | |||
| 235 | var dir_it = dir.iterate(); | ||
| 236 | while (try dir_it.next()) |entry| { | ||
| 237 | const is_dir = entry.kind == .directory; | ||
| 238 | |||
| 239 | if (is_dir and (mem.eql(u8, entry.name, "zig-cache") or mem.eql(u8, entry.name, "zig-out"))) continue; | ||
| 240 | |||
| 241 | if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) { | ||
| 242 | const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name }); | ||
| 243 | defer fmt.gpa.free(full_path); | ||
| 244 | |||
| 245 | if (is_dir) { | ||
| 246 | try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); | ||
| 247 | } else { | ||
| 248 | fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { | ||
| 249 | warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); | ||
| 250 | fmt.any_error = true; | ||
| 251 | return; | ||
| 252 | }; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | fn fmtPathFile( | ||
| 259 | fmt: *Fmt, | ||
| 260 | file_path: []const u8, | ||
| 261 | check_mode: bool, | ||
| 262 | dir: fs.Dir, | ||
| 263 | sub_path: []const u8, | ||
| 264 | ) FmtError!void { | ||
| 265 | const source_file = try dir.openFile(sub_path, .{}); | ||
| 266 | var file_closed = false; | ||
| 267 | errdefer if (!file_closed) source_file.close(); | ||
| 268 | |||
| 269 | const stat = try source_file.stat(); | ||
| 270 | |||
| 271 | if (stat.kind == .directory) | ||
| 272 | return error.IsDir; | ||
| 273 | |||
| 274 | const gpa = fmt.gpa; | ||
| 275 | const source_code = try std.zig.readSourceFileToEndAlloc( | ||
| 276 | gpa, | ||
| 277 | source_file, | ||
| 278 | std.math.cast(usize, stat.size) orelse return error.FileTooBig, | ||
| 279 | ); | ||
| 280 | defer gpa.free(source_code); | ||
| 281 | |||
| 282 | source_file.close(); | ||
| 283 | file_closed = true; | ||
| 284 | |||
| 285 | // Add to set after no longer possible to get error.IsDir. | ||
| 286 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; | ||
| 287 | |||
| 288 | var tree = try std.zig.Ast.parse(gpa, source_code, .zig); | ||
| 289 | defer tree.deinit(gpa); | ||
| 290 | |||
| 291 | if (tree.errors.len != 0) { | ||
| 292 | try std.zig.printAstErrorsToStderr(gpa, tree, file_path, fmt.color); | ||
| 293 | fmt.any_error = true; | ||
| 294 | return; | ||
| 295 | } | ||
| 296 | |||
| 297 | if (fmt.check_ast) { | ||
| 298 | if (stat.size > std.zig.max_src_size) | ||
| 299 | return error.FileTooBig; | ||
| 300 | |||
| 301 | var zir = try std.zig.AstGen.generate(gpa, tree); | ||
| 302 | defer zir.deinit(gpa); | ||
| 303 | |||
| 304 | if (zir.hasCompileErrors()) { | ||
| 305 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 306 | try wip_errors.init(gpa); | ||
| 307 | defer wip_errors.deinit(); | ||
| 308 | try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path); | ||
| 309 | var error_bundle = try wip_errors.toOwnedBundle(""); | ||
| 310 | defer error_bundle.deinit(gpa); | ||
| 311 | error_bundle.renderToStdErr(fmt.color.renderOptions()); | ||
| 312 | fmt.any_error = true; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | // As a heuristic, we make enough capacity for the same as the input source. | ||
| 317 | fmt.out_buffer.shrinkRetainingCapacity(0); | ||
| 318 | try fmt.out_buffer.ensureTotalCapacity(source_code.len); | ||
| 319 | |||
| 320 | try tree.renderToArrayList(&fmt.out_buffer, .{}); | ||
| 321 | if (mem.eql(u8, fmt.out_buffer.items, source_code)) | ||
| 322 | return; | ||
| 323 | |||
| 324 | if (check_mode) { | ||
| 325 | const stdout = std.io.getStdOut().writer(); | ||
| 326 | try stdout.print("{s}\n", .{file_path}); | ||
| 327 | fmt.any_error = true; | ||
| 328 | } else { | ||
| 329 | var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode }); | ||
| 330 | defer af.deinit(); | ||
| 331 | |||
| 332 | try af.file.writeAll(fmt.out_buffer.items); | ||
| 333 | try af.finish(); | ||
| 334 | const stdout = std.io.getStdOut().writer(); | ||
| 335 | try stdout.print("{s}\n", .{file_path}); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | fn fatal(comptime format: []const u8, args: anytype) noreturn { | ||
| 340 | std.log.err(format, args); | ||
| 341 | process.exit(1); | ||
| 342 | } |
src/Compilation.zig+3-78| ... | @@ -3322,85 +3322,10 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void { | ... | @@ -3322,85 +3322,10 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void { |
| 3322 | assert(file.zir_loaded); | 3322 | assert(file.zir_loaded); |
| 3323 | assert(file.tree_loaded); | 3323 | assert(file.tree_loaded); |
| 3324 | assert(file.source_loaded); | 3324 | assert(file.source_loaded); |
| 3325 | const payload_index = file.zir.extra[@intFromEnum(Zir.ExtraIndex.compile_errors)]; | ||
| 3326 | assert(payload_index != 0); | ||
| 3327 | const gpa = eb.gpa; | 3325 | const gpa = eb.gpa; |
| 3328 | 3326 | const src_path = try file.fullPath(gpa); | |
| 3329 | const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index); | 3327 | defer gpa.free(src_path); |
| 3330 | const items_len = header.data.items_len; | 3328 | return eb.addZirErrorMessages(file.zir, file.tree, file.source, src_path); |
| 3331 | var extra_index = header.end; | ||
| 3332 | for (0..items_len) |_| { | ||
| 3333 | const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); | ||
| 3334 | extra_index = item.end; | ||
| 3335 | const err_span = blk: { | ||
| 3336 | if (item.data.node != 0) { | ||
| 3337 | break :blk Module.SrcLoc.nodeToSpan(&file.tree, item.data.node); | ||
| 3338 | } | ||
| 3339 | const token_starts = file.tree.tokens.items(.start); | ||
| 3340 | const start = token_starts[item.data.token] + item.data.byte_offset; | ||
| 3341 | const end = start + @as(u32, @intCast(file.tree.tokenSlice(item.data.token).len)) - item.data.byte_offset; | ||
| 3342 | break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; | ||
| 3343 | }; | ||
| 3344 | const err_loc = std.zig.findLineColumn(file.source, err_span.main); | ||
| 3345 | |||
| 3346 | { | ||
| 3347 | const msg = file.zir.nullTerminatedString(item.data.msg); | ||
| 3348 | const src_path = try file.fullPath(gpa); | ||
| 3349 | defer gpa.free(src_path); | ||
| 3350 | try eb.addRootErrorMessage(.{ | ||
| 3351 | .msg = try eb.addString(msg), | ||
| 3352 | .src_loc = try eb.addSourceLocation(.{ | ||
| 3353 | .src_path = try eb.addString(src_path), | ||
| 3354 | .span_start = err_span.start, | ||
| 3355 | .span_main = err_span.main, | ||
| 3356 | .span_end = err_span.end, | ||
| 3357 | .line = @as(u32, @intCast(err_loc.line)), | ||
| 3358 | .column = @as(u32, @intCast(err_loc.column)), | ||
| 3359 | .source_line = try eb.addString(err_loc.source_line), | ||
| 3360 | }), | ||
| 3361 | .notes_len = item.data.notesLen(file.zir), | ||
| 3362 | }); | ||
| 3363 | } | ||
| 3364 | |||
| 3365 | if (item.data.notes != 0) { | ||
| 3366 | const notes_start = try eb.reserveNotes(item.data.notes); | ||
| 3367 | const block = file.zir.extraData(Zir.Inst.Block, item.data.notes); | ||
| 3368 | const body = file.zir.extra[block.end..][0..block.data.body_len]; | ||
| 3369 | for (notes_start.., body) |note_i, body_elem| { | ||
| 3370 | const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); | ||
| 3371 | const msg = file.zir.nullTerminatedString(note_item.data.msg); | ||
| 3372 | const span = blk: { | ||
| 3373 | if (note_item.data.node != 0) { | ||
| 3374 | break :blk Module.SrcLoc.nodeToSpan(&file.tree, note_item.data.node); | ||
| 3375 | } | ||
| 3376 | const token_starts = file.tree.tokens.items(.start); | ||
| 3377 | const start = token_starts[note_item.data.token] + note_item.data.byte_offset; | ||
| 3378 | const end = start + @as(u32, @intCast(file.tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset; | ||
| 3379 | break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; | ||
| 3380 | }; | ||
| 3381 | const loc = std.zig.findLineColumn(file.source, span.main); | ||
| 3382 | const src_path = try file.fullPath(gpa); | ||
| 3383 | defer gpa.free(src_path); | ||
| 3384 | |||
| 3385 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | ||
| 3386 | .msg = try eb.addString(msg), | ||
| 3387 | .src_loc = try eb.addSourceLocation(.{ | ||
| 3388 | .src_path = try eb.addString(src_path), | ||
| 3389 | .span_start = span.start, | ||
| 3390 | .span_main = span.main, | ||
| 3391 | .span_end = span.end, | ||
| 3392 | .line = @as(u32, @intCast(loc.line)), | ||
| 3393 | .column = @as(u32, @intCast(loc.column)), | ||
| 3394 | .source_line = if (loc.eql(err_loc)) | ||
| 3395 | 0 | ||
| 3396 | else | ||
| 3397 | try eb.addString(loc.source_line), | ||
| 3398 | }), | ||
| 3399 | .notes_len = 0, // TODO rework this function to be recursive | ||
| 3400 | })); | ||
| 3401 | } | ||
| 3402 | } | ||
| 3403 | } | ||
| 3404 | } | 3329 | } |
| 3405 | 3330 | ||
| 3406 | pub fn performAllTheWork( | 3331 | pub fn performAllTheWork( |
src/Module.zig+66-108| ... | @@ -1255,11 +1255,7 @@ pub const SrcLoc = struct { | ... | @@ -1255,11 +1255,7 @@ pub const SrcLoc = struct { |
| 1255 | return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))); | 1255 | return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | pub const Span = struct { | 1258 | pub const Span = Ast.Span; |
| 1259 | start: u32, | ||
| 1260 | end: u32, | ||
| 1261 | main: u32, | ||
| 1262 | }; | ||
| 1263 | 1259 | ||
| 1264 | pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { | 1260 | pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { |
| 1265 | switch (src_loc.lazy) { | 1261 | switch (src_loc.lazy) { |
| ... | @@ -1276,7 +1272,7 @@ pub const SrcLoc = struct { | ... | @@ -1276,7 +1272,7 @@ pub const SrcLoc = struct { |
| 1276 | }, | 1272 | }, |
| 1277 | .node_abs => |node| { | 1273 | .node_abs => |node| { |
| 1278 | const tree = try src_loc.file_scope.getTree(gpa); | 1274 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1279 | return nodeToSpan(tree, node); | 1275 | return tree.nodeToSpan(node); |
| 1280 | }, | 1276 | }, |
| 1281 | .byte_offset => |byte_off| { | 1277 | .byte_offset => |byte_off| { |
| 1282 | const tree = try src_loc.file_scope.getTree(gpa); | 1278 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1297,25 +1293,24 @@ pub const SrcLoc = struct { | ... | @@ -1297,25 +1293,24 @@ pub const SrcLoc = struct { |
| 1297 | const tree = try src_loc.file_scope.getTree(gpa); | 1293 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1298 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1294 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1299 | assert(src_loc.file_scope.tree_loaded); | 1295 | assert(src_loc.file_scope.tree_loaded); |
| 1300 | return nodeToSpan(tree, node); | 1296 | return tree.nodeToSpan(node); |
| 1301 | }, | 1297 | }, |
| 1302 | .node_offset_main_token => |node_off| { | 1298 | .node_offset_main_token => |node_off| { |
| 1303 | const tree = try src_loc.file_scope.getTree(gpa); | 1299 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1304 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1300 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1305 | const main_token = tree.nodes.items(.main_token)[node]; | 1301 | const main_token = tree.nodes.items(.main_token)[node]; |
| 1306 | return tokensToSpan(tree, main_token, main_token, main_token); | 1302 | return tree.tokensToSpan(main_token, main_token, main_token); |
| 1307 | }, | 1303 | }, |
| 1308 | .node_offset_bin_op => |node_off| { | 1304 | .node_offset_bin_op => |node_off| { |
| 1309 | const tree = try src_loc.file_scope.getTree(gpa); | 1305 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1310 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1306 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1311 | assert(src_loc.file_scope.tree_loaded); | 1307 | assert(src_loc.file_scope.tree_loaded); |
| 1312 | return nodeToSpan(tree, node); | 1308 | return tree.nodeToSpan(node); |
| 1313 | }, | 1309 | }, |
| 1314 | .node_offset_initializer => |node_off| { | 1310 | .node_offset_initializer => |node_off| { |
| 1315 | const tree = try src_loc.file_scope.getTree(gpa); | 1311 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1316 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1312 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1317 | return tokensToSpan( | 1313 | return tree.tokensToSpan( |
| 1318 | tree, | ||
| 1319 | tree.firstToken(node) - 3, | 1314 | tree.firstToken(node) - 3, |
| 1320 | tree.lastToken(node), | 1315 | tree.lastToken(node), |
| 1321 | tree.nodes.items(.main_token)[node] - 2, | 1316 | tree.nodes.items(.main_token)[node] - 2, |
| ... | @@ -1333,12 +1328,12 @@ pub const SrcLoc = struct { | ... | @@ -1333,12 +1328,12 @@ pub const SrcLoc = struct { |
| 1333 | => tree.fullVarDecl(node).?, | 1328 | => tree.fullVarDecl(node).?, |
| 1334 | .@"usingnamespace" => { | 1329 | .@"usingnamespace" => { |
| 1335 | const node_data = tree.nodes.items(.data); | 1330 | const node_data = tree.nodes.items(.data); |
| 1336 | return nodeToSpan(tree, node_data[node].lhs); | 1331 | return tree.nodeToSpan(node_data[node].lhs); |
| 1337 | }, | 1332 | }, |
| 1338 | else => unreachable, | 1333 | else => unreachable, |
| 1339 | }; | 1334 | }; |
| 1340 | if (full.ast.type_node != 0) { | 1335 | if (full.ast.type_node != 0) { |
| 1341 | return nodeToSpan(tree, full.ast.type_node); | 1336 | return tree.nodeToSpan(full.ast.type_node); |
| 1342 | } | 1337 | } |
| 1343 | const tok_index = full.ast.mut_token + 1; // the name token | 1338 | const tok_index = full.ast.mut_token + 1; // the name token |
| 1344 | const start = tree.tokens.items(.start)[tok_index]; | 1339 | const start = tree.tokens.items(.start)[tok_index]; |
| ... | @@ -1349,25 +1344,25 @@ pub const SrcLoc = struct { | ... | @@ -1349,25 +1344,25 @@ pub const SrcLoc = struct { |
| 1349 | const tree = try src_loc.file_scope.getTree(gpa); | 1344 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1350 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1345 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1351 | const full = tree.fullVarDecl(node).?; | 1346 | const full = tree.fullVarDecl(node).?; |
| 1352 | return nodeToSpan(tree, full.ast.align_node); | 1347 | return tree.nodeToSpan(full.ast.align_node); |
| 1353 | }, | 1348 | }, |
| 1354 | .node_offset_var_decl_section => |node_off| { | 1349 | .node_offset_var_decl_section => |node_off| { |
| 1355 | const tree = try src_loc.file_scope.getTree(gpa); | 1350 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1356 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1351 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1357 | const full = tree.fullVarDecl(node).?; | 1352 | const full = tree.fullVarDecl(node).?; |
| 1358 | return nodeToSpan(tree, full.ast.section_node); | 1353 | return tree.nodeToSpan(full.ast.section_node); |
| 1359 | }, | 1354 | }, |
| 1360 | .node_offset_var_decl_addrspace => |node_off| { | 1355 | .node_offset_var_decl_addrspace => |node_off| { |
| 1361 | const tree = try src_loc.file_scope.getTree(gpa); | 1356 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1362 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1357 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1363 | const full = tree.fullVarDecl(node).?; | 1358 | const full = tree.fullVarDecl(node).?; |
| 1364 | return nodeToSpan(tree, full.ast.addrspace_node); | 1359 | return tree.nodeToSpan(full.ast.addrspace_node); |
| 1365 | }, | 1360 | }, |
| 1366 | .node_offset_var_decl_init => |node_off| { | 1361 | .node_offset_var_decl_init => |node_off| { |
| 1367 | const tree = try src_loc.file_scope.getTree(gpa); | 1362 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1368 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1363 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1369 | const full = tree.fullVarDecl(node).?; | 1364 | const full = tree.fullVarDecl(node).?; |
| 1370 | return nodeToSpan(tree, full.ast.init_node); | 1365 | return tree.nodeToSpan(full.ast.init_node); |
| 1371 | }, | 1366 | }, |
| 1372 | .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), | 1367 | .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), |
| 1373 | .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), | 1368 | .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), |
| ... | @@ -1408,13 +1403,13 @@ pub const SrcLoc = struct { | ... | @@ -1408,13 +1403,13 @@ pub const SrcLoc = struct { |
| 1408 | node = node_datas[node].lhs; | 1403 | node = node_datas[node].lhs; |
| 1409 | } | 1404 | } |
| 1410 | 1405 | ||
| 1411 | return nodeToSpan(tree, node); | 1406 | return tree.nodeToSpan(node); |
| 1412 | }, | 1407 | }, |
| 1413 | .node_offset_array_access_index => |node_off| { | 1408 | .node_offset_array_access_index => |node_off| { |
| 1414 | const tree = try src_loc.file_scope.getTree(gpa); | 1409 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1415 | const node_datas = tree.nodes.items(.data); | 1410 | const node_datas = tree.nodes.items(.data); |
| 1416 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1411 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1417 | return nodeToSpan(tree, node_datas[node].rhs); | 1412 | return tree.nodeToSpan(node_datas[node].rhs); |
| 1418 | }, | 1413 | }, |
| 1419 | .node_offset_slice_ptr, | 1414 | .node_offset_slice_ptr, |
| 1420 | .node_offset_slice_start, | 1415 | .node_offset_slice_start, |
| ... | @@ -1431,14 +1426,14 @@ pub const SrcLoc = struct { | ... | @@ -1431,14 +1426,14 @@ pub const SrcLoc = struct { |
| 1431 | .node_offset_slice_sentinel => full.ast.sentinel, | 1426 | .node_offset_slice_sentinel => full.ast.sentinel, |
| 1432 | else => unreachable, | 1427 | else => unreachable, |
| 1433 | }; | 1428 | }; |
| 1434 | return nodeToSpan(tree, part_node); | 1429 | return tree.nodeToSpan(part_node); |
| 1435 | }, | 1430 | }, |
| 1436 | .node_offset_call_func => |node_off| { | 1431 | .node_offset_call_func => |node_off| { |
| 1437 | const tree = try src_loc.file_scope.getTree(gpa); | 1432 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1438 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1433 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1439 | var buf: [1]Ast.Node.Index = undefined; | 1434 | var buf: [1]Ast.Node.Index = undefined; |
| 1440 | const full = tree.fullCall(&buf, node).?; | 1435 | const full = tree.fullCall(&buf, node).?; |
| 1441 | return nodeToSpan(tree, full.ast.fn_expr); | 1436 | return tree.nodeToSpan(full.ast.fn_expr); |
| 1442 | }, | 1437 | }, |
| 1443 | .node_offset_field_name => |node_off| { | 1438 | .node_offset_field_name => |node_off| { |
| 1444 | const tree = try src_loc.file_scope.getTree(gpa); | 1439 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1477,13 +1472,13 @@ pub const SrcLoc = struct { | ... | @@ -1477,13 +1472,13 @@ pub const SrcLoc = struct { |
| 1477 | .node_offset_deref_ptr => |node_off| { | 1472 | .node_offset_deref_ptr => |node_off| { |
| 1478 | const tree = try src_loc.file_scope.getTree(gpa); | 1473 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1479 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1474 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1480 | return nodeToSpan(tree, node); | 1475 | return tree.nodeToSpan(node); |
| 1481 | }, | 1476 | }, |
| 1482 | .node_offset_asm_source => |node_off| { | 1477 | .node_offset_asm_source => |node_off| { |
| 1483 | const tree = try src_loc.file_scope.getTree(gpa); | 1478 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1484 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1479 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1485 | const full = tree.fullAsm(node).?; | 1480 | const full = tree.fullAsm(node).?; |
| 1486 | return nodeToSpan(tree, full.ast.template); | 1481 | return tree.nodeToSpan(full.ast.template); |
| 1487 | }, | 1482 | }, |
| 1488 | .node_offset_asm_ret_ty => |node_off| { | 1483 | .node_offset_asm_ret_ty => |node_off| { |
| 1489 | const tree = try src_loc.file_scope.getTree(gpa); | 1484 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1491,7 +1486,7 @@ pub const SrcLoc = struct { | ... | @@ -1491,7 +1486,7 @@ pub const SrcLoc = struct { |
| 1491 | const full = tree.fullAsm(node).?; | 1486 | const full = tree.fullAsm(node).?; |
| 1492 | const asm_output = full.outputs[0]; | 1487 | const asm_output = full.outputs[0]; |
| 1493 | const node_datas = tree.nodes.items(.data); | 1488 | const node_datas = tree.nodes.items(.data); |
| 1494 | return nodeToSpan(tree, node_datas[asm_output].lhs); | 1489 | return tree.nodeToSpan(node_datas[asm_output].lhs); |
| 1495 | }, | 1490 | }, |
| 1496 | 1491 | ||
| 1497 | .node_offset_if_cond => |node_off| { | 1492 | .node_offset_if_cond => |node_off| { |
| ... | @@ -1514,21 +1509,21 @@ pub const SrcLoc = struct { | ... | @@ -1514,21 +1509,21 @@ pub const SrcLoc = struct { |
| 1514 | const inputs = tree.fullFor(node).?.ast.inputs; | 1509 | const inputs = tree.fullFor(node).?.ast.inputs; |
| 1515 | const start = tree.firstToken(inputs[0]); | 1510 | const start = tree.firstToken(inputs[0]); |
| 1516 | const end = tree.lastToken(inputs[inputs.len - 1]); | 1511 | const end = tree.lastToken(inputs[inputs.len - 1]); |
| 1517 | return tokensToSpan(tree, start, end, start); | 1512 | return tree.tokensToSpan(start, end, start); |
| 1518 | }, | 1513 | }, |
| 1519 | 1514 | ||
| 1520 | .@"orelse" => node, | 1515 | .@"orelse" => node, |
| 1521 | .@"catch" => node, | 1516 | .@"catch" => node, |
| 1522 | else => unreachable, | 1517 | else => unreachable, |
| 1523 | }; | 1518 | }; |
| 1524 | return nodeToSpan(tree, src_node); | 1519 | return tree.nodeToSpan(src_node); |
| 1525 | }, | 1520 | }, |
| 1526 | .for_input => |for_input| { | 1521 | .for_input => |for_input| { |
| 1527 | const tree = try src_loc.file_scope.getTree(gpa); | 1522 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1528 | const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset); | 1523 | const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset); |
| 1529 | const for_full = tree.fullFor(node).?; | 1524 | const for_full = tree.fullFor(node).?; |
| 1530 | const src_node = for_full.ast.inputs[for_input.input_index]; | 1525 | const src_node = for_full.ast.inputs[for_input.input_index]; |
| 1531 | return nodeToSpan(tree, src_node); | 1526 | return tree.nodeToSpan(src_node); |
| 1532 | }, | 1527 | }, |
| 1533 | .for_capture_from_input => |node_off| { | 1528 | .for_capture_from_input => |node_off| { |
| 1534 | const tree = try src_loc.file_scope.getTree(gpa); | 1529 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1554,12 +1549,12 @@ pub const SrcLoc = struct { | ... | @@ -1554,12 +1549,12 @@ pub const SrcLoc = struct { |
| 1554 | }, | 1549 | }, |
| 1555 | .identifier => { | 1550 | .identifier => { |
| 1556 | if (count == 0) | 1551 | if (count == 0) |
| 1557 | return tokensToSpan(tree, tok, tok + 1, tok); | 1552 | return tree.tokensToSpan(tok, tok + 1, tok); |
| 1558 | tok += 1; | 1553 | tok += 1; |
| 1559 | }, | 1554 | }, |
| 1560 | .asterisk => { | 1555 | .asterisk => { |
| 1561 | if (count == 0) | 1556 | if (count == 0) |
| 1562 | return tokensToSpan(tree, tok, tok + 2, tok); | 1557 | return tree.tokensToSpan(tok, tok + 2, tok); |
| 1563 | tok += 1; | 1558 | tok += 1; |
| 1564 | }, | 1559 | }, |
| 1565 | else => unreachable, | 1560 | else => unreachable, |
| ... | @@ -1591,7 +1586,7 @@ pub const SrcLoc = struct { | ... | @@ -1591,7 +1586,7 @@ pub const SrcLoc = struct { |
| 1591 | .array_init_comma, | 1586 | .array_init_comma, |
| 1592 | => { | 1587 | => { |
| 1593 | const full = tree.fullArrayInit(&buf, call_args_node).?.ast.elements; | 1588 | const full = tree.fullArrayInit(&buf, call_args_node).?.ast.elements; |
| 1594 | return nodeToSpan(tree, full[call_arg.arg_index]); | 1589 | return tree.nodeToSpan(full[call_arg.arg_index]); |
| 1595 | }, | 1590 | }, |
| 1596 | .struct_init_one, | 1591 | .struct_init_one, |
| 1597 | .struct_init_one_comma, | 1592 | .struct_init_one_comma, |
| ... | @@ -1603,12 +1598,12 @@ pub const SrcLoc = struct { | ... | @@ -1603,12 +1598,12 @@ pub const SrcLoc = struct { |
| 1603 | .struct_init_comma, | 1598 | .struct_init_comma, |
| 1604 | => { | 1599 | => { |
| 1605 | const full = tree.fullStructInit(&buf, call_args_node).?.ast.fields; | 1600 | const full = tree.fullStructInit(&buf, call_args_node).?.ast.fields; |
| 1606 | return nodeToSpan(tree, full[call_arg.arg_index]); | 1601 | return tree.nodeToSpan(full[call_arg.arg_index]); |
| 1607 | }, | 1602 | }, |
| 1608 | else => return nodeToSpan(tree, call_args_node), | 1603 | else => return tree.nodeToSpan(call_args_node), |
| 1609 | } | 1604 | } |
| 1610 | }; | 1605 | }; |
| 1611 | return nodeToSpan(tree, call_full.ast.params[call_arg.arg_index]); | 1606 | return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]); |
| 1612 | }, | 1607 | }, |
| 1613 | .fn_proto_param => |fn_proto_param| { | 1608 | .fn_proto_param => |fn_proto_param| { |
| 1614 | const tree = try src_loc.file_scope.getTree(gpa); | 1609 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1619,12 +1614,11 @@ pub const SrcLoc = struct { | ... | @@ -1619,12 +1614,11 @@ pub const SrcLoc = struct { |
| 1619 | var i: usize = 0; | 1614 | var i: usize = 0; |
| 1620 | while (it.next()) |param| : (i += 1) { | 1615 | while (it.next()) |param| : (i += 1) { |
| 1621 | if (i == fn_proto_param.param_index) { | 1616 | if (i == fn_proto_param.param_index) { |
| 1622 | if (param.anytype_ellipsis3) |token| return tokenToSpan(tree, token); | 1617 | if (param.anytype_ellipsis3) |token| return tree.tokenToSpan(token); |
| 1623 | const first_token = param.comptime_noalias orelse | 1618 | const first_token = param.comptime_noalias orelse |
| 1624 | param.name_token orelse | 1619 | param.name_token orelse |
| 1625 | tree.firstToken(param.type_expr); | 1620 | tree.firstToken(param.type_expr); |
| 1626 | return tokensToSpan( | 1621 | return tree.tokensToSpan( |
| 1627 | tree, | ||
| 1628 | first_token, | 1622 | first_token, |
| 1629 | tree.lastToken(param.type_expr), | 1623 | tree.lastToken(param.type_expr), |
| 1630 | first_token, | 1624 | first_token, |
| ... | @@ -1637,13 +1631,13 @@ pub const SrcLoc = struct { | ... | @@ -1637,13 +1631,13 @@ pub const SrcLoc = struct { |
| 1637 | const tree = try src_loc.file_scope.getTree(gpa); | 1631 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1638 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1632 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1639 | const node_datas = tree.nodes.items(.data); | 1633 | const node_datas = tree.nodes.items(.data); |
| 1640 | return nodeToSpan(tree, node_datas[node].lhs); | 1634 | return tree.nodeToSpan(node_datas[node].lhs); |
| 1641 | }, | 1635 | }, |
| 1642 | .node_offset_bin_rhs => |node_off| { | 1636 | .node_offset_bin_rhs => |node_off| { |
| 1643 | const tree = try src_loc.file_scope.getTree(gpa); | 1637 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1644 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1638 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1645 | const node_datas = tree.nodes.items(.data); | 1639 | const node_datas = tree.nodes.items(.data); |
| 1646 | return nodeToSpan(tree, node_datas[node].rhs); | 1640 | return tree.nodeToSpan(node_datas[node].rhs); |
| 1647 | }, | 1641 | }, |
| 1648 | .array_cat_lhs, .array_cat_rhs => |cat| { | 1642 | .array_cat_lhs, .array_cat_rhs => |cat| { |
| 1649 | const tree = try src_loc.file_scope.getTree(gpa); | 1643 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1667,9 +1661,9 @@ pub const SrcLoc = struct { | ... | @@ -1667,9 +1661,9 @@ pub const SrcLoc = struct { |
| 1667 | .array_init_comma, | 1661 | .array_init_comma, |
| 1668 | => { | 1662 | => { |
| 1669 | const full = tree.fullArrayInit(&buf, arr_node).?.ast.elements; | 1663 | const full = tree.fullArrayInit(&buf, arr_node).?.ast.elements; |
| 1670 | return nodeToSpan(tree, full[cat.elem_index]); | 1664 | return tree.nodeToSpan(full[cat.elem_index]); |
| 1671 | }, | 1665 | }, |
| 1672 | else => return nodeToSpan(tree, arr_node), | 1666 | else => return tree.nodeToSpan(arr_node), |
| 1673 | } | 1667 | } |
| 1674 | }, | 1668 | }, |
| 1675 | 1669 | ||
| ... | @@ -1677,7 +1671,7 @@ pub const SrcLoc = struct { | ... | @@ -1677,7 +1671,7 @@ pub const SrcLoc = struct { |
| 1677 | const tree = try src_loc.file_scope.getTree(gpa); | 1671 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1678 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1672 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1679 | const node_datas = tree.nodes.items(.data); | 1673 | const node_datas = tree.nodes.items(.data); |
| 1680 | return nodeToSpan(tree, node_datas[node].lhs); | 1674 | return tree.nodeToSpan(node_datas[node].lhs); |
| 1681 | }, | 1675 | }, |
| 1682 | 1676 | ||
| 1683 | .node_offset_switch_special_prong => |node_off| { | 1677 | .node_offset_switch_special_prong => |node_off| { |
| ... | @@ -1696,7 +1690,7 @@ pub const SrcLoc = struct { | ... | @@ -1696,7 +1690,7 @@ pub const SrcLoc = struct { |
| 1696 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); | 1690 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); |
| 1697 | if (!is_special) continue; | 1691 | if (!is_special) continue; |
| 1698 | 1692 | ||
| 1699 | return nodeToSpan(tree, case_node); | 1693 | return tree.nodeToSpan(case_node); |
| 1700 | } else unreachable; | 1694 | } else unreachable; |
| 1701 | }, | 1695 | }, |
| 1702 | 1696 | ||
| ... | @@ -1718,7 +1712,7 @@ pub const SrcLoc = struct { | ... | @@ -1718,7 +1712,7 @@ pub const SrcLoc = struct { |
| 1718 | 1712 | ||
| 1719 | for (case.ast.values) |item_node| { | 1713 | for (case.ast.values) |item_node| { |
| 1720 | if (node_tags[item_node] == .switch_range) { | 1714 | if (node_tags[item_node] == .switch_range) { |
| 1721 | return nodeToSpan(tree, item_node); | 1715 | return tree.nodeToSpan(item_node); |
| 1722 | } | 1716 | } |
| 1723 | } | 1717 | } |
| 1724 | } else unreachable; | 1718 | } else unreachable; |
| ... | @@ -1754,28 +1748,28 @@ pub const SrcLoc = struct { | ... | @@ -1754,28 +1748,28 @@ pub const SrcLoc = struct { |
| 1754 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1748 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1755 | var buf: [1]Ast.Node.Index = undefined; | 1749 | var buf: [1]Ast.Node.Index = undefined; |
| 1756 | const full = tree.fullFnProto(&buf, node).?; | 1750 | const full = tree.fullFnProto(&buf, node).?; |
| 1757 | return nodeToSpan(tree, full.ast.align_expr); | 1751 | return tree.nodeToSpan(full.ast.align_expr); |
| 1758 | }, | 1752 | }, |
| 1759 | .node_offset_fn_type_addrspace => |node_off| { | 1753 | .node_offset_fn_type_addrspace => |node_off| { |
| 1760 | const tree = try src_loc.file_scope.getTree(gpa); | 1754 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1761 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1755 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1762 | var buf: [1]Ast.Node.Index = undefined; | 1756 | var buf: [1]Ast.Node.Index = undefined; |
| 1763 | const full = tree.fullFnProto(&buf, node).?; | 1757 | const full = tree.fullFnProto(&buf, node).?; |
| 1764 | return nodeToSpan(tree, full.ast.addrspace_expr); | 1758 | return tree.nodeToSpan(full.ast.addrspace_expr); |
| 1765 | }, | 1759 | }, |
| 1766 | .node_offset_fn_type_section => |node_off| { | 1760 | .node_offset_fn_type_section => |node_off| { |
| 1767 | const tree = try src_loc.file_scope.getTree(gpa); | 1761 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1768 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1762 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1769 | var buf: [1]Ast.Node.Index = undefined; | 1763 | var buf: [1]Ast.Node.Index = undefined; |
| 1770 | const full = tree.fullFnProto(&buf, node).?; | 1764 | const full = tree.fullFnProto(&buf, node).?; |
| 1771 | return nodeToSpan(tree, full.ast.section_expr); | 1765 | return tree.nodeToSpan(full.ast.section_expr); |
| 1772 | }, | 1766 | }, |
| 1773 | .node_offset_fn_type_cc => |node_off| { | 1767 | .node_offset_fn_type_cc => |node_off| { |
| 1774 | const tree = try src_loc.file_scope.getTree(gpa); | 1768 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1775 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1769 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1776 | var buf: [1]Ast.Node.Index = undefined; | 1770 | var buf: [1]Ast.Node.Index = undefined; |
| 1777 | const full = tree.fullFnProto(&buf, node).?; | 1771 | const full = tree.fullFnProto(&buf, node).?; |
| 1778 | return nodeToSpan(tree, full.ast.callconv_expr); | 1772 | return tree.nodeToSpan(full.ast.callconv_expr); |
| 1779 | }, | 1773 | }, |
| 1780 | 1774 | ||
| 1781 | .node_offset_fn_type_ret_ty => |node_off| { | 1775 | .node_offset_fn_type_ret_ty => |node_off| { |
| ... | @@ -1783,7 +1777,7 @@ pub const SrcLoc = struct { | ... | @@ -1783,7 +1777,7 @@ pub const SrcLoc = struct { |
| 1783 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1777 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1784 | var buf: [1]Ast.Node.Index = undefined; | 1778 | var buf: [1]Ast.Node.Index = undefined; |
| 1785 | const full = tree.fullFnProto(&buf, node).?; | 1779 | const full = tree.fullFnProto(&buf, node).?; |
| 1786 | return nodeToSpan(tree, full.ast.return_type); | 1780 | return tree.nodeToSpan(full.ast.return_type); |
| 1787 | }, | 1781 | }, |
| 1788 | .node_offset_param => |node_off| { | 1782 | .node_offset_param => |node_off| { |
| 1789 | const tree = try src_loc.file_scope.getTree(gpa); | 1783 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1795,8 +1789,7 @@ pub const SrcLoc = struct { | ... | @@ -1795,8 +1789,7 @@ pub const SrcLoc = struct { |
| 1795 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, | 1789 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1796 | else => break, | 1790 | else => break, |
| 1797 | }; | 1791 | }; |
| 1798 | return tokensToSpan( | 1792 | return tree.tokensToSpan( |
| 1799 | tree, | ||
| 1800 | first_tok, | 1793 | first_tok, |
| 1801 | tree.lastToken(node), | 1794 | tree.lastToken(node), |
| 1802 | first_tok, | 1795 | first_tok, |
| ... | @@ -1813,8 +1806,7 @@ pub const SrcLoc = struct { | ... | @@ -1813,8 +1806,7 @@ pub const SrcLoc = struct { |
| 1813 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, | 1806 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1814 | else => break, | 1807 | else => break, |
| 1815 | }; | 1808 | }; |
| 1816 | return tokensToSpan( | 1809 | return tree.tokensToSpan( |
| 1817 | tree, | ||
| 1818 | first_tok, | 1810 | first_tok, |
| 1819 | tok_index, | 1811 | tok_index, |
| 1820 | first_tok, | 1812 | first_tok, |
| ... | @@ -1825,7 +1817,7 @@ pub const SrcLoc = struct { | ... | @@ -1825,7 +1817,7 @@ pub const SrcLoc = struct { |
| 1825 | const tree = try src_loc.file_scope.getTree(gpa); | 1817 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1826 | const node_datas = tree.nodes.items(.data); | 1818 | const node_datas = tree.nodes.items(.data); |
| 1827 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1819 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1828 | return nodeToSpan(tree, node_datas[parent_node].rhs); | 1820 | return tree.nodeToSpan(node_datas[parent_node].rhs); |
| 1829 | }, | 1821 | }, |
| 1830 | 1822 | ||
| 1831 | .node_offset_lib_name => |node_off| { | 1823 | .node_offset_lib_name => |node_off| { |
| ... | @@ -1844,70 +1836,70 @@ pub const SrcLoc = struct { | ... | @@ -1844,70 +1836,70 @@ pub const SrcLoc = struct { |
| 1844 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1836 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1845 | 1837 | ||
| 1846 | const full = tree.fullArrayType(parent_node).?; | 1838 | const full = tree.fullArrayType(parent_node).?; |
| 1847 | return nodeToSpan(tree, full.ast.elem_count); | 1839 | return tree.nodeToSpan(full.ast.elem_count); |
| 1848 | }, | 1840 | }, |
| 1849 | .node_offset_array_type_sentinel => |node_off| { | 1841 | .node_offset_array_type_sentinel => |node_off| { |
| 1850 | const tree = try src_loc.file_scope.getTree(gpa); | 1842 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1851 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1843 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1852 | 1844 | ||
| 1853 | const full = tree.fullArrayType(parent_node).?; | 1845 | const full = tree.fullArrayType(parent_node).?; |
| 1854 | return nodeToSpan(tree, full.ast.sentinel); | 1846 | return tree.nodeToSpan(full.ast.sentinel); |
| 1855 | }, | 1847 | }, |
| 1856 | .node_offset_array_type_elem => |node_off| { | 1848 | .node_offset_array_type_elem => |node_off| { |
| 1857 | const tree = try src_loc.file_scope.getTree(gpa); | 1849 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1858 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1850 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1859 | 1851 | ||
| 1860 | const full = tree.fullArrayType(parent_node).?; | 1852 | const full = tree.fullArrayType(parent_node).?; |
| 1861 | return nodeToSpan(tree, full.ast.elem_type); | 1853 | return tree.nodeToSpan(full.ast.elem_type); |
| 1862 | }, | 1854 | }, |
| 1863 | .node_offset_un_op => |node_off| { | 1855 | .node_offset_un_op => |node_off| { |
| 1864 | const tree = try src_loc.file_scope.getTree(gpa); | 1856 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1865 | const node_datas = tree.nodes.items(.data); | 1857 | const node_datas = tree.nodes.items(.data); |
| 1866 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1858 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| 1867 | 1859 | ||
| 1868 | return nodeToSpan(tree, node_datas[node].lhs); | 1860 | return tree.nodeToSpan(node_datas[node].lhs); |
| 1869 | }, | 1861 | }, |
| 1870 | .node_offset_ptr_elem => |node_off| { | 1862 | .node_offset_ptr_elem => |node_off| { |
| 1871 | const tree = try src_loc.file_scope.getTree(gpa); | 1863 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1872 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1864 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1873 | 1865 | ||
| 1874 | const full = tree.fullPtrType(parent_node).?; | 1866 | const full = tree.fullPtrType(parent_node).?; |
| 1875 | return nodeToSpan(tree, full.ast.child_type); | 1867 | return tree.nodeToSpan(full.ast.child_type); |
| 1876 | }, | 1868 | }, |
| 1877 | .node_offset_ptr_sentinel => |node_off| { | 1869 | .node_offset_ptr_sentinel => |node_off| { |
| 1878 | const tree = try src_loc.file_scope.getTree(gpa); | 1870 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1879 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1871 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1880 | 1872 | ||
| 1881 | const full = tree.fullPtrType(parent_node).?; | 1873 | const full = tree.fullPtrType(parent_node).?; |
| 1882 | return nodeToSpan(tree, full.ast.sentinel); | 1874 | return tree.nodeToSpan(full.ast.sentinel); |
| 1883 | }, | 1875 | }, |
| 1884 | .node_offset_ptr_align => |node_off| { | 1876 | .node_offset_ptr_align => |node_off| { |
| 1885 | const tree = try src_loc.file_scope.getTree(gpa); | 1877 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1886 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1878 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1887 | 1879 | ||
| 1888 | const full = tree.fullPtrType(parent_node).?; | 1880 | const full = tree.fullPtrType(parent_node).?; |
| 1889 | return nodeToSpan(tree, full.ast.align_node); | 1881 | return tree.nodeToSpan(full.ast.align_node); |
| 1890 | }, | 1882 | }, |
| 1891 | .node_offset_ptr_addrspace => |node_off| { | 1883 | .node_offset_ptr_addrspace => |node_off| { |
| 1892 | const tree = try src_loc.file_scope.getTree(gpa); | 1884 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1893 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1885 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1894 | 1886 | ||
| 1895 | const full = tree.fullPtrType(parent_node).?; | 1887 | const full = tree.fullPtrType(parent_node).?; |
| 1896 | return nodeToSpan(tree, full.ast.addrspace_node); | 1888 | return tree.nodeToSpan(full.ast.addrspace_node); |
| 1897 | }, | 1889 | }, |
| 1898 | .node_offset_ptr_bitoffset => |node_off| { | 1890 | .node_offset_ptr_bitoffset => |node_off| { |
| 1899 | const tree = try src_loc.file_scope.getTree(gpa); | 1891 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1900 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1892 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1901 | 1893 | ||
| 1902 | const full = tree.fullPtrType(parent_node).?; | 1894 | const full = tree.fullPtrType(parent_node).?; |
| 1903 | return nodeToSpan(tree, full.ast.bit_range_start); | 1895 | return tree.nodeToSpan(full.ast.bit_range_start); |
| 1904 | }, | 1896 | }, |
| 1905 | .node_offset_ptr_hostsize => |node_off| { | 1897 | .node_offset_ptr_hostsize => |node_off| { |
| 1906 | const tree = try src_loc.file_scope.getTree(gpa); | 1898 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1907 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); | 1899 | const parent_node = src_loc.declRelativeToNodeIndex(node_off); |
| 1908 | 1900 | ||
| 1909 | const full = tree.fullPtrType(parent_node).?; | 1901 | const full = tree.fullPtrType(parent_node).?; |
| 1910 | return nodeToSpan(tree, full.ast.bit_range_end); | 1902 | return tree.nodeToSpan(full.ast.bit_range_end); |
| 1911 | }, | 1903 | }, |
| 1912 | .node_offset_container_tag => |node_off| { | 1904 | .node_offset_container_tag => |node_off| { |
| 1913 | const tree = try src_loc.file_scope.getTree(gpa); | 1905 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1917,13 +1909,12 @@ pub const SrcLoc = struct { | ... | @@ -1917,13 +1909,12 @@ pub const SrcLoc = struct { |
| 1917 | switch (node_tags[parent_node]) { | 1909 | switch (node_tags[parent_node]) { |
| 1918 | .container_decl_arg, .container_decl_arg_trailing => { | 1910 | .container_decl_arg, .container_decl_arg_trailing => { |
| 1919 | const full = tree.containerDeclArg(parent_node); | 1911 | const full = tree.containerDeclArg(parent_node); |
| 1920 | return nodeToSpan(tree, full.ast.arg); | 1912 | return tree.nodeToSpan(full.ast.arg); |
| 1921 | }, | 1913 | }, |
| 1922 | .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { | 1914 | .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { |
| 1923 | const full = tree.taggedUnionEnumTag(parent_node); | 1915 | const full = tree.taggedUnionEnumTag(parent_node); |
| 1924 | 1916 | ||
| 1925 | return tokensToSpan( | 1917 | return tree.tokensToSpan( |
| 1926 | tree, | ||
| 1927 | tree.firstToken(full.ast.arg) - 2, | 1918 | tree.firstToken(full.ast.arg) - 2, |
| 1928 | tree.lastToken(full.ast.arg) + 1, | 1919 | tree.lastToken(full.ast.arg) + 1, |
| 1929 | tree.nodes.items(.main_token)[full.ast.arg], | 1920 | tree.nodes.items(.main_token)[full.ast.arg], |
| ... | @@ -1942,7 +1933,7 @@ pub const SrcLoc = struct { | ... | @@ -1942,7 +1933,7 @@ pub const SrcLoc = struct { |
| 1942 | .container_field_init => tree.containerFieldInit(parent_node), | 1933 | .container_field_init => tree.containerFieldInit(parent_node), |
| 1943 | else => unreachable, | 1934 | else => unreachable, |
| 1944 | }; | 1935 | }; |
| 1945 | return nodeToSpan(tree, full.ast.value_expr); | 1936 | return tree.nodeToSpan(full.ast.value_expr); |
| 1946 | }, | 1937 | }, |
| 1947 | .node_offset_init_ty => |node_off| { | 1938 | .node_offset_init_ty => |node_off| { |
| 1948 | const tree = try src_loc.file_scope.getTree(gpa); | 1939 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1950,7 +1941,7 @@ pub const SrcLoc = struct { | ... | @@ -1950,7 +1941,7 @@ pub const SrcLoc = struct { |
| 1950 | 1941 | ||
| 1951 | var buf: [2]Ast.Node.Index = undefined; | 1942 | var buf: [2]Ast.Node.Index = undefined; |
| 1952 | const full = tree.fullArrayInit(&buf, parent_node).?; | 1943 | const full = tree.fullArrayInit(&buf, parent_node).?; |
| 1953 | return nodeToSpan(tree, full.ast.type_expr); | 1944 | return tree.nodeToSpan(full.ast.type_expr); |
| 1954 | }, | 1945 | }, |
| 1955 | .node_offset_store_ptr => |node_off| { | 1946 | .node_offset_store_ptr => |node_off| { |
| 1956 | const tree = try src_loc.file_scope.getTree(gpa); | 1947 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | @@ -1960,9 +1951,9 @@ pub const SrcLoc = struct { | ... | @@ -1960,9 +1951,9 @@ pub const SrcLoc = struct { |
| 1960 | 1951 | ||
| 1961 | switch (node_tags[node]) { | 1952 | switch (node_tags[node]) { |
| 1962 | .assign => { | 1953 | .assign => { |
| 1963 | return nodeToSpan(tree, node_datas[node].lhs); | 1954 | return tree.nodeToSpan(node_datas[node].lhs); |
| 1964 | }, | 1955 | }, |
| 1965 | else => return nodeToSpan(tree, node), | 1956 | else => return tree.nodeToSpan(node), |
| 1966 | } | 1957 | } |
| 1967 | }, | 1958 | }, |
| 1968 | .node_offset_store_operand => |node_off| { | 1959 | .node_offset_store_operand => |node_off| { |
| ... | @@ -1973,9 +1964,9 @@ pub const SrcLoc = struct { | ... | @@ -1973,9 +1964,9 @@ pub const SrcLoc = struct { |
| 1973 | 1964 | ||
| 1974 | switch (node_tags[node]) { | 1965 | switch (node_tags[node]) { |
| 1975 | .assign => { | 1966 | .assign => { |
| 1976 | return nodeToSpan(tree, node_datas[node].rhs); | 1967 | return tree.nodeToSpan(node_datas[node].rhs); |
| 1977 | }, | 1968 | }, |
| 1978 | else => return nodeToSpan(tree, node), | 1969 | else => return tree.nodeToSpan(node), |
| 1979 | } | 1970 | } |
| 1980 | }, | 1971 | }, |
| 1981 | .node_offset_return_operand => |node_off| { | 1972 | .node_offset_return_operand => |node_off| { |
| ... | @@ -1984,9 +1975,9 @@ pub const SrcLoc = struct { | ... | @@ -1984,9 +1975,9 @@ pub const SrcLoc = struct { |
| 1984 | const node_tags = tree.nodes.items(.tag); | 1975 | const node_tags = tree.nodes.items(.tag); |
| 1985 | const node_datas = tree.nodes.items(.data); | 1976 | const node_datas = tree.nodes.items(.data); |
| 1986 | if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { | 1977 | if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { |
| 1987 | return nodeToSpan(tree, node_datas[node].lhs); | 1978 | return tree.nodeToSpan(node_datas[node].lhs); |
| 1988 | } | 1979 | } |
| 1989 | return nodeToSpan(tree, node); | 1980 | return tree.nodeToSpan(node); |
| 1990 | }, | 1981 | }, |
| 1991 | } | 1982 | } |
| 1992 | } | 1983 | } |
| ... | @@ -2010,40 +2001,7 @@ pub const SrcLoc = struct { | ... | @@ -2010,40 +2001,7 @@ pub const SrcLoc = struct { |
| 2010 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index], | 2001 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index], |
| 2011 | else => unreachable, | 2002 | else => unreachable, |
| 2012 | }; | 2003 | }; |
| 2013 | return nodeToSpan(tree, param); | 2004 | return tree.nodeToSpan(param); |
| 2014 | } | ||
| 2015 | |||
| 2016 | pub fn nodeToSpan(tree: *const Ast, node: u32) Span { | ||
| 2017 | return tokensToSpan( | ||
| 2018 | tree, | ||
| 2019 | tree.firstToken(node), | ||
| 2020 | tree.lastToken(node), | ||
| 2021 | tree.nodes.items(.main_token)[node], | ||
| 2022 | ); | ||
| 2023 | } | ||
| 2024 | |||
| 2025 | fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { | ||
| 2026 | return tokensToSpan(tree, token, token, token); | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { | ||
| 2030 | const token_starts = tree.tokens.items(.start); | ||
| 2031 | var start_tok = start; | ||
| 2032 | var end_tok = end; | ||
| 2033 | |||
| 2034 | if (tree.tokensOnSameLine(start, end)) { | ||
| 2035 | // do nothing | ||
| 2036 | } else if (tree.tokensOnSameLine(start, main)) { | ||
| 2037 | end_tok = main; | ||
| 2038 | } else if (tree.tokensOnSameLine(main, end)) { | ||
| 2039 | start_tok = main; | ||
| 2040 | } else { | ||
| 2041 | start_tok = main; | ||
| 2042 | end_tok = main; | ||
| 2043 | } | ||
| 2044 | const start_off = token_starts[start_tok]; | ||
| 2045 | const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | ||
| 2046 | return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; | ||
| 2047 | } | 2005 | } |
| 2048 | }; | 2006 | }; |
| 2049 | 2007 |
src/Package/Fetch.zig+1-2| ... | @@ -592,7 +592,7 @@ fn loadManifest(f: *Fetch, pkg_root: Package.Path) RunError!void { | ... | @@ -592,7 +592,7 @@ fn loadManifest(f: *Fetch, pkg_root: Package.Path) RunError!void { |
| 592 | 592 | ||
| 593 | if (ast.errors.len > 0) { | 593 | if (ast.errors.len > 0) { |
| 594 | const file_path = try std.fmt.allocPrint(arena, "{}" ++ Manifest.basename, .{pkg_root}); | 594 | const file_path = try std.fmt.allocPrint(arena, "{}" ++ Manifest.basename, .{pkg_root}); |
| 595 | try main.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); | 595 | try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); |
| 596 | return error.FetchFailed; | 596 | return error.FetchFailed; |
| 597 | } | 597 | } |
| 598 | 598 | ||
| ... | @@ -1690,7 +1690,6 @@ const Cache = std.Build.Cache; | ... | @@ -1690,7 +1690,6 @@ const Cache = std.Build.Cache; |
| 1690 | const ThreadPool = std.Thread.Pool; | 1690 | const ThreadPool = std.Thread.Pool; |
| 1691 | const WaitGroup = std.Thread.WaitGroup; | 1691 | const WaitGroup = std.Thread.WaitGroup; |
| 1692 | const Fetch = @This(); | 1692 | const Fetch = @This(); |
| 1693 | const main = @import("../main.zig"); | ||
| 1694 | const git = @import("Fetch/git.zig"); | 1693 | const git = @import("Fetch/git.zig"); |
| 1695 | const Package = @import("../Package.zig"); | 1694 | const Package = @import("../Package.zig"); |
| 1696 | const Manifest = Package.Manifest; | 1695 | const Manifest = Package.Manifest; |
src/main.zig+134-475| ... | @@ -8,6 +8,7 @@ const process = std.process; | ... | @@ -8,6 +8,7 @@ const process = std.process; |
| 8 | const Allocator = mem.Allocator; | 8 | const Allocator = mem.Allocator; |
| 9 | const ArrayList = std.ArrayList; | 9 | const ArrayList = std.ArrayList; |
| 10 | const Ast = std.zig.Ast; | 10 | const Ast = std.zig.Ast; |
| 11 | const Color = std.zig.Color; | ||
| 11 | const warn = std.log.warn; | 12 | const warn = std.log.warn; |
| 12 | const ThreadPool = std.Thread.Pool; | 13 | const ThreadPool = std.Thread.Pool; |
| 13 | const cleanExit = std.process.cleanExit; | 14 | const cleanExit = std.process.cleanExit; |
| ... | @@ -66,18 +67,8 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn { | ... | @@ -66,18 +67,8 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn { |
| 66 | process.exit(1); | 67 | process.exit(1); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | /// There are many assumptions in the entire codebase that Zig source files can | ||
| 70 | /// be byte-indexed with a u32 integer. | ||
| 71 | const max_src_size = std.math.maxInt(u32); | ||
| 72 | |||
| 73 | const debug_extensions_enabled = builtin.mode == .Debug; | 70 | const debug_extensions_enabled = builtin.mode == .Debug; |
| 74 | 71 | ||
| 75 | const Color = enum { | ||
| 76 | auto, | ||
| 77 | off, | ||
| 78 | on, | ||
| 79 | }; | ||
| 80 | |||
| 81 | const normal_usage = | 72 | const normal_usage = |
| 82 | \\Usage: zig [command] [options] | 73 | \\Usage: zig [command] [options] |
| 83 | \\ | 74 | \\ |
| ... | @@ -4501,7 +4492,7 @@ fn updateModule(comp: *Compilation, color: Color) !void { | ... | @@ -4501,7 +4492,7 @@ fn updateModule(comp: *Compilation, color: Color) !void { |
| 4501 | defer errors.deinit(comp.gpa); | 4492 | defer errors.deinit(comp.gpa); |
| 4502 | 4493 | ||
| 4503 | if (errors.errorMessageCount() > 0) { | 4494 | if (errors.errorMessageCount() > 0) { |
| 4504 | errors.renderToStdErr(renderOptions(color)); | 4495 | errors.renderToStdErr(color.renderOptions()); |
| 4505 | return error.SemanticAnalyzeFail; | 4496 | return error.SemanticAnalyzeFail; |
| 4506 | } | 4497 | } |
| 4507 | } | 4498 | } |
| ... | @@ -4601,7 +4592,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati | ... | @@ -4601,7 +4592,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati |
| 4601 | p.errors = errors; | 4592 | p.errors = errors; |
| 4602 | return; | 4593 | return; |
| 4603 | } else { | 4594 | } else { |
| 4604 | errors.renderToStdErr(renderOptions(color)); | 4595 | errors.renderToStdErr(color.renderOptions()); |
| 4605 | process.exit(1); | 4596 | process.exit(1); |
| 4606 | } | 4597 | } |
| 4607 | }, | 4598 | }, |
| ... | @@ -5528,7 +5519,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5528,7 +5519,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5528 | 5519 | ||
| 5529 | if (fetch.error_bundle.root_list.items.len > 0) { | 5520 | if (fetch.error_bundle.root_list.items.len > 0) { |
| 5530 | var errors = try fetch.error_bundle.toOwnedBundle(""); | 5521 | var errors = try fetch.error_bundle.toOwnedBundle(""); |
| 5531 | errors.renderToStdErr(renderOptions(color)); | 5522 | errors.renderToStdErr(color.renderOptions()); |
| 5532 | process.exit(1); | 5523 | process.exit(1); |
| 5533 | } | 5524 | } |
| 5534 | 5525 | ||
| ... | @@ -5719,470 +5710,155 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -5719,470 +5710,155 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5719 | } | 5710 | } |
| 5720 | } | 5711 | } |
| 5721 | 5712 | ||
| 5722 | fn readSourceFileToEndAlloc( | 5713 | fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5723 | allocator: Allocator, | 5714 | const color: Color = .auto; |
| 5724 | input: *const fs.File, | ||
| 5725 | size_hint: ?usize, | ||
| 5726 | ) ![:0]u8 { | ||
| 5727 | const source_code = input.readToEndAllocOptions( | ||
| 5728 | allocator, | ||
| 5729 | max_src_size, | ||
| 5730 | size_hint, | ||
| 5731 | @alignOf(u16), | ||
| 5732 | 0, | ||
| 5733 | ) catch |err| switch (err) { | ||
| 5734 | error.ConnectionResetByPeer => unreachable, | ||
| 5735 | error.ConnectionTimedOut => unreachable, | ||
| 5736 | error.NotOpenForReading => unreachable, | ||
| 5737 | else => |e| return e, | ||
| 5738 | }; | ||
| 5739 | errdefer allocator.free(source_code); | ||
| 5740 | 5715 | ||
| 5741 | // Detect unsupported file types with their Byte Order Mark | 5716 | const target_query: std.Target.Query = .{}; |
| 5742 | const unsupported_boms = [_][]const u8{ | 5717 | const resolved_target: Package.Module.ResolvedTarget = .{ |
| 5743 | "\xff\xfe\x00\x00", // UTF-32 little endian | 5718 | .result = resolveTargetQueryOrFatal(target_query), |
| 5744 | "\xfe\xff\x00\x00", // UTF-32 big endian | 5719 | .is_native_os = true, |
| 5745 | "\xfe\xff", // UTF-16 big endian | 5720 | .is_native_abi = true, |
| 5746 | }; | 5721 | }; |
| 5747 | for (unsupported_boms) |bom| { | ||
| 5748 | if (mem.startsWith(u8, source_code, bom)) { | ||
| 5749 | return error.UnsupportedEncoding; | ||
| 5750 | } | ||
| 5751 | } | ||
| 5752 | 5722 | ||
| 5753 | // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 | 5723 | const exe_basename = try std.zig.binNameAlloc(arena, .{ |
| 5754 | if (mem.startsWith(u8, source_code, "\xff\xfe")) { | 5724 | .root_name = "fmt", |
| 5755 | const source_code_utf16_le = mem.bytesAsSlice(u16, source_code); | 5725 | .target = resolved_target.result, |
| 5756 | const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(allocator, source_code_utf16_le) catch |err| switch (err) { | 5726 | .output_mode = .Exe, |
| 5757 | error.DanglingSurrogateHalf => error.UnsupportedEncoding, | 5727 | }); |
| 5758 | error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, | 5728 | const emit_bin: Compilation.EmitLoc = .{ |
| 5759 | error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, | 5729 | .directory = null, // Use the global zig-cache. |
| 5760 | else => |e| return e, | 5730 | .basename = exe_basename, |
| 5761 | }; | 5731 | }; |
| 5762 | 5732 | ||
| 5763 | allocator.free(source_code); | 5733 | const self_exe_path = introspect.findZigExePath(arena) catch |err| { |
| 5764 | return source_code_utf8; | 5734 | fatal("unable to find self exe path: {s}", .{@errorName(err)}); |
| 5765 | } | 5735 | }; |
| 5766 | 5736 | ||
| 5767 | return source_code; | 5737 | const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); |
| 5768 | } | 5738 | const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); |
| 5769 | 5739 | ||
| 5770 | const usage_fmt = | 5740 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ |
| 5771 | \\Usage: zig fmt [file]... | 5741 | .path = lib_dir, |
| 5772 | \\ | 5742 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { |
| 5773 | \\ Formats the input files and modifies them in-place. | 5743 | fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) }); |
| 5774 | \\ Arguments can be files or directories, which are searched | 5744 | }, |
| 5775 | \\ recursively. | 5745 | } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| 5776 | \\ | 5746 | fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); |
| 5777 | \\Options: | 5747 | }; |
| 5778 | \\ -h, --help Print this help and exit | 5748 | defer zig_lib_directory.handle.close(); |
| 5779 | \\ --color [auto|off|on] Enable or disable colored error messages | ||
| 5780 | \\ --stdin Format code from stdin; output to stdout | ||
| 5781 | \\ --check List non-conforming files and exit with an error | ||
| 5782 | \\ if the list is non-empty | ||
| 5783 | \\ --ast-check Run zig ast-check on every file | ||
| 5784 | \\ --exclude [file] Exclude file or directory from formatting | ||
| 5785 | \\ | ||
| 5786 | \\ | ||
| 5787 | ; | ||
| 5788 | 5749 | ||
| 5789 | const Fmt = struct { | 5750 | var global_cache_directory: Compilation.Directory = l: { |
| 5790 | seen: SeenMap, | 5751 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); |
| 5791 | any_error: bool, | 5752 | break :l .{ |
| 5792 | check_ast: bool, | 5753 | .handle = try fs.cwd().makeOpenPath(p, .{}), |
| 5793 | color: Color, | 5754 | .path = p, |
| 5794 | gpa: Allocator, | 5755 | }; |
| 5795 | arena: Allocator, | 5756 | }; |
| 5796 | out_buffer: std.ArrayList(u8), | 5757 | defer global_cache_directory.handle.close(); |
| 5797 | 5758 | ||
| 5798 | const SeenMap = std.AutoHashMap(fs.File.INode, void); | 5759 | var thread_pool: ThreadPool = undefined; |
| 5799 | }; | 5760 | try thread_pool.init(.{ .allocator = gpa }); |
| 5761 | defer thread_pool.deinit(); | ||
| 5800 | 5762 | ||
| 5801 | fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | 5763 | var child_argv: std.ArrayListUnmanaged([]const u8) = .{}; |
| 5802 | var color: Color = .auto; | 5764 | try child_argv.ensureUnusedCapacity(arena, args.len + 1); |
| 5803 | var stdin_flag: bool = false; | ||
| 5804 | var check_flag: bool = false; | ||
| 5805 | var check_ast_flag: bool = false; | ||
| 5806 | var input_files = ArrayList([]const u8).init(gpa); | ||
| 5807 | defer input_files.deinit(); | ||
| 5808 | var excluded_files = ArrayList([]const u8).init(gpa); | ||
| 5809 | defer excluded_files.deinit(); | ||
| 5810 | 5765 | ||
| 5766 | // We want to release all the locks before executing the child process, so we make a nice | ||
| 5767 | // big block here to ensure the cleanup gets run when we extract out our argv. | ||
| 5811 | { | 5768 | { |
| 5812 | var i: usize = 0; | 5769 | const main_mod_paths: Package.Module.CreateOptions.Paths = .{ |
| 5813 | while (i < args.len) : (i += 1) { | 5770 | .root = .{ |
| 5814 | const arg = args[i]; | 5771 | .root_dir = zig_lib_directory, |
| 5815 | if (mem.startsWith(u8, arg, "-")) { | 5772 | .sub_path = "std/zig", |
| 5816 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { | 5773 | }, |
| 5817 | const stdout = io.getStdOut().writer(); | 5774 | .root_src_path = "fmt.zig", |
| 5818 | try stdout.writeAll(usage_fmt); | ||
| 5819 | return cleanExit(); | ||
| 5820 | } else if (mem.eql(u8, arg, "--color")) { | ||
| 5821 | if (i + 1 >= args.len) { | ||
| 5822 | fatal("expected [auto|on|off] after --color", .{}); | ||
| 5823 | } | ||
| 5824 | i += 1; | ||
| 5825 | const next_arg = args[i]; | ||
| 5826 | color = std.meta.stringToEnum(Color, next_arg) orelse { | ||
| 5827 | fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); | ||
| 5828 | }; | ||
| 5829 | } else if (mem.eql(u8, arg, "--stdin")) { | ||
| 5830 | stdin_flag = true; | ||
| 5831 | } else if (mem.eql(u8, arg, "--check")) { | ||
| 5832 | check_flag = true; | ||
| 5833 | } else if (mem.eql(u8, arg, "--ast-check")) { | ||
| 5834 | check_ast_flag = true; | ||
| 5835 | } else if (mem.eql(u8, arg, "--exclude")) { | ||
| 5836 | if (i + 1 >= args.len) { | ||
| 5837 | fatal("expected parameter after --exclude", .{}); | ||
| 5838 | } | ||
| 5839 | i += 1; | ||
| 5840 | const next_arg = args[i]; | ||
| 5841 | try excluded_files.append(next_arg); | ||
| 5842 | } else { | ||
| 5843 | fatal("unrecognized parameter: '{s}'", .{arg}); | ||
| 5844 | } | ||
| 5845 | } else { | ||
| 5846 | try input_files.append(arg); | ||
| 5847 | } | ||
| 5848 | } | ||
| 5849 | } | ||
| 5850 | |||
| 5851 | if (stdin_flag) { | ||
| 5852 | if (input_files.items.len != 0) { | ||
| 5853 | fatal("cannot use --stdin with positional arguments", .{}); | ||
| 5854 | } | ||
| 5855 | |||
| 5856 | const stdin = io.getStdIn(); | ||
| 5857 | const source_code = readSourceFileToEndAlloc(gpa, &stdin, null) catch |err| { | ||
| 5858 | fatal("unable to read stdin: {}", .{err}); | ||
| 5859 | }; | ||
| 5860 | defer gpa.free(source_code); | ||
| 5861 | |||
| 5862 | var tree = Ast.parse(gpa, source_code, .zig) catch |err| { | ||
| 5863 | fatal("error parsing stdin: {}", .{err}); | ||
| 5864 | }; | 5775 | }; |
| 5865 | defer tree.deinit(gpa); | ||
| 5866 | |||
| 5867 | if (check_ast_flag) { | ||
| 5868 | var file: Module.File = .{ | ||
| 5869 | .status = .never_loaded, | ||
| 5870 | .source_loaded = true, | ||
| 5871 | .zir_loaded = false, | ||
| 5872 | .sub_file_path = "<stdin>", | ||
| 5873 | .source = source_code, | ||
| 5874 | .stat = undefined, | ||
| 5875 | .tree = tree, | ||
| 5876 | .tree_loaded = true, | ||
| 5877 | .zir = undefined, | ||
| 5878 | .mod = undefined, | ||
| 5879 | .root_decl = .none, | ||
| 5880 | }; | ||
| 5881 | |||
| 5882 | file.mod = try Package.Module.createLimited(arena, .{ | ||
| 5883 | .root = Package.Path.cwd(), | ||
| 5884 | .root_src_path = file.sub_file_path, | ||
| 5885 | .fully_qualified_name = "root", | ||
| 5886 | }); | ||
| 5887 | |||
| 5888 | file.zir = try AstGen.generate(gpa, file.tree); | ||
| 5889 | file.zir_loaded = true; | ||
| 5890 | defer file.zir.deinit(gpa); | ||
| 5891 | |||
| 5892 | if (file.zir.hasCompileErrors()) { | ||
| 5893 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 5894 | try wip_errors.init(gpa); | ||
| 5895 | defer wip_errors.deinit(); | ||
| 5896 | try Compilation.addZirErrorMessages(&wip_errors, &file); | ||
| 5897 | var error_bundle = try wip_errors.toOwnedBundle(""); | ||
| 5898 | defer error_bundle.deinit(gpa); | ||
| 5899 | error_bundle.renderToStdErr(renderOptions(color)); | ||
| 5900 | process.exit(2); | ||
| 5901 | } | ||
| 5902 | } else if (tree.errors.len != 0) { | ||
| 5903 | try printAstErrorsToStderr(gpa, tree, "<stdin>", color); | ||
| 5904 | process.exit(2); | ||
| 5905 | } | ||
| 5906 | const formatted = try tree.render(gpa); | ||
| 5907 | defer gpa.free(formatted); | ||
| 5908 | |||
| 5909 | if (check_flag) { | ||
| 5910 | const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code)); | ||
| 5911 | process.exit(code); | ||
| 5912 | } | ||
| 5913 | 5776 | ||
| 5914 | return io.getStdOut().writeAll(formatted); | 5777 | const config = try Compilation.Config.resolve(.{ |
| 5915 | } | 5778 | .output_mode = .Exe, |
| 5779 | .root_optimize_mode = .ReleaseFast, | ||
| 5780 | .resolved_target = resolved_target, | ||
| 5781 | .have_zcu = true, | ||
| 5782 | .emit_bin = true, | ||
| 5783 | .is_test = false, | ||
| 5784 | }); | ||
| 5916 | 5785 | ||
| 5917 | if (input_files.items.len == 0) { | 5786 | const root_mod = try Package.Module.create(arena, .{ |
| 5918 | fatal("expected at least one source file argument", .{}); | 5787 | .global_cache_directory = global_cache_directory, |
| 5919 | } | 5788 | .paths = main_mod_paths, |
| 5789 | .fully_qualified_name = "root", | ||
| 5790 | .cc_argv = &.{}, | ||
| 5791 | .inherited = .{ | ||
| 5792 | .resolved_target = resolved_target, | ||
| 5793 | .optimize_mode = .ReleaseFast, | ||
| 5794 | }, | ||
| 5795 | .global = config, | ||
| 5796 | .parent = null, | ||
| 5797 | .builtin_mod = null, | ||
| 5798 | }); | ||
| 5920 | 5799 | ||
| 5921 | var fmt = Fmt{ | 5800 | const comp = Compilation.create(gpa, arena, .{ |
| 5922 | .gpa = gpa, | 5801 | .zig_lib_directory = zig_lib_directory, |
| 5923 | .arena = arena, | 5802 | .local_cache_directory = global_cache_directory, |
| 5924 | .seen = Fmt.SeenMap.init(gpa), | 5803 | .global_cache_directory = global_cache_directory, |
| 5925 | .any_error = false, | 5804 | .root_name = "fmt", |
| 5926 | .check_ast = check_ast_flag, | 5805 | .config = config, |
| 5927 | .color = color, | 5806 | .root_mod = root_mod, |
| 5928 | .out_buffer = std.ArrayList(u8).init(gpa), | 5807 | .main_mod = root_mod, |
| 5929 | }; | 5808 | .emit_bin = emit_bin, |
| 5930 | defer fmt.seen.deinit(); | 5809 | .emit_h = null, |
| 5931 | defer fmt.out_buffer.deinit(); | 5810 | .self_exe_path = self_exe_path, |
| 5811 | .thread_pool = &thread_pool, | ||
| 5812 | .cache_mode = .whole, | ||
| 5813 | }) catch |err| { | ||
| 5814 | fatal("unable to create compilation: {s}", .{@errorName(err)}); | ||
| 5815 | }; | ||
| 5816 | defer comp.destroy(); | ||
| 5932 | 5817 | ||
| 5933 | // Mark any excluded files/directories as already seen, | 5818 | updateModule(comp, color) catch |err| switch (err) { |
| 5934 | // so that they are skipped later during actual processing | 5819 | error.SemanticAnalyzeFail => process.exit(2), |
| 5935 | for (excluded_files.items) |file_path| { | ||
| 5936 | const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { | ||
| 5937 | error.FileNotFound => continue, | ||
| 5938 | // On Windows, statFile does not work for directories | ||
| 5939 | error.IsDir => dir: { | ||
| 5940 | var dir = try fs.cwd().openDir(file_path, .{}); | ||
| 5941 | defer dir.close(); | ||
| 5942 | break :dir try dir.stat(); | ||
| 5943 | }, | ||
| 5944 | else => |e| return e, | 5820 | else => |e| return e, |
| 5945 | }; | 5821 | }; |
| 5946 | try fmt.seen.put(stat.inode, {}); | ||
| 5947 | } | ||
| 5948 | |||
| 5949 | for (input_files.items) |file_path| { | ||
| 5950 | try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); | ||
| 5951 | } | ||
| 5952 | if (fmt.any_error) { | ||
| 5953 | process.exit(1); | ||
| 5954 | } | ||
| 5955 | } | ||
| 5956 | |||
| 5957 | const FmtError = error{ | ||
| 5958 | SystemResources, | ||
| 5959 | OperationAborted, | ||
| 5960 | IoPending, | ||
| 5961 | BrokenPipe, | ||
| 5962 | Unexpected, | ||
| 5963 | WouldBlock, | ||
| 5964 | FileClosed, | ||
| 5965 | DestinationAddressRequired, | ||
| 5966 | DiskQuota, | ||
| 5967 | FileTooBig, | ||
| 5968 | InputOutput, | ||
| 5969 | NoSpaceLeft, | ||
| 5970 | AccessDenied, | ||
| 5971 | OutOfMemory, | ||
| 5972 | RenameAcrossMountPoints, | ||
| 5973 | ReadOnlyFileSystem, | ||
| 5974 | LinkQuotaExceeded, | ||
| 5975 | FileBusy, | ||
| 5976 | EndOfStream, | ||
| 5977 | Unseekable, | ||
| 5978 | NotOpenForWriting, | ||
| 5979 | UnsupportedEncoding, | ||
| 5980 | ConnectionResetByPeer, | ||
| 5981 | SocketNotConnected, | ||
| 5982 | LockViolation, | ||
| 5983 | NetNameDeleted, | ||
| 5984 | InvalidArgument, | ||
| 5985 | } || fs.File.OpenError; | ||
| 5986 | |||
| 5987 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { | ||
| 5988 | fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { | ||
| 5989 | error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), | ||
| 5990 | else => { | ||
| 5991 | warn("unable to format '{s}': {s}", .{ file_path, @errorName(err) }); | ||
| 5992 | fmt.any_error = true; | ||
| 5993 | return; | ||
| 5994 | }, | ||
| 5995 | }; | ||
| 5996 | } | ||
| 5997 | |||
| 5998 | fn fmtPathDir( | ||
| 5999 | fmt: *Fmt, | ||
| 6000 | file_path: []const u8, | ||
| 6001 | check_mode: bool, | ||
| 6002 | parent_dir: fs.Dir, | ||
| 6003 | parent_sub_path: []const u8, | ||
| 6004 | ) FmtError!void { | ||
| 6005 | var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); | ||
| 6006 | defer dir.close(); | ||
| 6007 | |||
| 6008 | const stat = try dir.stat(); | ||
| 6009 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; | ||
| 6010 | |||
| 6011 | var dir_it = dir.iterate(); | ||
| 6012 | while (try dir_it.next()) |entry| { | ||
| 6013 | const is_dir = entry.kind == .directory; | ||
| 6014 | |||
| 6015 | if (is_dir and (mem.eql(u8, entry.name, "zig-cache") or mem.eql(u8, entry.name, "zig-out"))) continue; | ||
| 6016 | |||
| 6017 | if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) { | ||
| 6018 | const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name }); | ||
| 6019 | defer fmt.gpa.free(full_path); | ||
| 6020 | |||
| 6021 | if (is_dir) { | ||
| 6022 | try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); | ||
| 6023 | } else { | ||
| 6024 | fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { | ||
| 6025 | warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); | ||
| 6026 | fmt.any_error = true; | ||
| 6027 | return; | ||
| 6028 | }; | ||
| 6029 | } | ||
| 6030 | } | ||
| 6031 | } | ||
| 6032 | } | ||
| 6033 | |||
| 6034 | fn fmtPathFile( | ||
| 6035 | fmt: *Fmt, | ||
| 6036 | file_path: []const u8, | ||
| 6037 | check_mode: bool, | ||
| 6038 | dir: fs.Dir, | ||
| 6039 | sub_path: []const u8, | ||
| 6040 | ) FmtError!void { | ||
| 6041 | const source_file = try dir.openFile(sub_path, .{}); | ||
| 6042 | var file_closed = false; | ||
| 6043 | errdefer if (!file_closed) source_file.close(); | ||
| 6044 | |||
| 6045 | const stat = try source_file.stat(); | ||
| 6046 | |||
| 6047 | if (stat.kind == .directory) | ||
| 6048 | return error.IsDir; | ||
| 6049 | |||
| 6050 | const gpa = fmt.gpa; | ||
| 6051 | const source_code = try readSourceFileToEndAlloc( | ||
| 6052 | gpa, | ||
| 6053 | &source_file, | ||
| 6054 | std.math.cast(usize, stat.size) orelse return error.FileTooBig, | ||
| 6055 | ); | ||
| 6056 | defer gpa.free(source_code); | ||
| 6057 | |||
| 6058 | source_file.close(); | ||
| 6059 | file_closed = true; | ||
| 6060 | |||
| 6061 | // Add to set after no longer possible to get error.IsDir. | ||
| 6062 | if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; | ||
| 6063 | |||
| 6064 | var tree = try Ast.parse(gpa, source_code, .zig); | ||
| 6065 | defer tree.deinit(gpa); | ||
| 6066 | 5822 | ||
| 6067 | if (tree.errors.len != 0) { | 5823 | const fmt_exe = try global_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); |
| 6068 | try printAstErrorsToStderr(gpa, tree, file_path, fmt.color); | 5824 | child_argv.appendAssumeCapacity(fmt_exe); |
| 6069 | fmt.any_error = true; | ||
| 6070 | return; | ||
| 6071 | } | 5825 | } |
| 6072 | 5826 | ||
| 6073 | if (fmt.check_ast) { | 5827 | child_argv.appendSliceAssumeCapacity(args); |
| 6074 | var file: Module.File = .{ | ||
| 6075 | .status = .never_loaded, | ||
| 6076 | .source_loaded = true, | ||
| 6077 | .zir_loaded = false, | ||
| 6078 | .sub_file_path = file_path, | ||
| 6079 | .source = source_code, | ||
| 6080 | .stat = .{ | ||
| 6081 | .size = stat.size, | ||
| 6082 | .inode = stat.inode, | ||
| 6083 | .mtime = stat.mtime, | ||
| 6084 | }, | ||
| 6085 | .tree = tree, | ||
| 6086 | .tree_loaded = true, | ||
| 6087 | .zir = undefined, | ||
| 6088 | .mod = undefined, | ||
| 6089 | .root_decl = .none, | ||
| 6090 | }; | ||
| 6091 | 5828 | ||
| 6092 | file.mod = try Package.Module.createLimited(fmt.arena, .{ | 5829 | if (process.can_execv) { |
| 6093 | .root = Package.Path.cwd(), | 5830 | const err = process.execv(gpa, child_argv.items); |
| 6094 | .root_src_path = file.sub_file_path, | 5831 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 6095 | .fully_qualified_name = "root", | 5832 | fatal("the following command failed to execve with '{s}':\n{s}", .{ |
| 5833 | @errorName(err), | ||
| 5834 | cmd, | ||
| 6096 | }); | 5835 | }); |
| 6097 | |||
| 6098 | if (stat.size > max_src_size) | ||
| 6099 | return error.FileTooBig; | ||
| 6100 | |||
| 6101 | file.zir = try AstGen.generate(gpa, file.tree); | ||
| 6102 | file.zir_loaded = true; | ||
| 6103 | defer file.zir.deinit(gpa); | ||
| 6104 | |||
| 6105 | if (file.zir.hasCompileErrors()) { | ||
| 6106 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 6107 | try wip_errors.init(gpa); | ||
| 6108 | defer wip_errors.deinit(); | ||
| 6109 | try Compilation.addZirErrorMessages(&wip_errors, &file); | ||
| 6110 | var error_bundle = try wip_errors.toOwnedBundle(""); | ||
| 6111 | defer error_bundle.deinit(gpa); | ||
| 6112 | error_bundle.renderToStdErr(renderOptions(fmt.color)); | ||
| 6113 | fmt.any_error = true; | ||
| 6114 | } | ||
| 6115 | } | 5836 | } |
| 6116 | 5837 | ||
| 6117 | // As a heuristic, we make enough capacity for the same as the input source. | 5838 | if (!process.can_spawn) { |
| 6118 | fmt.out_buffer.shrinkRetainingCapacity(0); | 5839 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 6119 | try fmt.out_buffer.ensureTotalCapacity(source_code.len); | 5840 | fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ |
| 6120 | 5841 | @tagName(builtin.os.tag), cmd, | |
| 6121 | try tree.renderToArrayList(&fmt.out_buffer, .{}); | 5842 | }); |
| 6122 | if (mem.eql(u8, fmt.out_buffer.items, source_code)) | ||
| 6123 | return; | ||
| 6124 | |||
| 6125 | if (check_mode) { | ||
| 6126 | const stdout = io.getStdOut().writer(); | ||
| 6127 | try stdout.print("{s}\n", .{file_path}); | ||
| 6128 | fmt.any_error = true; | ||
| 6129 | } else { | ||
| 6130 | var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode }); | ||
| 6131 | defer af.deinit(); | ||
| 6132 | |||
| 6133 | try af.file.writeAll(fmt.out_buffer.items); | ||
| 6134 | try af.finish(); | ||
| 6135 | const stdout = io.getStdOut().writer(); | ||
| 6136 | try stdout.print("{s}\n", .{file_path}); | ||
| 6137 | } | 5843 | } |
| 6138 | } | ||
| 6139 | |||
| 6140 | fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { | ||
| 6141 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | ||
| 6142 | try wip_errors.init(gpa); | ||
| 6143 | defer wip_errors.deinit(); | ||
| 6144 | 5844 | ||
| 6145 | try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); | 5845 | var child = std.ChildProcess.init(child_argv.items, gpa); |
| 5846 | child.stdin_behavior = .Inherit; | ||
| 5847 | child.stdout_behavior = .Inherit; | ||
| 5848 | child.stderr_behavior = .Inherit; | ||
| 6146 | 5849 | ||
| 6147 | var error_bundle = try wip_errors.toOwnedBundle(""); | 5850 | const term = try child.spawnAndWait(); |
| 6148 | defer error_bundle.deinit(gpa); | 5851 | switch (term) { |
| 6149 | error_bundle.renderToStdErr(renderOptions(color)); | 5852 | .Exited => |code| { |
| 6150 | } | 5853 | if (code == 0) return cleanExit(); |
| 6151 | 5854 | const cmd = try std.mem.join(arena, " ", child_argv.items); | |
| 6152 | pub fn putAstErrorsIntoBundle( | 5855 | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); |
| 6153 | gpa: Allocator, | ||
| 6154 | tree: Ast, | ||
| 6155 | path: []const u8, | ||
| 6156 | wip_errors: *std.zig.ErrorBundle.Wip, | ||
| 6157 | ) Allocator.Error!void { | ||
| 6158 | var file: Module.File = .{ | ||
| 6159 | .status = .never_loaded, | ||
| 6160 | .source_loaded = true, | ||
| 6161 | .zir_loaded = false, | ||
| 6162 | .sub_file_path = path, | ||
| 6163 | .source = tree.source, | ||
| 6164 | .stat = .{ | ||
| 6165 | .size = 0, | ||
| 6166 | .inode = 0, | ||
| 6167 | .mtime = 0, | ||
| 6168 | }, | 5856 | }, |
| 6169 | .tree = tree, | 5857 | else => { |
| 6170 | .tree_loaded = true, | 5858 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 6171 | .zir = undefined, | 5859 | fatal("the following build command crashed:\n{s}", .{cmd}); |
| 6172 | .mod = try Package.Module.createLimited(gpa, .{ | 5860 | }, |
| 6173 | .root = Package.Path.cwd(), | 5861 | } |
| 6174 | .root_src_path = path, | ||
| 6175 | .fully_qualified_name = "root", | ||
| 6176 | }), | ||
| 6177 | .root_decl = .none, | ||
| 6178 | }; | ||
| 6179 | defer gpa.destroy(file.mod); | ||
| 6180 | |||
| 6181 | file.zir = try AstGen.generate(gpa, file.tree); | ||
| 6182 | file.zir_loaded = true; | ||
| 6183 | defer file.zir.deinit(gpa); | ||
| 6184 | |||
| 6185 | try Compilation.addZirErrorMessages(wip_errors, &file); | ||
| 6186 | } | 5862 | } |
| 6187 | 5863 | ||
| 6188 | const info_zen = | 5864 | const info_zen = |
| ... | @@ -6710,7 +6386,7 @@ fn cmdAstCheck( | ... | @@ -6710,7 +6386,7 @@ fn cmdAstCheck( |
| 6710 | 6386 | ||
| 6711 | const stat = try f.stat(); | 6387 | const stat = try f.stat(); |
| 6712 | 6388 | ||
| 6713 | if (stat.size > max_src_size) | 6389 | if (stat.size > std.zig.max_src_size) |
| 6714 | return error.FileTooBig; | 6390 | return error.FileTooBig; |
| 6715 | 6391 | ||
| 6716 | const source = try arena.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); | 6392 | const source = try arena.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); |
| ... | @@ -6728,7 +6404,7 @@ fn cmdAstCheck( | ... | @@ -6728,7 +6404,7 @@ fn cmdAstCheck( |
| 6728 | }; | 6404 | }; |
| 6729 | } else { | 6405 | } else { |
| 6730 | const stdin = io.getStdIn(); | 6406 | const stdin = io.getStdIn(); |
| 6731 | const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| { | 6407 | const source = std.zig.readSourceFileToEndAlloc(arena, stdin, null) catch |err| { |
| 6732 | fatal("unable to read stdin: {}", .{err}); | 6408 | fatal("unable to read stdin: {}", .{err}); |
| 6733 | }; | 6409 | }; |
| 6734 | file.sub_file_path = "<stdin>"; | 6410 | file.sub_file_path = "<stdin>"; |
| ... | @@ -6758,7 +6434,7 @@ fn cmdAstCheck( | ... | @@ -6758,7 +6434,7 @@ fn cmdAstCheck( |
| 6758 | try Compilation.addZirErrorMessages(&wip_errors, &file); | 6434 | try Compilation.addZirErrorMessages(&wip_errors, &file); |
| 6759 | var error_bundle = try wip_errors.toOwnedBundle(""); | 6435 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 6760 | defer error_bundle.deinit(gpa); | 6436 | defer error_bundle.deinit(gpa); |
| 6761 | error_bundle.renderToStdErr(renderOptions(color)); | 6437 | error_bundle.renderToStdErr(color.renderOptions()); |
| 6762 | process.exit(1); | 6438 | process.exit(1); |
| 6763 | } | 6439 | } |
| 6764 | 6440 | ||
| ... | @@ -6889,7 +6565,7 @@ fn cmdChangelist( | ... | @@ -6889,7 +6565,7 @@ fn cmdChangelist( |
| 6889 | 6565 | ||
| 6890 | const stat = try f.stat(); | 6566 | const stat = try f.stat(); |
| 6891 | 6567 | ||
| 6892 | if (stat.size > max_src_size) | 6568 | if (stat.size > std.zig.max_src_size) |
| 6893 | return error.FileTooBig; | 6569 | return error.FileTooBig; |
| 6894 | 6570 | ||
| 6895 | var file: Module.File = .{ | 6571 | var file: Module.File = .{ |
| ... | @@ -6938,7 +6614,7 @@ fn cmdChangelist( | ... | @@ -6938,7 +6614,7 @@ fn cmdChangelist( |
| 6938 | try Compilation.addZirErrorMessages(&wip_errors, &file); | 6614 | try Compilation.addZirErrorMessages(&wip_errors, &file); |
| 6939 | var error_bundle = try wip_errors.toOwnedBundle(""); | 6615 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 6940 | defer error_bundle.deinit(gpa); | 6616 | defer error_bundle.deinit(gpa); |
| 6941 | error_bundle.renderToStdErr(renderOptions(color)); | 6617 | error_bundle.renderToStdErr(color.renderOptions()); |
| 6942 | process.exit(1); | 6618 | process.exit(1); |
| 6943 | } | 6619 | } |
| 6944 | 6620 | ||
| ... | @@ -6949,7 +6625,7 @@ fn cmdChangelist( | ... | @@ -6949,7 +6625,7 @@ fn cmdChangelist( |
| 6949 | 6625 | ||
| 6950 | const new_stat = try new_f.stat(); | 6626 | const new_stat = try new_f.stat(); |
| 6951 | 6627 | ||
| 6952 | if (new_stat.size > max_src_size) | 6628 | if (new_stat.size > std.zig.max_src_size) |
| 6953 | return error.FileTooBig; | 6629 | return error.FileTooBig; |
| 6954 | 6630 | ||
| 6955 | const new_source = try arena.allocSentinel(u8, @as(usize, @intCast(new_stat.size)), 0); | 6631 | const new_source = try arena.allocSentinel(u8, @as(usize, @intCast(new_stat.size)), 0); |
| ... | @@ -6973,7 +6649,7 @@ fn cmdChangelist( | ... | @@ -6973,7 +6649,7 @@ fn cmdChangelist( |
| 6973 | try Compilation.addZirErrorMessages(&wip_errors, &file); | 6649 | try Compilation.addZirErrorMessages(&wip_errors, &file); |
| 6974 | var error_bundle = try wip_errors.toOwnedBundle(""); | 6650 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 6975 | defer error_bundle.deinit(gpa); | 6651 | defer error_bundle.deinit(gpa); |
| 6976 | error_bundle.renderToStdErr(renderOptions(color)); | 6652 | error_bundle.renderToStdErr(color.renderOptions()); |
| 6977 | process.exit(1); | 6653 | process.exit(1); |
| 6978 | } | 6654 | } |
| 6979 | 6655 | ||
| ... | @@ -7241,23 +6917,6 @@ const ClangSearchSanitizer = struct { | ... | @@ -7241,23 +6917,6 @@ const ClangSearchSanitizer = struct { |
| 7241 | }; | 6917 | }; |
| 7242 | }; | 6918 | }; |
| 7243 | 6919 | ||
| 7244 | fn get_tty_conf(color: Color) std.io.tty.Config { | ||
| 7245 | return switch (color) { | ||
| 7246 | .auto => std.io.tty.detectConfig(std.io.getStdErr()), | ||
| 7247 | .on => .escape_codes, | ||
| 7248 | .off => .no_color, | ||
| 7249 | }; | ||
| 7250 | } | ||
| 7251 | |||
| 7252 | fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { | ||
| 7253 | const ttyconf = get_tty_conf(color); | ||
| 7254 | return .{ | ||
| 7255 | .ttyconf = ttyconf, | ||
| 7256 | .include_source_line = ttyconf != .no_color, | ||
| 7257 | .include_reference_trace = ttyconf != .no_color, | ||
| 7258 | }; | ||
| 7259 | } | ||
| 7260 | |||
| 7261 | fn accessLibPath( | 6920 | fn accessLibPath( |
| 7262 | test_path: *std.ArrayList(u8), | 6921 | test_path: *std.ArrayList(u8), |
| 7263 | checked_paths: *std.ArrayList(u8), | 6922 | checked_paths: *std.ArrayList(u8), |
| ... | @@ -7498,7 +7157,7 @@ fn cmdFetch( | ... | @@ -7498,7 +7157,7 @@ fn cmdFetch( |
| 7498 | 7157 | ||
| 7499 | if (fetch.error_bundle.root_list.items.len > 0) { | 7158 | if (fetch.error_bundle.root_list.items.len > 0) { |
| 7500 | var errors = try fetch.error_bundle.toOwnedBundle(""); | 7159 | var errors = try fetch.error_bundle.toOwnedBundle(""); |
| 7501 | errors.renderToStdErr(renderOptions(color)); | 7160 | errors.renderToStdErr(color.renderOptions()); |
| 7502 | process.exit(1); | 7161 | process.exit(1); |
| 7503 | } | 7162 | } |
| 7504 | 7163 | ||
| ... | @@ -7790,7 +7449,7 @@ fn loadManifest( | ... | @@ -7790,7 +7449,7 @@ fn loadManifest( |
| 7790 | errdefer ast.deinit(gpa); | 7449 | errdefer ast.deinit(gpa); |
| 7791 | 7450 | ||
| 7792 | if (ast.errors.len > 0) { | 7451 | if (ast.errors.len > 0) { |
| 7793 | try printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color); | 7452 | try std.zig.printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color); |
| 7794 | process.exit(2); | 7453 | process.exit(2); |
| 7795 | } | 7454 | } |
| 7796 | 7455 | ||
| ... | @@ -7807,7 +7466,7 @@ fn loadManifest( | ... | @@ -7807,7 +7466,7 @@ fn loadManifest( |
| 7807 | 7466 | ||
| 7808 | var error_bundle = try wip_errors.toOwnedBundle(""); | 7467 | var error_bundle = try wip_errors.toOwnedBundle(""); |
| 7809 | defer error_bundle.deinit(gpa); | 7468 | defer error_bundle.deinit(gpa); |
| 7810 | error_bundle.renderToStdErr(renderOptions(options.color)); | 7469 | error_bundle.renderToStdErr(options.color.renderOptions()); |
| 7811 | 7470 | ||
| 7812 | process.exit(2); | 7471 | process.exit(2); |
| 7813 | } | 7472 | } |