authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-08 14:02:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-08 17:34:29-07:00
loge51bf822dd0a79bc946f956f0fcb7a7f9abde389
treefe92458caa31065322644323fa1a582ce6cccf41
parent2f2224c19a5328de4cdc962192e763f6301bfd72

zig fmt: add aggregate stats


1 files changed, 55 insertions(+), 18 deletions(-)

src/fmt.zig+55-18
...@@ -239,11 +239,47 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !...@@ -239,11 +239,47 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) !
239239
240 if (fmt.stats) |stats| {240 if (fmt.stats) |stats| {
241 if (stats.files > 1) {241 if (stats.files > 1) {
242 try stats.root_struct.field("files", stats.files, .{});242 var agg_struct = try stats.root_struct.beginStructField("aggregate", .{});
243 try stats.root_struct.field("tokens", stats.tokens, .{});243 try agg_struct.field("file_count", stats.files, .{});
244 try stats.root_struct.field("nodes", stats.nodes, .{});244 try agg_struct.field("token_count", stats.tokens, .{});
245 try agg_struct.field("node_count", stats.nodes, .{});
246
247 const token_names = @typeInfo(std.zig.Token.Tag).@"enum".field_names;
248 const node_names = @typeInfo(std.zig.Ast.Node.Tag).@"enum".field_names;
249
250 var token_order: [token_names.len]usize = undefined;
251 var node_order: [node_names.len]usize = undefined;
252 {
253 for (&token_order, 0..) |*elem, i| elem.* = i;
254 std.mem.sortContext(0, token_names.len, @as(SortContext, .{
255 .stats = stats.token_stats,
256 .order = &token_order,
257 }));
258 var tokens_struct = try agg_struct.beginStructField("tokens", .{});
259 for (&token_order) |i| {
260 const n = stats.token_stats[i];
261 if (n != 0) try tokens_struct.field(token_names[i], n, .{});
262 }
263 try tokens_struct.end();
264 }
265 {
266 for (&node_order, 0..) |*elem, i| elem.* = i;
267 std.mem.sortContext(0, node_names.len, @as(SortContext, .{
268 .stats = stats.node_stats,
269 .order = &node_order,
270 }));
271 var nodes_struct = try agg_struct.beginStructField("nodes", .{});
272 for (&node_order) |i| {
273 const n = stats.node_stats[i];
274 if (n != 0) try nodes_struct.field(node_names[i], n, .{});
275 }
276 try nodes_struct.end();
277 }
278
279 try agg_struct.end();
245 }280 }
246 try stats.root_struct.end();281 try stats.root_struct.end();
282 try fmt.stdout_writer.interface.writeByte('\n');
247 }283 }
248284
249 try fmt.stdout_writer.flush();285 try fmt.stdout_writer.flush();
...@@ -413,19 +449,6 @@ fn fmtPathFile(...@@ -413,19 +449,6 @@ fn fmtPathFile(
413 node_stats[@backingInt(tag)] += 1;449 node_stats[@backingInt(tag)] += 1;
414 }450 }
415451
416 const SortContext = struct {
417 stats: []const u64,
418 order: []usize,
419
420 pub fn lessThan(this: @This(), a_index: usize, b_index: usize) bool {
421 return this.stats[this.order[b_index]] < this.stats[this.order[a_index]];
422 }
423
424 pub fn swap(this: @This(), a_index: usize, b_index: usize) void {
425 std.mem.swap(usize, &this.order[a_index], &this.order[b_index]);
426 }
427 };
428
429 {452 {
430 for (&token_order, 0..) |*elem, i| elem.* = i;453 for (&token_order, 0..) |*elem, i| elem.* = i;
431 std.mem.sortContext(0, token_names.len, @as(SortContext, .{454 std.mem.sortContext(0, token_names.len, @as(SortContext, .{
...@@ -435,7 +458,7 @@ fn fmtPathFile(...@@ -435,7 +458,7 @@ fn fmtPathFile(
435 var s = try zon_struct.beginStructField("tokens", .{});458 var s = try zon_struct.beginStructField("tokens", .{});
436 for (&token_order) |i| {459 for (&token_order) |i| {
437 const n = token_stats[i];460 const n = token_stats[i];
438 if (n != 0) try zon_struct.field(token_names[i], n, .{});461 if (n != 0) try s.field(token_names[i], n, .{});
439 }462 }
440 try s.end();463 try s.end();
441 }464 }
...@@ -449,13 +472,14 @@ fn fmtPathFile(...@@ -449,13 +472,14 @@ fn fmtPathFile(
449 var s = try zon_struct.beginStructField("nodes", .{});472 var s = try zon_struct.beginStructField("nodes", .{});
450 for (&node_order) |i| {473 for (&node_order) |i| {
451 const n = node_stats[i];474 const n = node_stats[i];
452 if (n != 0) try zon_struct.field(node_names[i], n, .{});475 if (n != 0) try s.field(node_names[i], n, .{});
453 }476 }
454 try s.end();477 try s.end();
455 }478 }
456479
457 stats.tokens += tree.tokens.len;480 stats.tokens += tree.tokens.len;
458 stats.nodes += tree.nodes.len;481 stats.nodes += tree.nodes.len;
482 stats.files += 1;
459 }483 }
460484
461 // As a heuristic, we make enough capacity for the same as the input source.485 // As a heuristic, we make enough capacity for the same as the input source.
...@@ -485,6 +509,19 @@ fn fmtPathFile(...@@ -485,6 +509,19 @@ fn fmtPathFile(
485 if (fmt.stats != null) try zon_struct.end();509 if (fmt.stats != null) try zon_struct.end();
486}510}
487511
512const SortContext = struct {
513 stats: []const u64,
514 order: []usize,
515
516 pub fn lessThan(this: @This(), a_index: usize, b_index: usize) bool {
517 return this.stats[this.order[b_index]] < this.stats[this.order[a_index]];
518 }
519
520 pub fn swap(this: @This(), a_index: usize, b_index: usize) void {
521 std.mem.swap(usize, &this.order[a_index], &this.order[b_index]);
522 }
523};
524
488/// Provided for debugging/testing purposes; unused by the compiler.525/// Provided for debugging/testing purposes; unused by the compiler.
489pub fn main(init: process.Init) !void {526pub fn main(init: process.Init) !void {
490 const args = try init.minimal.args.toSlice(init.arena.allocator());527 const args = try init.minimal.args.toSlice(init.arena.allocator());