Commit dd8e16b906

Der Teufel <der.teufel.mail@gmail.com>
2023-01-21 15:38:53
autodoc: Add tag handling to enums and unions. Add support for Struct, Enum, Union types in exprName. Anonymous types now work via a hack to ast_nodes.
1 parent da68e7f
Changed files (2)
lib
docs
src
lib/docs/main.js
@@ -1770,11 +1770,160 @@ const NAV_MODES = {
             throw "TODO";
           case typeKinds.Struct: {
             let structObj = typeObj;
-            return structObj;
+            let name = "";
+            if (opts.wantHtml) {
+              name = "<span class='tok-kw'>struct</span> { ";
+            } else {
+              name = "struct { ";
+            }
+            if (structObj.fields.length > 1 && opts.wantHtml) {name += "</br>";}
+            let indent = "";
+            if (structObj.fields.length > 1 && opts.wantHtml) {
+              indent = "&nbsp;&nbsp;&nbsp;&nbsp;"
+            }
+            if (opts.indent) {
+              indent = opts.indent + indent;
+            }
+            let structNode = getAstNode(structObj.src);
+            let field_end = ",";
+            if (structObj.fields.length > 1 && opts.wantHtml) {
+              field_end += "</br>";
+            } else {
+              field_end += " ";
+            }
+
+            for(let i = 0; i < structObj.fields.length; i += 1) {
+              let fieldNode = getAstNode(structNode.fields[i]);
+              let fieldName = fieldNode.name;
+              let html = indent + escapeHtml(fieldName);
+
+              let fieldTypeExpr = structObj.fields[i];
+              html += ": ";
+
+              html += exprName(fieldTypeExpr, {...opts, indent: indent});
+
+              html += field_end;
+
+              name += html;
+            }
+            if (opts.indent) {
+              name += opts.indent;
+            }
+            name += "}";
+            return name;
           }
           case typeKinds.Enum: {
             let enumObj = typeObj;
-            return enumObj;
+            let name = "";
+            if (opts.wantHtml) {
+              name = "<span class='tok-kw'>enum</span>";
+            } else {
+              name = "enum";
+            }
+            if (enumObj.tag) {
+              name += " (" + exprName(enumObj.tag, opts) + ")";
+            }
+            name += " { ";
+            let enumNode = getAstNode(enumObj.src);
+            let fields_len = enumNode.fields.length;
+            if (enumObj.nonexhaustive) {
+              fields_len += 1;
+            }
+            if (fields_len > 1 && opts.wantHtml) {name += "</br>";}
+            let indent = "";
+            if (fields_len > 1) {
+              if (opts.wantHtml) {
+                indent = "&nbsp;&nbsp;&nbsp;&nbsp;";
+              } else {
+                indent = "    ";
+              }
+            }
+            if (opts.indent) {
+              indent = opts.indent + indent;
+            }
+            let field_end = ",";
+            if (fields_len > 1 && opts.wantHtml) {
+              field_end += "</br>";
+            } else {
+              field_end += " ";
+            }
+            for(let i = 0; i < enumNode.fields.length; i += 1) {
+              let fieldNode = getAstNode(enumNode.fields[i]);
+              let fieldName = fieldNode.name;
+              let html =  indent + escapeHtml(fieldName);
+
+              html += field_end;
+
+              name += html;
+            }
+            if (enumObj.nonexhaustive) {
+              name += indent + "_" + field_end;
+            }
+            if (opts.indent) {
+              name += opts.indent;
+            }
+            name += "}";
+            return name;
+          }
+          case typeKinds.Union: {
+            let unionObj = typeObj;
+            let name = "";
+            if (opts.wantHtml) {
+              name = "<span class='tok-kw'>union</span>";
+            } else {
+              name = "union";
+            }
+            if (unionObj.auto_tag) {
+                if (opts.wantHtml) {
+                  name += " (<span class='tok-kw'>enum</span>";
+                } else {
+                  name += " (enum";
+                }
+                if (unionObj.tag) {
+                    name += "(" + exprName(unionObj.tag, opts) + "))";
+                } else {
+                  name += ")";
+                }
+            } else if (unionObj.tag) {
+              name += " (" + exprName(unionObj.tag, opts) + ")";
+            }
+            name += " { ";
+            if (unionObj.fields.length > 1 && opts.wantHtml) {
+              name += "</br>";
+            }
+            let indent = "";
+            if (unionObj.fields.length > 1 && opts.wantHtml) {
+              indent = "&nbsp;&nbsp;&nbsp;&nbsp;"
+            }
+            if (opts.indent) {
+              indent = opts.indent + indent;
+            }
+            let unionNode = getAstNode(unionObj.src);
+            let field_end = ",";
+            if (unionObj.fields.length > 1 && opts.wantHtml) {
+              field_end += "</br>";
+            } else {
+              field_end += " ";
+            }
+            for(let i = 0; i < unionObj.fields.length; i += 1) {
+              let fieldNode = getAstNode(unionNode.fields[i]);
+              let fieldName = fieldNode.name;
+              let html = indent + escapeHtml(fieldName);
+
+              let fieldTypeExpr = unionObj.fields[i];
+              html += ": ";
+
+              html += exprName(fieldTypeExpr, {...opts, indent: indent});
+
+              html += field_end;
+
+              name += html;
+            }
+            if (opts.indent) {
+              name += opts.indent;
+            }
+            name += "}";
+            return name;
           }
           case typeKinds.Opaque: {
             let opaqueObj = typeObj;
@@ -3835,6 +3984,8 @@ const NAV_MODES = {
           src: ty[2],
           privDecls: ty[3],
           pubDecls: ty[4],
+          tag: ty[5],
+          nonexhaustive: ty[6],
         };
       case 20: // Union
         return {
@@ -3844,6 +3995,8 @@ const NAV_MODES = {
           privDecls: ty[3],
           pubDecls: ty[4],
           fields: ty[5],
+          tag: ty[6],
+          auto_tag: ty[7],
         };
       case 21: // Fn
         return {
src/Autodoc.zig
@@ -586,6 +586,8 @@ const DocData = struct {
             privDecls: []usize = &.{}, // index into decls
             pubDecls: []usize = &.{}, // index into decls
             // (use src->fields to find field names)
+            tag: ?Expr = null, // tag type if specified
+            nonexhaustive: bool,
         },
         Union: struct {
             name: []const u8,
@@ -593,6 +595,8 @@ const DocData = struct {
             privDecls: []usize = &.{}, // index into decls
             pubDecls: []usize = &.{}, // index into decls
             fields: []Expr = &.{}, // (use src->fields to find names)
+            tag: ?Expr, // tag type if specified
+            auto_enum: bool, // tag is an auto enum
         },
         Fn: struct {
             name: []const u8,
@@ -2559,12 +2563,13 @@ fn walkInstruction(
                     else
                         parent_src;
 
-                    const tag_type: ?Ref = if (small.has_tag_type) blk: {
+                    const tag_type: ?DocData.Expr = if (small.has_tag_type) blk: {
                         const tag_type = file.zir.extra[extra_index];
                         extra_index += 1;
-                        break :blk @intToEnum(Ref, tag_type);
+                        const tag_ref = @intToEnum(Ref, tag_type);
+                        const wr = try self.walkRef(file, parent_scope, parent_src, tag_ref, false);
+                        break :blk wr.expr;
                     } else null;
-                    _ = tag_type;
 
                     const body_len = if (small.has_body_len) blk: {
                         const body_len = file.zir.extra[extra_index];
@@ -2652,6 +2657,8 @@ fn walkInstruction(
                             .privDecls = priv_decl_indexes.items,
                             .pubDecls = decl_indexes.items,
                             .fields = field_type_refs.items,
+                            .tag = tag_type,
+                            .auto_enum = small.auto_enum_tag,
                         },
                     };
 
@@ -2698,12 +2705,13 @@ fn walkInstruction(
                     else
                         parent_src;
 
-                    const tag_type: ?Ref = if (small.has_tag_type) blk: {
+                    const tag_type: ?DocData.Expr = if (small.has_tag_type) blk: {
                         const tag_type = file.zir.extra[extra_index];
                         extra_index += 1;
-                        break :blk @intToEnum(Ref, tag_type);
+                        const tag_ref = @intToEnum(Ref, tag_type);
+                        const wr = try self.walkRef(file, parent_scope, parent_src, tag_ref, false);
+                        break :blk wr.expr;
                     } else null;
-                    _ = tag_type;
 
                     const body_len = if (small.has_body_len) blk: {
                         const body_len = file.zir.extra[extra_index];
@@ -2816,6 +2824,8 @@ fn walkInstruction(
                             .src = self_ast_node_index,
                             .privDecls = priv_decl_indexes.items,
                             .pubDecls = decl_indexes.items,
+                            .tag = tag_type,
+                            .nonexhaustive = small.nonexhaustive,
                         },
                     };
                     if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| {
@@ -4185,6 +4195,12 @@ fn collectStructFieldInfo(
 
             const break_inst = body[body.len - 1];
             const operand = data[break_inst].@"break".operand;
+            try self.ast_nodes.append(self.arena, .{
+                .file = self.files.getIndex(file).?,
+                .line = parent_src.line,
+                .col = 0,
+                .fields = null, // walkInstruction will fill `fields` if necessary
+            });
             const walk_result = try self.walkRef(file, scope, parent_src, operand, false);
             break :expr walk_result.expr;
         };