From da68e7f0cbdf3a803765977ac5b27bfc5716087d Mon Sep 17 00:00:00 2001 From: Der Teufel Date: Sat, 21 Jan 2023 15:35:46 +0100 Subject: [PATCH 1/2] autodoc: add html tags to "null" --- lib/docs/main.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index 6823a97cc0..be922710a2 100644 --- a/lib/docs/main.js +++ b/lib/docs/main.js @@ -1641,7 +1641,11 @@ const NAV_MODES = { return payloadHtml; } case "null": { - return "null"; + if (opts.wantHtml) { + return 'null'; + } else { + return "null"; + } } case "array": { let payloadHtml = ".{"; From dd8e16b9065bc33195a398744c663718bec57d4d Mon Sep 17 00:00:00 2001 From: Der Teufel Date: Sat, 21 Jan 2023 15:38:53 +0100 Subject: [PATCH 2/2] 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. --- lib/docs/main.js | 157 ++++++++++++++++++++++++++++++++++++++++++++++- src/Autodoc.zig | 28 +++++++-- 2 files changed, 177 insertions(+), 8 deletions(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index be922710a2..6710dd964f 100644 --- a/lib/docs/main.js +++ b/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 = "struct { "; + } else { + name = "struct { "; + } + if (structObj.fields.length > 1 && opts.wantHtml) {name += "
";} + let indent = ""; + if (structObj.fields.length > 1 && opts.wantHtml) { + indent = "    " + } + if (opts.indent) { + indent = opts.indent + indent; + } + let structNode = getAstNode(structObj.src); + let field_end = ","; + if (structObj.fields.length > 1 && opts.wantHtml) { + field_end += "
"; + } 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 = "enum"; + } 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 += "
";} + let indent = ""; + if (fields_len > 1) { + if (opts.wantHtml) { + indent = "    "; + } else { + indent = " "; + } + } + if (opts.indent) { + indent = opts.indent + indent; + } + let field_end = ","; + if (fields_len > 1 && opts.wantHtml) { + field_end += "
"; + } 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 = "union"; + } else { + name = "union"; + } + if (unionObj.auto_tag) { + if (opts.wantHtml) { + name += " (enum"; + } 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 += "
"; + } + let indent = ""; + if (unionObj.fields.length > 1 && opts.wantHtml) { + indent = "    " + } + if (opts.indent) { + indent = opts.indent + indent; + } + let unionNode = getAstNode(unionObj.src); + let field_end = ","; + if (unionObj.fields.length > 1 && opts.wantHtml) { + field_end += "
"; + } 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 { diff --git a/src/Autodoc.zig b/src/Autodoc.zig index 6441470fde..fab20bff85 100644 --- a/src/Autodoc.zig +++ b/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; };