authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-06-09 21:20:25+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:12-07:00
logdd4bd55ef6891109f3a462369a3430d11d5db4ee
tree58e1a95a870307c9f52956568309b557f556cc05
parent45e3b1a23df6f0f0174b277194b5301662d7c256

autodoc: rework json printing code

We're now using `std.json.writeStream`, which makes our prints correct in terms of escapes and also reduces the amount of json-related code. Unfortunately, we have to mess around with the json stream writer state whenever we end up using `std.json.stringify` for convenience.

1 files changed, 137 insertions(+), 403 deletions(-)

src/Autodoc.zig+137-403
...@@ -178,9 +178,9 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -178,9 +178,9 @@ pub fn generateZirData(self: *Autodoc) !void {
178 try self.packages.put(self.arena, self.module.main_pkg, .{178 try self.packages.put(self.arena, self.module.main_pkg, .{
179 .name = "root",179 .name = "root",
180 .main = main_type_index,180 .main = main_type_index,
181 .table = .{ .data = std.StringHashMapUnmanaged(usize){} },181 .table = std.StringHashMapUnmanaged(usize){},
182 });182 });
183 try self.packages.entries.items(.value)[0].table.data.put(self.arena, "root", 0);183 try self.packages.entries.items(.value)[0].table.put(self.arena, "root", 0);
184 }184 }
185185
186 var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index };186 var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index };
...@@ -208,7 +208,7 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -208,7 +208,7 @@ pub fn generateZirData(self: *Autodoc) !void {
208 .rootPkgName = rootName,208 .rootPkgName = rootName,
209 .params = .{ .rootName = "root" },209 .params = .{ .rootName = "root" },
210 .packages = self.packages.values(),210 .packages = self.packages.values(),
211 .files = .{ .data = self.files },211 .files = self.files,
212 .calls = self.calls.items,212 .calls = self.calls.items,
213 .types = self.types.items,213 .types = self.types.items,
214 .decls = self.decls.items,214 .decls = self.decls.items,
...@@ -313,49 +313,7 @@ const DocData = struct {...@@ -313,49 +313,7 @@ const DocData = struct {
313 // non-hardcoded stuff313 // non-hardcoded stuff
314 astNodes: []AstNode,314 astNodes: []AstNode,
315 calls: []Call,315 calls: []Call,
316 files: struct {316 files: std.AutoArrayHashMapUnmanaged(*File, usize),
317 // this struct is a temporary hack to support json serialization
318 data: std.AutoArrayHashMapUnmanaged(*File, usize),
319 pub fn jsonStringify(
320 self: @This(),
321 opt: std.json.StringifyOptions,
322 w: anytype,
323 ) !void {
324 var idx: usize = 0;
325 var it = self.data.iterator();
326 try w.writeAll("{\n");
327
328 var options = opt;
329 if (options.whitespace) |*ws| ws.indent_level += 1;
330 while (it.next()) |kv| : (idx += 1) {
331 if (options.whitespace) |ws| try ws.outputIndent(w);
332 const builtin = @import("builtin");
333 if (builtin.target.os.tag == .windows) {
334 try w.print("\"", .{});
335 for (kv.key_ptr.*.sub_file_path) |c| {
336 if (c == '\\') {
337 try w.print("\\\\", .{});
338 } else {
339 try w.print("{c}", .{c});
340 }
341 }
342 try w.print("\"", .{});
343 try w.print(": {d}", .{
344 kv.value_ptr.*,
345 });
346 } else {
347 try w.print("\"{s}\": {d}", .{
348 kv.key_ptr.*.sub_file_path,
349 kv.value_ptr.*,
350 });
351 }
352 if (idx != self.data.count() - 1) try w.writeByte(',');
353 try w.writeByte('\n');
354 }
355 if (opt.whitespace) |ws| try ws.outputIndent(w);
356 try w.writeAll("}");
357 }
358 },
359 types: []Type,317 types: []Type,
360 decls: []Decl,318 decls: []Decl,
361 exprs: []Expr,319 exprs: []Expr,
...@@ -366,6 +324,26 @@ const DocData = struct {...@@ -366,6 +324,26 @@ const DocData = struct {
366 ret: Expr,324 ret: Expr,
367 };325 };
368326
327 pub fn jsonStringify(
328 self: DocData,
329 opts: std.json.StringifyOptions,
330 w: anytype,
331 ) !void {
332 var jsw = std.json.writeStream(w, 15);
333 try jsw.beginObject();
334 inline for (comptime std.meta.tags(std.meta.FieldEnum(DocData))) |f| {
335 const f_name = @tagName(f);
336 try jsw.objectField(f_name);
337 switch (f) {
338 .files => try writeFileTableToJson(self.files, &jsw),
339 else => {
340 try std.json.stringify(@field(self, f_name), opts, w);
341 jsw.state_index -= 1;
342 },
343 }
344 }
345 try jsw.endObject();
346 }
369 /// All the type "families" as described by `std.builtin.TypeId`347 /// All the type "families" as described by `std.builtin.TypeId`
370 /// plus a couple extra that are unique to our use case.348 /// plus a couple extra that are unique to our use case.
371 ///349 ///
...@@ -399,49 +377,28 @@ const DocData = struct {...@@ -399,49 +377,28 @@ const DocData = struct {
399 name: []const u8 = "(root)",377 name: []const u8 = "(root)",
400 file: usize = 0, // index into `files`378 file: usize = 0, // index into `files`
401 main: usize = 0, // index into `types`379 main: usize = 0, // index into `types`
402 table: struct {380 table: std.StringHashMapUnmanaged(usize),
403 // this struct is a temporary hack to support json serialization381
404 data: std.StringHashMapUnmanaged(usize),382 pub fn jsonStringify(
405 pub fn jsonStringify(383 self: DocPackage,
406 self: @This(),384 opts: std.json.StringifyOptions,
407 opt: std.json.StringifyOptions,385 w: anytype,
408 w: anytype,386 ) !void {
409 ) !void {387 var jsw = std.json.writeStream(w, 15);
410 var idx: usize = 0;388 try jsw.beginObject();
411 var it = self.data.iterator();389 inline for (comptime std.meta.tags(std.meta.FieldEnum(DocPackage))) |f| {
412 try w.writeAll("{\n");390 const f_name = @tagName(f);
413391 try jsw.objectField(f_name);
414 var options = opt;392 switch (f) {
415 if (options.whitespace) |*ws| ws.indent_level += 1;393 .table => try writePackageTableToJson(self.table, &jsw),
416 while (it.next()) |kv| : (idx += 1) {394 else => {
417 if (options.whitespace) |ws| try ws.outputIndent(w);395 try std.json.stringify(@field(self, f_name), opts, w);
418 const builtin = @import("builtin");396 jsw.state_index -= 1;
419 if (builtin.target.os.tag == .windows) {397 },
420 try w.print("\"", .{});
421 for (kv.key_ptr.*) |c| {
422 if (c == '\\') {
423 try w.print("\\\\", .{});
424 } else {
425 try w.print("{c}", .{c});
426 }
427 }
428 try w.print("\"", .{});
429 try w.print(": {d}", .{
430 kv.value_ptr.*,
431 });
432 } else {
433 try w.print("\"{s}\": {d}", .{
434 kv.key_ptr.*,
435 kv.value_ptr.*,
436 });
437 }
438 if (idx != self.data.count() - 1) try w.writeByte(',');
439 try w.writeByte('\n');
440 }398 }
441 if (opt.whitespace) |ws| try ws.outputIndent(w);
442 try w.writeAll("}");
443 }399 }
444 },400 try jsw.endObject();
401 }
445 };402 };
446403
447 const Decl = struct {404 const Decl = struct {
...@@ -466,7 +423,7 @@ const DocData = struct {...@@ -466,7 +423,7 @@ const DocData = struct {
466 };423 };
467424
468 const Type = union(DocTypeKinds) {425 const Type = union(DocTypeKinds) {
469 Unanalyzed: void,426 Unanalyzed: struct {},
470 Type: struct { name: []const u8 },427 Type: struct { name: []const u8 },
471 Void: struct { name: []const u8 },428 Void: struct { name: []const u8 },
472 Bool: struct { name: []const u8 },429 Bool: struct { name: []const u8 },
...@@ -568,130 +525,29 @@ const DocData = struct {...@@ -568,130 +525,29 @@ const DocData = struct {
568525
569 pub fn jsonStringify(526 pub fn jsonStringify(
570 self: Type,527 self: Type,
571 opt: std.json.StringifyOptions,528 opts: std.json.StringifyOptions,
572 w: anytype,529 w: anytype,
573 ) !void {530 ) !void {
574 try w.print(531 const active_tag = std.meta.activeTag(self);
575 \\{{ "kind": {},532 var jsw = std.json.writeStream(w, 15);
576 \\533 try jsw.beginObject();
577 , .{@enumToInt(std.meta.activeTag(self))});534 try jsw.objectField("kind");
578 var options = opt;535 try jsw.emitNumber(@enumToInt(active_tag));
579 if (options.whitespace) |*ws| ws.indent_level += 1;536 inline for (comptime std.meta.fields(Type)) |case| {
580 switch (self) {537 if (@field(Type, case.name) == active_tag) {
581 .Array => |v| try printTypeBody(v, options, w),538 const current_value = @field(self, case.name);
582 .Bool => |v| try printTypeBody(v, options, w),539 inline for (comptime std.meta.fields(case.field_type)) |f| {
583 .Void => |v| try printTypeBody(v, options, w),540 try jsw.objectField(f.name);
584 .ComptimeExpr => |v| try printTypeBody(v, options, w),541 if (f.field_type == std.builtin.TypeInfo.Pointer.Size) {
585 .ComptimeInt => |v| try printTypeBody(v, options, w),542 try jsw.emitNumber(@enumToInt(@field(current_value, f.name)));
586 .ComptimeFloat => |v| try printTypeBody(v, options, w),543 } else {
587 .Null => |v| try printTypeBody(v, options, w),544 try std.json.stringify(@field(current_value, f.name), opts, w);
588 .Optional => |v| try printTypeBody(v, options, w),545 jsw.state_index -= 1;
589 .Struct => |v| try printTypeBody(v, options, w),546 }
590 .Fn => |v| try printTypeBody(v, options, w),
591 .Union => |v| try printTypeBody(v, options, w),
592 .ErrorSet => |v| try printTypeBody(v, options, w),
593 .ErrorUnion => |v| try printTypeBody(v, options, w),
594 .Enum => |v| try printTypeBody(v, options, w),
595 .Int => |v| try printTypeBody(v, options, w),
596 .Float => |v| try printTypeBody(v, options, w),
597 .Type => |v| try printTypeBody(v, options, w),
598 .NoReturn => |v| try printTypeBody(v, options, w),
599 .EnumLiteral => |v| try printTypeBody(v, options, w),
600 .Pointer => |v| {
601 if (options.whitespace) |ws| try ws.outputIndent(w);
602 try w.print(
603 \\"size": {},
604 \\
605 , .{@enumToInt(v.size)});
606 if (options.whitespace) |ws| try ws.outputIndent(w);
607 if (v.sentinel) |sentinel| {
608 try w.print(
609 \\"sentinel":
610 , .{});
611 if (options.whitespace) |*ws| ws.indent_level += 1;
612 try sentinel.jsonStringify(options, w);
613 try w.print(",", .{});
614 }
615 if (v.@"align") |@"align"| {
616 try w.print(
617 \\"align":
618 , .{});
619 if (options.whitespace) |*ws| ws.indent_level += 1;
620 try @"align".jsonStringify(options, w);
621 try w.print(",", .{});
622 }
623 if (v.address_space) |address_space| {
624 try w.print(
625 \\"address_space":
626 , .{});
627 if (options.whitespace) |*ws| ws.indent_level += 1;
628 try address_space.jsonStringify(options, w);
629 try w.print(",", .{});
630 }
631 if (v.bit_start) |bit_start| {
632 try w.print(
633 \\"bit_start":
634 , .{});
635 if (options.whitespace) |*ws| ws.indent_level += 1;
636 try bit_start.jsonStringify(options, w);
637 try w.print(",", .{});
638 }
639 if (v.host_size) |host_size| {
640 try w.print(
641 \\"host_size":
642 , .{});
643 if (options.whitespace) |*ws| ws.indent_level += 1;
644 try host_size.jsonStringify(options, w);
645 try w.print(",", .{});
646 }547 }
647 if (options.whitespace) |ws| try ws.outputIndent(w);548 }
648 try w.print(
649 \\"is_allowzero": {},
650 \\"is_mutable": {},
651 \\"is_volatile": {},
652 \\"has_sentinel": {},
653 \\"has_align": {},
654 \\"has_addrspace": {},
655 \\"has_bit_range": {},
656 \\"is_ref": {},
657 \\
658 , .{ v.is_allowzero, v.is_mutable, v.is_volatile, v.has_sentinel, v.has_align, v.has_addrspace, v.has_bit_range, v.is_ref });
659 if (options.whitespace) |ws| try ws.outputIndent(w);
660 try w.print(
661 \\"child":
662 , .{});
663
664 if (options.whitespace) |*ws| ws.indent_level += 1;
665 try v.child.jsonStringify(options, w);
666 },
667 else => {
668 std.debug.print(
669 "TODO: add {s} to `DocData.Type.jsonStringify`\n",
670 .{@tagName(self)},
671 );
672 },
673 }
674 try w.print("}}", .{});
675 }
676
677 fn printTypeBody(
678 body: anytype,
679 options: std.json.StringifyOptions,
680 w: anytype,
681 ) !void {
682 const fields = std.meta.fields(@TypeOf(body));
683 inline for (fields) |f, idx| {
684 if (options.whitespace) |ws| try ws.outputIndent(w);
685 try w.print("\"{s}\": ", .{f.name});
686 try std.json.stringify(@field(body, f.name), options, w);
687 if (idx != fields.len - 1) try w.writeByte(',');
688 try w.writeByte('\n');
689 }
690 if (options.whitespace) |ws| {
691 var up = ws;
692 up.indent_level -= 1;
693 try up.outputIndent(w);
694 }549 }
550 try jsw.endObject();
695 }551 }
696 };552 };
697553
...@@ -700,13 +556,13 @@ const DocData = struct {...@@ -700,13 +556,13 @@ const DocData = struct {
700 /// type definition will hold an index into `self.types`.556 /// type definition will hold an index into `self.types`.
701 pub const Expr = union(enum) {557 pub const Expr = union(enum) {
702 comptimeExpr: usize, // index in `comptimeExprs`558 comptimeExpr: usize, // index in `comptimeExprs`
703 void,559 void: struct {},
704 @"unreachable",560 @"unreachable": struct {},
705 @"null",561 @"null": struct {},
706 @"undefined",562 @"undefined": struct {},
707 @"struct": []FieldVal,563 @"struct": []FieldVal,
708 bool: bool,564 bool: bool,
709 @"anytype",565 @"anytype": struct {},
710 type: usize, // index in `types`566 type: usize, // index in `types`
711 this: usize, // index in `types`567 this: usize, // index in `types`
712 declRef: usize, // index in `decls`568 declRef: usize, // index in `decls`
...@@ -791,184 +647,40 @@ const DocData = struct {...@@ -791,184 +647,40 @@ const DocData = struct {
791647
792 pub fn jsonStringify(648 pub fn jsonStringify(
793 self: Expr,649 self: Expr,
794 options: std.json.StringifyOptions,650 opt: std.json.StringifyOptions,
795 w: anytype,651 w: anytype,
796 ) std.os.WriteError!void {652 ) !void {
797 switch (self) {653 const active_tag = std.meta.activeTag(self);
798 .void, .@"unreachable", .@"anytype", .@"null", .@"undefined" => {654 var jsw = std.json.writeStream(w, 15);
799 try w.print(655 try jsw.beginObject();
800 \\{{ "{s}":{{}} }}656 try jsw.objectField(@tagName(active_tag));
801 , .{@tagName(self)});657 inline for (comptime std.meta.fields(Expr)) |case| {
802 },658 if (@field(Expr, case.name) == active_tag) {
803 .type, .comptimeExpr, .call, .this, .declRef, .typeOf, .errorUnion, .errorSets, .alignOf => |v| {659 switch (active_tag) {
804 try w.print(660 .int => {
805 \\{{ "{s}":{} }}661 if (self.int.negated) try w.writeAll("-");
806 , .{ @tagName(self), v });662 try jsw.emitNumber(self.int.value);
807 },663 },
808 .int => |v| {664 .int_big => {
809 const neg = if (v.negated) "-" else "";
810 try w.print(
811 \\{{ "int": {s}{} }}
812 , .{ neg, v.value });
813 },
814 .int_big => |v| {
815 const neg = if (v.negated) "-" else "";
816 try w.print(
817 \\{{ "int_big": {s}{s} }}
818 , .{ neg, v.value });
819 },
820 .float => |v| {
821 try w.print(
822 \\{{ "float": {} }}
823 , .{v});
824 },
825 .float128 => |v| {
826 try w.print(
827 \\{{ "float128": {} }}
828 , .{v});
829 },
830 .bool => |v| {
831 try w.print(
832 \\{{ "bool":{} }}
833 , .{v});
834 },
835 .sizeOf => |v| {
836 try w.print(
837 \\{{ "sizeOf":{} }}
838 , .{v});
839 },
840 .bitSizeOf => |v| {
841 try w.print(
842 \\{{ "bitSizeOf":{} }}
843 , .{v});
844 },
845 .enumToInt => |v| {
846 try w.print(
847 \\{{ "enumToInt":{} }}
848 , .{v});
849 },
850 .fieldRef => |v| try std.json.stringify(
851 struct { fieldRef: FieldRef }{ .fieldRef = v },
852 options,
853 w,
854 ),
855 .as => |v| try std.json.stringify(
856 struct { as: As }{ .as = v },
857 options,
858 w,
859 ),
860 .@"struct" => |v| try std.json.stringify(
861 struct { @"struct": []FieldVal }{ .@"struct" = v },
862 options,
863 w,
864 ),
865 .refPath => |v| {
866 try w.print("{{ \"refPath\": [", .{});
867 for (v) |c, i| {
868 const comma = if (i == v.len - 1) "]}" else ",\n";
869 try c.jsonStringify(options, w);
870 try w.print("{s}", .{comma});
871 }
872 },
873 .switchOp => |v| try std.json.stringify(
874 struct { switchOp: SwitchOp }{ .switchOp = v },
875 options,
876 w,
877 ),
878 .switchIndex => |v| try std.json.stringify(
879 struct { switchIndex: usize }{ .switchIndex = v },
880 options,
881 w,
882 ),
883 .cmpxchg => |v| try std.json.stringify(
884 struct { cmpxchg: Cmpxchg }{ .cmpxchg = v },
885 options,
886 w,
887 ),
888 .cmpxchgIndex => |v| try std.json.stringify(
889 struct { cmpxchgIndex: usize }{ .cmpxchgIndex = v },
890 options,
891 w,
892 ),
893 .binOp => |v| try std.json.stringify(
894 struct { binOp: BinOp }{ .binOp = v },
895 options,
896 w,
897 ),
898 .binOpIndex => |v| try std.json.stringify(
899 struct { binOpIndex: usize }{ .binOpIndex = v },
900 options,
901 w,
902 ),
903 .builtin => |v| try std.json.stringify(
904 struct { builtin: Builtin }{ .builtin = v },
905 options,
906 w,
907 ),
908 .builtinIndex => |v| try std.json.stringify(
909 struct { builtinIndex: usize }{ .builtinIndex = v },
910 options,
911 w,
912 ),
913 .builtinBin => |v| try std.json.stringify(
914 struct { builtinBin: BuiltinBin }{ .builtinBin = v },
915 options,
916 w,
917 ),
918 .builtinBinIndex => |v| try std.json.stringify(
919 struct { builtinBinIndex: usize }{ .builtinBinIndex = v },
920 options,
921 w,
922 ),
923 .slice => |v| try std.json.stringify(
924 struct { slice: Slice }{ .slice = v },
925 options,
926 w,
927 ),
928 .sliceIndex => |v| try std.json.stringify(
929 struct { sliceIndex: usize }{ .sliceIndex = v },
930 options,
931 w,
932 ),
933 .typeOf_peer => |v| try std.json.stringify(
934 struct { typeOf_peer: []usize }{ .typeOf_peer = v },
935 options,
936 w,
937 ),
938 .array => |v| try std.json.stringify(
939 struct { @"array": []usize }{ .@"array" = v },
940 options,
941 w,
942 ),
943 .compileError => |v| try std.json.stringify(
944 struct { compileError: []const u8 }{ .compileError = v },
945 options,
946 w,
947 ),
948 .string => |v| try std.json.stringify(
949 struct { string: []const u8 }{ .string = v },
950 options,
951 w,
952 ),
953 .enumLiteral => |v| try std.json.stringify(
954 struct { @"enumLiteral": []const u8 }{ .@"enumLiteral" = v },
955 options,
956 w,
957 ),
958
959 // try w.print("{ len: {},\n", .{v.len});
960
961 // if (options.whitespace) |ws| try ws.outputIndent(w);
962 // try w.print("typeRef: ", .{});
963 // try v.typeRef.jsonStringify(options, w);
964
965 // try w.print("{{ \"data\": [", .{});
966 // for (v.data) |d, i| {
967 // const comma = if (i == v.len - 1) "]}" else ",";
968 // try w.print("{d}{s}", .{ d, comma });
969 // }
970665
666 //@panic("TODO: json serialization of big ints!");
667 //if (v.negated) try w.writeAll("-");
668 //try jsw.emitNumber(v.value);
669 },
670 else => {
671 try std.json.stringify(@field(self, case.name), opt, w);
672 jsw.state_index -= 1;
673 // TODO: we should not reach into the state of the
674 // json writer, but alas, this is what's
675 // necessary with the current api.
676 // would be nice to have a proper integration
677 // between the json writer and the generic
678 // std.json.stringify implementation
679 },
680 }
681 }
971 }682 }
683 try jsw.endObject();
972 }684 }
973 };685 };
974686
...@@ -1043,7 +755,7 @@ fn walkInstruction(...@@ -1043,7 +755,7 @@ fn walkInstruction(
1043 // that belongs to another package through its file path?755 // that belongs to another package through its file path?
1044 // (ie not through its package name).756 // (ie not through its package name).
1045 // We're bailing for now, but maybe we shouldn't?757 // We're bailing for now, but maybe we shouldn't?
1046 _ = try current_package.table.data.getOrPutValue(758 _ = try current_package.table.getOrPutValue(
1047 self.arena,759 self.arena,
1048 path,760 path,
1049 self.packages.getIndex(other_package).?,761 self.packages.getIndex(other_package).?,
...@@ -1062,9 +774,7 @@ fn walkInstruction(...@@ -1062,9 +774,7 @@ fn walkInstruction(
1062 result.value_ptr.* = .{774 result.value_ptr.* = .{
1063 .name = path,775 .name = path,
1064 .main = main_type_index,776 .main = main_type_index,
1065 .table = .{777 .table = std.StringHashMapUnmanaged(usize){},
1066 .data = std.StringHashMapUnmanaged(usize){},
1067 },
1068 };778 };
1069779
1070 // TODO: Add this package as a dependency to the current pakcage780 // TODO: Add this package as a dependency to the current pakcage
...@@ -2464,7 +2174,7 @@ fn walkInstruction(...@@ -2464,7 +2174,7 @@ fn walkInstruction(
2464 },2174 },
2465 .func, .func_inferred => {2175 .func, .func_inferred => {
2466 const type_slot_index = self.types.items.len;2176 const type_slot_index = self.types.items.len;
2467 try self.types.append(self.arena, .{ .Unanalyzed = {} });2177 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
24682178
2469 const result = self.analyzeFunction(2179 const result = self.analyzeFunction(
2470 file,2180 file,
...@@ -2478,7 +2188,7 @@ fn walkInstruction(...@@ -2478,7 +2188,7 @@ fn walkInstruction(
2478 },2188 },
2479 .func_extended => {2189 .func_extended => {
2480 const type_slot_index = self.types.items.len;2190 const type_slot_index = self.types.items.len;
2481 try self.types.append(self.arena, .{ .Unanalyzed = {} });2191 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
24822192
2483 const result = self.analyzeFunctionExtended(2193 const result = self.analyzeFunctionExtended(
2484 file,2194 file,
...@@ -2546,13 +2256,17 @@ fn walkInstruction(...@@ -2546,13 +2256,17 @@ fn walkInstruction(
2546 if (small.has_lib_name) extra_index += 1;2256 if (small.has_lib_name) extra_index += 1;
2547 if (small.has_align) extra_index += 1;2257 if (small.has_align) extra_index += 1;
25482258
2549 const value: DocData.WalkResult = if (small.has_init) .{ .expr = .{ .void = {} } } else .{ .expr = .{ .void = {} } };2259 const value: DocData.WalkResult = if (small.has_init) .{
2260 .expr = .{ .void = .{} },
2261 } else .{
2262 .expr = .{ .void = .{} },
2263 };
25502264
2551 return value;2265 return value;
2552 },2266 },
2553 .union_decl => {2267 .union_decl => {
2554 const type_slot_index = self.types.items.len;2268 const type_slot_index = self.types.items.len;
2555 try self.types.append(self.arena, .{ .Unanalyzed = {} });2269 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
25562270
2557 var scope: Scope = .{2271 var scope: Scope = .{
2558 .parent = parent_scope,2272 .parent = parent_scope,
...@@ -2672,7 +2386,7 @@ fn walkInstruction(...@@ -2672,7 +2386,7 @@ fn walkInstruction(
2672 },2386 },
2673 .enum_decl => {2387 .enum_decl => {
2674 const type_slot_index = self.types.items.len;2388 const type_slot_index = self.types.items.len;
2675 try self.types.append(self.arena, .{ .Unanalyzed = {} });2389 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
26762390
2677 var scope: Scope = .{2391 var scope: Scope = .{
2678 .parent = parent_scope,2392 .parent = parent_scope,
...@@ -2817,7 +2531,7 @@ fn walkInstruction(...@@ -2817,7 +2531,7 @@ fn walkInstruction(
2817 },2531 },
2818 .struct_decl => {2532 .struct_decl => {
2819 const type_slot_index = self.types.items.len;2533 const type_slot_index = self.types.items.len;
2820 try self.types.append(self.arena, .{ .Unanalyzed = {} });2534 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
28212535
2822 var scope: Scope = .{2536 var scope: Scope = .{
2823 .parent = parent_scope,2537 .parent = parent_scope,
...@@ -3122,7 +2836,7 @@ fn walkDecls(...@@ -3122,7 +2836,7 @@ fn walkDecls(
3122 };2836 };
31232837
3124 const walk_result = if (is_test) // TODO: decide if tests should show up at all2838 const walk_result = if (is_test) // TODO: decide if tests should show up at all
3125 DocData.WalkResult{ .expr = .{ .void = {} } }2839 DocData.WalkResult{ .expr = .{ .void = .{} } }
3126 else2840 else
3127 try self.walkInstruction(file, scope, value_index, true);2841 try self.walkInstruction(file, scope, value_index, true);
31282842
...@@ -3545,7 +3259,7 @@ fn analyzeFunctionExtended(...@@ -3545,7 +3259,7 @@ fn analyzeFunctionExtended(
3545 });3259 });
35463260
3547 param_type_refs.appendAssumeCapacity(3261 param_type_refs.appendAssumeCapacity(
3548 DocData.Expr{ .@"anytype" = {} },3262 DocData.Expr{ .@"anytype" = .{} },
3549 );3263 );
3550 },3264 },
3551 .param, .param_comptime => {3265 .param, .param_comptime => {
...@@ -3699,7 +3413,7 @@ fn analyzeFunction(...@@ -3699,7 +3413,7 @@ fn analyzeFunction(
3699 });3413 });
37003414
3701 param_type_refs.appendAssumeCapacity(3415 param_type_refs.appendAssumeCapacity(
3702 DocData.Expr{ .@"anytype" = {} },3416 DocData.Expr{ .@"anytype" = .{} },
3703 );3417 );
3704 },3418 },
3705 .param, .param_comptime => {3419 .param, .param_comptime => {
...@@ -3961,13 +3675,13 @@ fn walkRef(...@@ -3961,13 +3675,13 @@ fn walkRef(
3961 .void_value => {3675 .void_value => {
3962 return DocData.WalkResult{3676 return DocData.WalkResult{
3963 .typeRef = .{ .type = @enumToInt(Ref.void_type) },3677 .typeRef = .{ .type = @enumToInt(Ref.void_type) },
3964 .expr = .{ .void = {} },3678 .expr = .{ .void = .{} },
3965 };3679 };
3966 },3680 },
3967 .unreachable_value => {3681 .unreachable_value => {
3968 return DocData.WalkResult{3682 return DocData.WalkResult{
3969 .typeRef = .{ .type = @enumToInt(Ref.noreturn_type) },3683 .typeRef = .{ .type = @enumToInt(Ref.noreturn_type) },
3970 .expr = .{ .@"unreachable" = {} },3684 .expr = .{ .@"unreachable" = .{} },
3971 };3685 };
3972 },3686 },
3973 .null_value => {3687 .null_value => {
...@@ -4063,3 +3777,23 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul...@@ -4063,3 +3777,23 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul
4063 });3777 });
4064 return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } };3778 return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } };
4065}3779}
3780
3781fn writeFileTableToJson(map: std.AutoArrayHashMapUnmanaged(*File, usize), jsw: anytype) !void {
3782 try jsw.beginObject();
3783 var it = map.iterator();
3784 while (it.next()) |entry| {
3785 try jsw.objectField(entry.key_ptr.*.sub_file_path);
3786 try jsw.emitNumber(entry.value_ptr.*);
3787 }
3788 try jsw.endObject();
3789}
3790
3791fn writePackageTableToJson(map: std.StringHashMapUnmanaged(usize), jsw: anytype) !void {
3792 try jsw.beginObject();
3793 var it = map.iterator();
3794 while (it.next()) |entry| {
3795 try jsw.objectField(entry.key_ptr.*);
3796 try jsw.emitNumber(entry.value_ptr.*);
3797 }
3798 try jsw.endObject();
3799}