authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-03-13 19:25:34+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:11-07:00
log63be9e65ed151a75595ffeac287a6897067ae41f
treee197e89a1e9874fa3e1ea52ca72071d24e9905e2
parent67f1d2b967a13c794c57cb8b6783f2e52b029888

autodoc: added support for error sets and extended functions


2 files changed, 154 insertions(+), 84 deletions(-)

lib/docs/main.js+4
......@@ -236,6 +236,10 @@
236236 return { type: typeTypeId };
237237 }
238238
239 if ("bool" in decl.value) {
240 return { type: typeKinds.Bool };
241 }
242
239243 console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
240244 console.assert(false);
241245 throw {};
src/Autodoc.zig+150-84
......@@ -402,7 +402,10 @@ const DocData = struct {
402402 child: TypeRef,
403403 },
404404 ErrorUnion: struct { name: []const u8 },
405 ErrorSet: struct { name: []const u8 },
405 ErrorSet: struct {
406 name: []const u8,
407 fields: []const Field,
408 },
406409 Enum: struct {
407410 name: []const u8,
408411 src: ?usize = null, // index into astNodes
......@@ -430,6 +433,11 @@ const DocData = struct {
430433 Vector: struct { name: []const u8 },
431434 EnumLiteral: struct { name: []const u8 },
432435
436 const Field = struct {
437 name: []const u8,
438 docs: []const u8,
439 };
440
433441 pub fn jsonStringify(
434442 self: Type,
435443 opt: std.json.StringifyOptions,
......@@ -1167,6 +1175,37 @@ fn walkInstruction(
11671175 .fieldVals = field_vals,
11681176 } };
11691177 },
1178 .error_set_decl => {
1179 const pl_node = data[inst_index].pl_node;
1180 const extra = file.zir.extraData(Zir.Inst.ErrorSetDecl, pl_node.payload_index);
1181 const fields = try self.arena.alloc(
1182 DocData.Type.Field,
1183 extra.data.fields_len,
1184 );
1185 var idx = extra.end;
1186 for (fields) |*f| {
1187 const name = file.zir.nullTerminatedString(file.zir.extra[idx]);
1188 idx += 1;
1189
1190 const docs = file.zir.nullTerminatedString(file.zir.extra[idx]);
1191 idx += 1;
1192
1193 f.* = .{
1194 .name = name,
1195 .docs = docs,
1196 };
1197 }
1198
1199 const type_slot_index = self.types.items.len;
1200 try self.types.append(self.arena, .{
1201 .ErrorSet = .{
1202 .name = "todo errset",
1203 .fields = fields,
1204 },
1205 });
1206
1207 return DocData.WalkResult{ .type = type_slot_index };
1208 },
11701209 .param_anytype => {
11711210 // Analysis of anytype function params happens in `.func`.
11721211 // This switch case handles the case where an expression depends
......@@ -1228,88 +1267,12 @@ fn walkInstruction(
12281267 return DocData.WalkResult{ .call = call_slot_index };
12291268 },
12301269 .func, .func_inferred => {
1231 const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index));
1232
1233 try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
1234 var param_type_refs = try std.ArrayListUnmanaged(DocData.TypeRef).initCapacity(
1235 self.arena,
1236 fn_info.total_params_len,
1237 );
1238 var param_ast_indexes = try std.ArrayListUnmanaged(usize).initCapacity(
1239 self.arena,
1240 fn_info.total_params_len,
1270 return self.analyzeFunction(
1271 file,
1272 parent_scope,
1273 inst_index,
1274 self_ast_node_index,
12411275 );
1242 // TODO: handle scope rules for fn parameters
1243 for (fn_info.param_body[0..fn_info.total_params_len]) |param_index| {
1244 switch (tags[param_index]) {
1245 else => panicWithContext(
1246 file,
1247 param_index,
1248 "TODO: handle `{s}` in walkInstruction.func\n",
1249 .{@tagName(tags[param_index])},
1250 ),
1251 .param_anytype => {
1252 // TODO: where are the doc comments?
1253 const str_tok = data[param_index].str_tok;
1254
1255 const name = str_tok.get(file.zir);
1256
1257 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
1258 self.ast_nodes.appendAssumeCapacity(.{
1259 .name = name,
1260 .docs = "",
1261 .@"comptime" = true,
1262 });
1263
1264 param_type_refs.appendAssumeCapacity(
1265 DocData.TypeRef{ .@"anytype" = {} },
1266 );
1267 },
1268 .param, .param_comptime => {
1269 const pl_tok = data[param_index].pl_tok;
1270 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
1271 const doc_comment = if (extra.data.doc_comment != 0)
1272 file.zir.nullTerminatedString(extra.data.doc_comment)
1273 else
1274 "";
1275 const name = file.zir.nullTerminatedString(extra.data.name);
1276
1277 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
1278 self.ast_nodes.appendAssumeCapacity(.{
1279 .name = name,
1280 .docs = doc_comment,
1281 .@"comptime" = tags[param_index] == .param_comptime,
1282 });
1283
1284 const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1];
1285 const break_operand = data[break_index].@"break".operand;
1286 const param_type_ref = try self.walkRef(file, parent_scope, break_operand);
1287
1288 param_type_refs.appendAssumeCapacity(
1289 walkResultToTypeRef(param_type_ref),
1290 );
1291 },
1292 }
1293 }
1294
1295 // ret
1296 const ret_type_ref = blk: {
1297 const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1];
1298 const break_operand = data[last_instr_index].@"break".operand;
1299 const wr = try self.walkRef(file, parent_scope, break_operand);
1300 break :blk walkResultToTypeRef(wr);
1301 };
1302
1303 self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items;
1304 try self.types.append(self.arena, .{
1305 .Fn = .{
1306 .name = "todo_name func",
1307 .src = self_ast_node_index,
1308 .params = param_type_refs.items,
1309 .ret = ret_type_ref,
1310 },
1311 });
1312 return DocData.WalkResult{ .type = self.types.items.len - 1 };
13131276 },
13141277 .extended => {
13151278 // NOTE: this code + the subsequent defer block are working towards
......@@ -1338,11 +1301,21 @@ fn walkInstruction(
13381301 const extended = data[inst_index].extended;
13391302 switch (extended.opcode) {
13401303 else => {
1341 std.debug.panic(
1342 "TODO: implement `walkinstruction.extended` for {s}\n\n",
1304 panicWithContext(
1305 file,
1306 inst_index,
1307 "TODO: implement `walkInstruction.extended` for {s}\n\n",
13431308 .{@tagName(extended.opcode)},
13441309 );
13451310 },
1311 .func => {
1312 return try self.analyzeFunction(
1313 file,
1314 parent_scope,
1315 inst_index,
1316 self_ast_node_index,
1317 );
1318 },
13461319 .variable => {
13471320 const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small);
13481321 var extra_index: usize = extended.operand;
......@@ -2105,6 +2078,99 @@ fn tryResolveDeclPath(
21052078 }
21062079}
21072080
2081fn analyzeFunction(
2082 self: *Autodoc,
2083 file: *File,
2084 scope: *Scope,
2085 inst_index: usize,
2086 self_ast_node_index: usize,
2087) error{OutOfMemory}!DocData.WalkResult {
2088 const tags = file.zir.instructions.items(.tag);
2089 const data = file.zir.instructions.items(.data);
2090
2091 const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index));
2092 try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len);
2093 var param_type_refs = try std.ArrayListUnmanaged(DocData.TypeRef).initCapacity(
2094 self.arena,
2095 fn_info.total_params_len,
2096 );
2097 var param_ast_indexes = try std.ArrayListUnmanaged(usize).initCapacity(
2098 self.arena,
2099 fn_info.total_params_len,
2100 );
2101 // TODO: handle scope rules for fn parameters
2102 for (fn_info.param_body[0..fn_info.total_params_len]) |param_index| {
2103 switch (tags[param_index]) {
2104 else => panicWithContext(
2105 file,
2106 param_index,
2107 "TODO: handle `{s}` in walkInstruction.func\n",
2108 .{@tagName(tags[param_index])},
2109 ),
2110 .param_anytype => {
2111 // TODO: where are the doc comments?
2112 const str_tok = data[param_index].str_tok;
2113
2114 const name = str_tok.get(file.zir);
2115
2116 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
2117 self.ast_nodes.appendAssumeCapacity(.{
2118 .name = name,
2119 .docs = "",
2120 .@"comptime" = true,
2121 });
2122
2123 param_type_refs.appendAssumeCapacity(
2124 DocData.TypeRef{ .@"anytype" = {} },
2125 );
2126 },
2127 .param, .param_comptime => {
2128 const pl_tok = data[param_index].pl_tok;
2129 const extra = file.zir.extraData(Zir.Inst.Param, pl_tok.payload_index);
2130 const doc_comment = if (extra.data.doc_comment != 0)
2131 file.zir.nullTerminatedString(extra.data.doc_comment)
2132 else
2133 "";
2134 const name = file.zir.nullTerminatedString(extra.data.name);
2135
2136 param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len);
2137 self.ast_nodes.appendAssumeCapacity(.{
2138 .name = name,
2139 .docs = doc_comment,
2140 .@"comptime" = tags[param_index] == .param_comptime,
2141 });
2142
2143 const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1];
2144 const break_operand = data[break_index].@"break".operand;
2145 const param_type_ref = try self.walkRef(file, scope, break_operand);
2146
2147 param_type_refs.appendAssumeCapacity(
2148 walkResultToTypeRef(param_type_ref),
2149 );
2150 },
2151 }
2152 }
2153
2154 // ret
2155 const ret_type_ref = blk: {
2156 const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1];
2157 const break_operand = data[last_instr_index].@"break".operand;
2158 const wr = try self.walkRef(file, scope, break_operand);
2159 break :blk walkResultToTypeRef(wr);
2160 };
2161
2162 self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items;
2163 try self.types.append(self.arena, .{
2164 .Fn = .{
2165 .name = "todo_name func",
2166 .src = self_ast_node_index,
2167 .params = param_type_refs.items,
2168 .ret = ret_type_ref,
2169 },
2170 });
2171 return DocData.WalkResult{ .type = self.types.items.len - 1 };
2172}
2173
21082174fn collectUnionFieldInfo(
21092175 self: *Autodoc,
21102176 file: *File,