| ... | ... | @@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{ |
| 700 | 700 | }), |
| 701 | 701 | }; |
| 702 | 702 | |
| 703 | const Fmt = struct { |
| 704 | seen: std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8), |
| 705 | queue: std.LinkedList([]const u8), |
| 706 | any_error: bool, |
| 707 | |
| 708 | // file_path must outlive Fmt |
| 709 | fn addToQueue(self: *Fmt, file_path: []const u8) !void { |
| 710 | const new_node = try self.seen.allocator.construct(std.LinkedList([]const u8).Node{ |
| 711 | .prev = undefined, |
| 712 | .next = undefined, |
| 713 | .data = file_path, |
| 714 | }); |
| 715 | |
| 716 | if (try self.seen.put(file_path, {})) |_| return; |
| 717 | |
| 718 | self.queue.append(new_node); |
| 719 | } |
| 720 | |
| 721 | fn addDirToQueue(self: *Fmt, file_path: []const u8) !void { |
| 722 | var dir = try std.os.Dir.open(self.seen.allocator, file_path); |
| 723 | defer dir.close(); |
| 724 | while (try dir.next()) |entry| { |
| 725 | if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { |
| 726 | const full_path = try os.path.join(self.seen.allocator, file_path, entry.name); |
| 727 | try self.addToQueue(full_path); |
| 728 | } |
| 729 | } |
| 730 | } |
| 731 | }; |
| 732 | |
| 703 | 733 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 704 | 734 | var flags = try Args.parse(allocator, args_fmt_spec, args); |
| 705 | 735 | defer flags.deinit(); |
| ... | ... | @@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 728 | 758 | } |
| 729 | 759 | }; |
| 730 | 760 | |
| 731 | | var fmt_errors = false; |
| 761 | var fmt = Fmt{ |
| 762 | .seen = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator), |
| 763 | .queue = std.LinkedList([]const u8).init(), |
| 764 | .any_error = false, |
| 765 | }; |
| 766 | |
| 732 | 767 | for (flags.positionals.toSliceConst()) |file_path| { |
| 768 | try fmt.addToQueue(file_path); |
| 769 | } |
| 770 | |
| 771 | while (fmt.queue.popFirst()) |node| { |
| 772 | const file_path = node.data; |
| 773 | |
| 733 | 774 | var file = try os.File.openRead(allocator, file_path); |
| 734 | 775 | defer file.close(); |
| 735 | 776 | |
| 736 | | const source_code = io.readFileAlloc(allocator, file_path) catch |err| { |
| 737 | | try stderr.print("unable to open '{}': {}\n", file_path, err); |
| 738 | | fmt_errors = true; |
| 739 | | continue; |
| 777 | const source_code = io.readFileAlloc(allocator, file_path) catch |err| switch (err) { |
| 778 | error.IsDir => { |
| 779 | try fmt.addDirToQueue(file_path); |
| 780 | continue; |
| 781 | }, |
| 782 | else => { |
| 783 | try stderr.print("unable to open '{}': {}\n", file_path, err); |
| 784 | fmt.any_error = true; |
| 785 | continue; |
| 786 | }, |
| 740 | 787 | }; |
| 741 | 788 | defer allocator.free(source_code); |
| 742 | 789 | |
| 743 | 790 | var tree = std.zig.parse(allocator, source_code) catch |err| { |
| 744 | 791 | try stderr.print("error parsing file '{}': {}\n", file_path, err); |
| 745 | | fmt_errors = true; |
| 792 | fmt.any_error = true; |
| 746 | 793 | continue; |
| 747 | 794 | }; |
| 748 | 795 | defer tree.deinit(); |
| ... | ... | @@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 755 | 802 | try errmsg.printToFile(&stderr_file, msg, color); |
| 756 | 803 | } |
| 757 | 804 | if (tree.errors.len != 0) { |
| 758 | | fmt_errors = true; |
| 805 | fmt.any_error = true; |
| 759 | 806 | continue; |
| 760 | 807 | } |
| 761 | 808 | |
| ... | ... | @@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 769 | 816 | } |
| 770 | 817 | } |
| 771 | 818 | |
| 772 | | if (fmt_errors) { |
| 819 | if (fmt.any_error) { |
| 773 | 820 | os.exit(1); |
| 774 | 821 | } |
| 775 | 822 | } |