| ... | ... | @@ -402,7 +402,10 @@ const DocData = struct { |
| 402 | 402 | child: TypeRef, |
| 403 | 403 | }, |
| 404 | 404 | ErrorUnion: struct { name: []const u8 }, |
| 405 | | ErrorSet: struct { name: []const u8 }, |
| 405 | ErrorSet: struct { |
| 406 | name: []const u8, |
| 407 | fields: []const Field, |
| 408 | }, |
| 406 | 409 | Enum: struct { |
| 407 | 410 | name: []const u8, |
| 408 | 411 | src: ?usize = null, // index into astNodes |
| ... | ... | @@ -430,6 +433,11 @@ const DocData = struct { |
| 430 | 433 | Vector: struct { name: []const u8 }, |
| 431 | 434 | EnumLiteral: struct { name: []const u8 }, |
| 432 | 435 | |
| 436 | const Field = struct { |
| 437 | name: []const u8, |
| 438 | docs: []const u8, |
| 439 | }; |
| 440 | |
| 433 | 441 | pub fn jsonStringify( |
| 434 | 442 | self: Type, |
| 435 | 443 | opt: std.json.StringifyOptions, |
| ... | ... | @@ -1167,6 +1175,37 @@ fn walkInstruction( |
| 1167 | 1175 | .fieldVals = field_vals, |
| 1168 | 1176 | } }; |
| 1169 | 1177 | }, |
| 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 | }, |
| 1170 | 1209 | .param_anytype => { |
| 1171 | 1210 | // Analysis of anytype function params happens in `.func`. |
| 1172 | 1211 | // This switch case handles the case where an expression depends |
| ... | ... | @@ -1228,88 +1267,12 @@ fn walkInstruction( |
| 1228 | 1267 | return DocData.WalkResult{ .call = call_slot_index }; |
| 1229 | 1268 | }, |
| 1230 | 1269 | .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, |
| 1241 | 1275 | ); |
| 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 }; |
| 1313 | 1276 | }, |
| 1314 | 1277 | .extended => { |
| 1315 | 1278 | // NOTE: this code + the subsequent defer block are working towards |
| ... | ... | @@ -1338,11 +1301,21 @@ fn walkInstruction( |
| 1338 | 1301 | const extended = data[inst_index].extended; |
| 1339 | 1302 | switch (extended.opcode) { |
| 1340 | 1303 | 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", |
| 1343 | 1308 | .{@tagName(extended.opcode)}, |
| 1344 | 1309 | ); |
| 1345 | 1310 | }, |
| 1311 | .func => { |
| 1312 | return try self.analyzeFunction( |
| 1313 | file, |
| 1314 | parent_scope, |
| 1315 | inst_index, |
| 1316 | self_ast_node_index, |
| 1317 | ); |
| 1318 | }, |
| 1346 | 1319 | .variable => { |
| 1347 | 1320 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| 1348 | 1321 | var extra_index: usize = extended.operand; |
| ... | ... | @@ -2105,6 +2078,99 @@ fn tryResolveDeclPath( |
| 2105 | 2078 | } |
| 2106 | 2079 | } |
| 2107 | 2080 | |
| 2081 | fn 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 | |
| 2108 | 2174 | fn collectUnionFieldInfo( |
| 2109 | 2175 | self: *Autodoc, |
| 2110 | 2176 | file: *File, |