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.
This commit is contained in:
Der Teufel
2023-01-21 15:38:53 +01:00
committed by Loris Cro
parent da68e7f0cb
commit dd8e16b906
2 changed files with 177 additions and 8 deletions

View File

@@ -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 {

View File

@@ -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;
};