| ... | @@ -28,7 +28,7 @@ decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, | ... | @@ -28,7 +28,7 @@ decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, |
| 28 | exprs: std.ArrayListUnmanaged(DocData.Expr) = .{}, | 28 | exprs: std.ArrayListUnmanaged(DocData.Expr) = .{}, |
| 29 | ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, | 29 | ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, |
| 30 | comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{}, | 30 | comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{}, |
| 31 | guides: std.StringHashMapUnmanaged([]const u8) = .{}, | 31 | guide_sections: std.ArrayListUnmanaged(Section) = .{}, |
| 32 | | 32 | |
| 33 | // These fields hold temporary state of the analysis process | 33 | // These fields hold temporary state of the analysis process |
| 34 | // and are mainly used by the decl path resolving algorithm. | 34 | // and are mainly used by the decl path resolving algorithm. |
| ... | @@ -63,6 +63,16 @@ const SrcLocInfo = struct { | ... | @@ -63,6 +63,16 @@ const SrcLocInfo = struct { |
| 63 | src_node: u32 = 0, | 63 | src_node: u32 = 0, |
| 64 | }; | 64 | }; |
| 65 | | 65 | |
| | 66 | const Section = struct { |
| | 67 | name: []const u8 = "", // empty string is the default section |
| | 68 | guides: std.ArrayListUnmanaged(Guide) = .{}, |
| | 69 | |
| | 70 | const Guide = struct { |
| | 71 | name: []const u8, |
| | 72 | body: []const u8, |
| | 73 | }; |
| | 74 | }; |
| | 75 | |
| 66 | var arena_allocator: std.heap.ArenaAllocator = undefined; | 76 | var arena_allocator: std.heap.ArenaAllocator = undefined; |
| 67 | pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc { | 77 | pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc { |
| 68 | arena_allocator = std.heap.ArenaAllocator.init(m.gpa); | 78 | arena_allocator = std.heap.ArenaAllocator.init(m.gpa); |
| ... | @@ -253,7 +263,7 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -253,7 +263,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 253 | .exprs = self.exprs.items, | 263 | .exprs = self.exprs.items, |
| 254 | .astNodes = self.ast_nodes.items, | 264 | .astNodes = self.ast_nodes.items, |
| 255 | .comptimeExprs = self.comptime_exprs.items, | 265 | .comptimeExprs = self.comptime_exprs.items, |
| 256 | .guides = self.guides, | 266 | .guide_sections = self.guide_sections, |
| 257 | }; | 267 | }; |
| 258 | | 268 | |
| 259 | const base_dir = self.doc_location.directory orelse | 269 | const base_dir = self.doc_location.directory orelse |
| ... | @@ -419,7 +429,7 @@ const DocData = struct { | ... | @@ -419,7 +429,7 @@ const DocData = struct { |
| 419 | exprs: []Expr, | 429 | exprs: []Expr, |
| 420 | comptimeExprs: []ComptimeExpr, | 430 | comptimeExprs: []ComptimeExpr, |
| 421 | | 431 | |
| 422 | guides: std.StringHashMapUnmanaged([]const u8), | 432 | guide_sections: std.ArrayListUnmanaged(Section), |
| 423 | | 433 | |
| 424 | const Call = struct { | 434 | const Call = struct { |
| 425 | func: Expr, | 435 | func: Expr, |
| ... | @@ -440,7 +450,7 @@ const DocData = struct { | ... | @@ -440,7 +450,7 @@ const DocData = struct { |
| 440 | try jsw.objectField(f_name); | 450 | try jsw.objectField(f_name); |
| 441 | switch (f) { | 451 | switch (f) { |
| 442 | .files => try writeFileTableToJson(self.files, &jsw), | 452 | .files => try writeFileTableToJson(self.files, &jsw), |
| 443 | .guides => try writeGuidesToJson(self.guides, &jsw), | 453 | .guide_sections => try writeGuidesToJson(self.guide_sections, &jsw), |
| 444 | else => { | 454 | else => { |
| 445 | try std.json.stringify(@field(self, f_name), opts, w); | 455 | try std.json.stringify(@field(self, f_name), opts, w); |
| 446 | jsw.state_index -= 1; | 456 | jsw.state_index -= 1; |
| ... | @@ -4613,14 +4623,39 @@ fn writeFileTableToJson(map: std.AutoArrayHashMapUnmanaged(*File, usize), jsw: a | ... | @@ -4613,14 +4623,39 @@ fn writeFileTableToJson(map: std.AutoArrayHashMapUnmanaged(*File, usize), jsw: a |
| 4613 | try jsw.endArray(); | 4623 | try jsw.endArray(); |
| 4614 | } | 4624 | } |
| 4615 | | 4625 | |
| 4616 | fn writeGuidesToJson(map: std.StringHashMapUnmanaged([]const u8), jsw: anytype) !void { | 4626 | /// Writes the data like so: |
| 4617 | try jsw.beginObject(); | 4627 | /// ``` |
| 4618 | var it = map.iterator(); | 4628 | /// { |
| 4619 | while (it.next()) |entry| { | 4629 | /// "<section name>": [{name: "<guide name>", text: "<guide contents>"},], |
| 4620 | try jsw.objectField(entry.key_ptr.*); | 4630 | /// } |
| 4621 | try jsw.emitString(entry.value_ptr.*); | 4631 | /// ``` |
| | 4632 | fn writeGuidesToJson(sections: std.ArrayListUnmanaged(Section), jsw: anytype) !void { |
| | 4633 | try jsw.beginArray(); |
| | 4634 | |
| | 4635 | for (sections.items) |s| { |
| | 4636 | // section name |
| | 4637 | try jsw.arrayElem(); |
| | 4638 | try jsw.beginObject(); |
| | 4639 | try jsw.objectField("name"); |
| | 4640 | try jsw.emitString(s.name); |
| | 4641 | try jsw.objectField("guides"); |
| | 4642 | |
| | 4643 | // section value |
| | 4644 | try jsw.beginArray(); |
| | 4645 | for (s.guides.items) |g| { |
| | 4646 | try jsw.arrayElem(); |
| | 4647 | try jsw.beginObject(); |
| | 4648 | try jsw.objectField("name"); |
| | 4649 | try jsw.emitString(g.name); |
| | 4650 | try jsw.objectField("body"); |
| | 4651 | try jsw.emitString(g.body); |
| | 4652 | try jsw.endObject(); |
| | 4653 | } |
| | 4654 | try jsw.endArray(); |
| | 4655 | try jsw.endObject(); |
| 4622 | } | 4656 | } |
| 4623 | try jsw.endObject(); | 4657 | |
| | 4658 | try jsw.endArray(); |
| 4624 | } | 4659 | } |
| 4625 | | 4660 | |
| 4626 | fn writePackageTableToJson( | 4661 | fn writePackageTableToJson( |
| ... | @@ -4688,19 +4723,31 @@ fn getTLDocComment(self: *Autodoc, file: *File) ![]const u8 { | ... | @@ -4688,19 +4723,31 @@ fn getTLDocComment(self: *Autodoc, file: *File) ![]const u8 { |
| 4688 | } | 4723 | } |
| 4689 | | 4724 | |
| 4690 | fn findGuidePaths(self: *Autodoc, file: *File, str: []const u8) !void { | 4725 | fn findGuidePaths(self: *Autodoc, file: *File, str: []const u8) !void { |
| 4691 | const prefix = "zig-autodoc-guide:"; | 4726 | const guide_prefix = "zig-autodoc-guide:"; |
| | 4727 | const section_prefix = "zig-autodoc-section:"; |
| | 4728 | |
| | 4729 | try self.guide_sections.append(self.arena, .{}); // add a default section |
| | 4730 | var current_section = &self.guide_sections.items[self.guide_sections.items.len - 1]; |
| | 4731 | |
| 4692 | var it = std.mem.tokenize(u8, str, "\n"); | 4732 | var it = std.mem.tokenize(u8, str, "\n"); |
| 4693 | while (it.next()) |line| { | 4733 | while (it.next()) |line| { |
| 4694 | const trimmed_line = std.mem.trim(u8, line, " "); | 4734 | const trimmed_line = std.mem.trim(u8, line, " "); |
| 4695 | if (std.mem.startsWith(u8, trimmed_line, prefix)) { | 4735 | if (std.mem.startsWith(u8, trimmed_line, guide_prefix)) { |
| 4696 | const path = trimmed_line[prefix.len..]; | 4736 | const path = trimmed_line[guide_prefix.len..]; |
| 4697 | const trimmed_path = std.mem.trim(u8, path, " "); | 4737 | const trimmed_path = std.mem.trim(u8, path, " "); |
| 4698 | try self.addGuide(file, trimmed_path); | 4738 | try self.addGuide(file, trimmed_path, current_section); |
| | 4739 | } else if (std.mem.startsWith(u8, trimmed_line, section_prefix)) { |
| | 4740 | const section_name = trimmed_line[section_prefix.len..]; |
| | 4741 | const trimmed_section_name = std.mem.trim(u8, section_name, " "); |
| | 4742 | try self.guide_sections.append(self.arena, .{ |
| | 4743 | .name = trimmed_section_name, |
| | 4744 | }); |
| | 4745 | current_section = &self.guide_sections.items[self.guide_sections.items.len - 1]; |
| 4699 | } | 4746 | } |
| 4700 | } | 4747 | } |
| 4701 | } | 4748 | } |
| 4702 | | 4749 | |
| 4703 | fn addGuide(self: *Autodoc, file: *File, guide_path: []const u8) !void { | 4750 | fn addGuide(self: *Autodoc, file: *File, guide_path: []const u8, section: *Section) !void { |
| 4704 | if (guide_path.len == 0) return error.MissingAutodocGuideName; | 4751 | if (guide_path.len == 0) return error.MissingAutodocGuideName; |
| 4705 | | 4752 | |
| 4706 | const cur_pkg_dir_path = file.pkg.root_src_directory.path orelse "."; | 4753 | const cur_pkg_dir_path = file.pkg.root_src_directory.path orelse "."; |
| ... | @@ -4716,5 +4763,8 @@ fn addGuide(self: *Autodoc, file: *File, guide_path: []const u8) !void { | ... | @@ -4716,5 +4763,8 @@ fn addGuide(self: *Autodoc, file: *File, guide_path: []const u8) !void { |
| 4716 | else => |e| return e, | 4763 | else => |e| return e, |
| 4717 | }; | 4764 | }; |
| 4718 | | 4765 | |
| 4719 | try self.guides.put(self.arena, resolved_path, guide); | 4766 | try section.guides.append(self.arena, .{ |
| | 4767 | .name = resolved_path, |
| | 4768 | .body = guide, |
| | 4769 | }); |
| 4720 | } | 4770 | } |