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) !
239239
240240 if (fmt.stats) |stats| {
241241 if (stats.files > 1) {
242 try stats.root_struct.field("files", stats.files, .{});
243 try stats.root_struct.field("tokens", stats.tokens, .{});
244 try stats.root_struct.field("nodes", stats.nodes, .{});
242 var agg_struct = try stats.root_struct.beginStructField("aggregate", .{});
243 try agg_struct.field("file_count", stats.files, .{});
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();
245280 }
246281 try stats.root_struct.end();
282 try fmt.stdout_writer.interface.writeByte('\n');
247283 }
248284
249285 try fmt.stdout_writer.flush();
......@@ -413,19 +449,6 @@ fn fmtPathFile(
413449 node_stats[@backingInt(tag)] += 1;
414450 }
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
429452 {
430453 for (&token_order, 0..) |*elem, i| elem.* = i;
431454 std.mem.sortContext(0, token_names.len, @as(SortContext, .{
......@@ -435,7 +458,7 @@ fn fmtPathFile(
435458 var s = try zon_struct.beginStructField("tokens", .{});
436459 for (&token_order) |i| {
437460 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, .{});
439462 }
440463 try s.end();
441464 }
......@@ -449,13 +472,14 @@ fn fmtPathFile(
449472 var s = try zon_struct.beginStructField("nodes", .{});
450473 for (&node_order) |i| {
451474 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, .{});
453476 }
454477 try s.end();
455478 }
456479
457480 stats.tokens += tree.tokens.len;
458481 stats.nodes += tree.nodes.len;
482 stats.files += 1;
459483 }
460484
461485 // As a heuristic, we make enough capacity for the same as the input source.
......@@ -485,6 +509,19 @@ fn fmtPathFile(
485509 if (fmt.stats != null) try zon_struct.end();
486510}
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
488525/// Provided for debugging/testing purposes; unused by the compiler.
489526pub fn main(init: process.Init) !void {
490527 const args = try init.minimal.args.toSlice(init.arena.allocator());