authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-11-14 19:50:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-11-15 00:26:43-05:00
log0c3bd0c3d16eb8c38593254ae54ef7fd22d8fa41
tree7609fdfb03f2380692258697fafc1b4e99d33132
parent65cddc5a1955303481252768b72c2f68200be359
signature Commit is signed but in an unrecognized format.

zig fmt: add --check flag

closes #1558 closes #1555

4 files changed, 49 insertions(+), 22 deletions(-)

src-self-hosted/arg.zig+1-1
...@@ -149,7 +149,7 @@ pub const Args = struct {...@@ -149,7 +149,7 @@ pub const Args = struct {
149 }149 }
150150
151 // e.g. --help151 // e.g. --help
152 pub fn present(self: *Args, name: []const u8) bool {152 pub fn present(self: *const Args, name: []const u8) bool {
153 return self.flags.contains(name);153 return self.flags.contains(name);
154 }154 }
155155
src-self-hosted/main.zig+32-12
...@@ -514,17 +514,22 @@ const usage_fmt =...@@ -514,17 +514,22 @@ const usage_fmt =
514 \\usage: zig fmt [file]...514 \\usage: zig fmt [file]...
515 \\515 \\
516 \\ Formats the input files and modifies them in-place.516 \\ Formats the input files and modifies them in-place.
517 \\ Arguments can be files or directories, which are searched
518 \\ recursively.
517 \\519 \\
518 \\Options:520 \\Options:
519 \\ --help Print this help and exit521 \\ --help Print this help and exit
520 \\ --color [auto|off|on] Enable or disable colored error messages522 \\ --color [auto|off|on] Enable or disable colored error messages
521 \\ --stdin Format code from stdin523 \\ --stdin Format code from stdin; output to stdout
524 \\ --check List non-conforming files and exit with an error
525 \\ if the list is non-empty
522 \\526 \\
523 \\527 \\
524;528;
525529
526const args_fmt_spec = []Flag{530const args_fmt_spec = []Flag{
527 Flag.Bool("--help"),531 Flag.Bool("--help"),
532 Flag.Bool("--check"),
528 Flag.Option("--color", []const []const u8{533 Flag.Option("--color", []const []const u8{
529 "auto",534 "auto",
530 "off",535 "off",
...@@ -640,6 +645,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -640,6 +645,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
640 if (tree.errors.len != 0) {645 if (tree.errors.len != 0) {
641 os.exit(1);646 os.exit(1);
642 }647 }
648 if (flags.present("check")) {
649 const anything_changed = try std.zig.render(allocator, io.noop_out_stream, &tree);
650 const code = if (anything_changed) u8(1) else u8(0);
651 os.exit(code);
652 }
643653
644 _ = try std.zig.render(allocator, stdout, &tree);654 _ = try std.zig.render(allocator, stdout, &tree);
645 return;655 return;
...@@ -711,9 +721,11 @@ async fn asyncFmtMain(...@@ -711,9 +721,11 @@ async fn asyncFmtMain(
711 .loop = loop,721 .loop = loop,
712 };722 };
713723
724 const check_mode = flags.present("check");
725
714 var group = event.Group(FmtError!void).init(loop);726 var group = event.Group(FmtError!void).init(loop);
715 for (flags.positionals.toSliceConst()) |file_path| {727 for (flags.positionals.toSliceConst()) |file_path| {
716 try group.call(fmtPath, &fmt, file_path);728 try group.call(fmtPath, &fmt, file_path, check_mode);
717 }729 }
718 try await (async group.wait() catch unreachable);730 try await (async group.wait() catch unreachable);
719 if (fmt.any_error) {731 if (fmt.any_error) {
...@@ -721,7 +733,7 @@ async fn asyncFmtMain(...@@ -721,7 +733,7 @@ async fn asyncFmtMain(
721 }733 }
722}734}
723735
724async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {736async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
725 const file_path = try std.mem.dupe(fmt.loop.allocator, u8, file_path_ref);737 const file_path = try std.mem.dupe(fmt.loop.allocator, u8, file_path_ref);
726 defer fmt.loop.allocator.free(file_path);738 defer fmt.loop.allocator.free(file_path);
727739
...@@ -746,7 +758,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {...@@ -746,7 +758,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {
746 while (try dir.next()) |entry| {758 while (try dir.next()) |entry| {
747 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {759 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
748 const full_path = try os.path.join(fmt.loop.allocator, file_path, entry.name);760 const full_path = try os.path.join(fmt.loop.allocator, file_path, entry.name);
749 try group.call(fmtPath, fmt, full_path);761 try group.call(fmtPath, fmt, full_path, check_mode);
750 }762 }
751 }763 }
752 return await (async group.wait() catch unreachable);764 return await (async group.wait() catch unreachable);
...@@ -779,14 +791,22 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {...@@ -779,14 +791,22 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {
779 return;791 return;
780 }792 }
781793
782 // TODO make this evented794 if (check_mode) {
783 const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);795 const anything_changed = try std.zig.render(fmt.loop.allocator, io.noop_out_stream, &tree);
784 defer baf.destroy();796 if (anything_changed) {
785797 try stderr.print("{}\n", file_path);
786 const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), &tree);798 fmt.any_error = true;
787 if (anything_changed) {799 }
788 try stderr.print("{}\n", file_path);800 } else {
789 try baf.finish();801 // TODO make this evented
802 const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);
803 defer baf.destroy();
804
805 const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), &tree);
806 if (anything_changed) {
807 try stderr.print("{}\n", file_path);
808 try baf.finish();
809 }
790 }810 }
791}811}
792812
std/io.zig+15-8
...@@ -203,20 +203,20 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -203,20 +203,20 @@ pub fn OutStream(comptime WriteError: type) type {
203203
204 writeFn: fn (self: *Self, bytes: []const u8) Error!void,204 writeFn: fn (self: *Self, bytes: []const u8) Error!void,
205205
206 pub fn print(self: *Self, comptime format: []const u8, args: ...) !void {206 pub fn print(self: *Self, comptime format: []const u8, args: ...) Error!void {
207 return std.fmt.format(self, Error, self.writeFn, format, args);207 return std.fmt.format(self, Error, self.writeFn, format, args);
208 }208 }
209209
210 pub fn write(self: *Self, bytes: []const u8) !void {210 pub fn write(self: *Self, bytes: []const u8) Error!void {
211 return self.writeFn(self, bytes);211 return self.writeFn(self, bytes);
212 }212 }
213213
214 pub fn writeByte(self: *Self, byte: u8) !void {214 pub fn writeByte(self: *Self, byte: u8) Error!void {
215 const slice = (*[1]u8)(&byte)[0..];215 const slice = (*[1]u8)(&byte)[0..];
216 return self.writeFn(self, slice);216 return self.writeFn(self, slice);
217 }217 }
218218
219 pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) !void {219 pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
220 const slice = (*[1]u8)(&byte)[0..];220 const slice = (*[1]u8)(&byte)[0..];
221 var i: usize = 0;221 var i: usize = 0;
222 while (i < n) : (i += 1) {222 while (i < n) : (i += 1) {
...@@ -225,23 +225,23 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -225,23 +225,23 @@ pub fn OutStream(comptime WriteError: type) type {
225 }225 }
226226
227 /// Write a native-endian integer.227 /// Write a native-endian integer.
228 pub fn writeIntNe(self: *Self, comptime T: type, value: T) !void {228 pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
229 return self.writeInt(builtin.endian, T, value);229 return self.writeInt(builtin.endian, T, value);
230 }230 }
231231
232 pub fn writeIntLe(self: *Self, comptime T: type, value: T) !void {232 pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {
233 var bytes: [@sizeOf(T)]u8 = undefined;233 var bytes: [@sizeOf(T)]u8 = undefined;
234 mem.writeIntLE(T, &bytes, value);234 mem.writeIntLE(T, &bytes, value);
235 return self.writeFn(self, bytes);235 return self.writeFn(self, bytes);
236 }236 }
237237
238 pub fn writeIntBe(self: *Self, comptime T: type, value: T) !void {238 pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {
239 var bytes: [@sizeOf(T)]u8 = undefined;239 var bytes: [@sizeOf(T)]u8 = undefined;
240 mem.writeIntBE(T, &bytes, value);240 mem.writeIntBE(T, &bytes, value);
241 return self.writeFn(self, bytes);241 return self.writeFn(self, bytes);
242 }242 }
243243
244 pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) !void {244 pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {
245 var bytes: [@sizeOf(T)]u8 = undefined;245 var bytes: [@sizeOf(T)]u8 = undefined;
246 mem.writeInt(bytes[0..], value, endian);246 mem.writeInt(bytes[0..], value, endian);
247 return self.writeFn(self, bytes);247 return self.writeFn(self, bytes);
...@@ -249,6 +249,13 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -249,6 +249,13 @@ pub fn OutStream(comptime WriteError: type) type {
249 };249 };
250}250}
251251
252pub const noop_out_stream = &noop_out_stream_state;
253const NoopOutStreamError = error{};
254var noop_out_stream_state = OutStream(NoopOutStreamError){
255 .writeFn = noop_out_stream_write,
256};
257fn noop_out_stream_write(self: *OutStream(NoopOutStreamError), bytes: []const u8) error{}!void {}
258
252pub fn writeFile(path: []const u8, data: []const u8) !void {259pub fn writeFile(path: []const u8, data: []const u8) !void {
253 var file = try File.openWrite(path);260 var file = try File.openWrite(path);
254 defer file.close();261 defer file.close();
std/zig/render.zig+1-1
...@@ -133,7 +133,7 @@ fn renderRoot(...@@ -133,7 +133,7 @@ fn renderRoot(
133 }133 }
134}134}
135135
136fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) !void {136fn renderExtraNewline(tree: *ast.Tree, stream: var, start_col: *usize, node: *ast.Node) @typeOf(stream).Child.Error!void {
137 const first_token = node.firstToken();137 const first_token = node.firstToken();
138 var prev_token = first_token;138 var prev_token = first_token;
139 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {139 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {