| ... | @@ -402,7 +402,10 @@ const DocData = struct { | ... | @@ -402,7 +402,10 @@ const DocData = struct { |
| 402 | child: TypeRef, | 402 | child: TypeRef, |
| 403 | }, | 403 | }, |
| 404 | ErrorUnion: struct { name: []const u8 }, | 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 | Enum: struct { | 409 | Enum: struct { |
| 407 | name: []const u8, | 410 | name: []const u8, |
| 408 | src: ?usize = null, // index into astNodes | 411 | src: ?usize = null, // index into astNodes |
| ... | @@ -430,6 +433,11 @@ const DocData = struct { | ... | @@ -430,6 +433,11 @@ const DocData = struct { |
| 430 | Vector: struct { name: []const u8 }, | 433 | Vector: struct { name: []const u8 }, |
| 431 | EnumLiteral: struct { name: []const u8 }, | 434 | EnumLiteral: struct { name: []const u8 }, |
| 432 | | 435 | |
| | 436 | const Field = struct { |
| | 437 | name: []const u8, |
| | 438 | docs: []const u8, |
| | 439 | }; |
| | 440 | |
| 433 | pub fn jsonStringify( | 441 | pub fn jsonStringify( |
| 434 | self: Type, | 442 | self: Type, |
| 435 | opt: std.json.StringifyOptions, | 443 | opt: std.json.StringifyOptions, |
| ... | @@ -1167,6 +1175,37 @@ fn walkInstruction( | ... | @@ -1167,6 +1175,37 @@ fn walkInstruction( |
| 1167 | .fieldVals = field_vals, | 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 | .param_anytype => { | 1209 | .param_anytype => { |
| 1171 | // Analysis of anytype function params happens in `.func`. | 1210 | // Analysis of anytype function params happens in `.func`. |
| 1172 | // This switch case handles the case where an expression depends | 1211 | // This switch case handles the case where an expression depends |
| ... | @@ -1228,88 +1267,12 @@ fn walkInstruction( | ... | @@ -1228,88 +1267,12 @@ fn walkInstruction( |
| 1228 | return DocData.WalkResult{ .call = call_slot_index }; | 1267 | return DocData.WalkResult{ .call = call_slot_index }; |
| 1229 | }, | 1268 | }, |
| 1230 | .func, .func_inferred => { | 1269 | .func, .func_inferred => { |
| 1231 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); | 1270 | return self.analyzeFunction( |
| 1232 | | 1271 | file, |
| 1233 | try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len); | 1272 | parent_scope, |
| 1234 | var param_type_refs = try std.ArrayListUnmanaged(DocData.TypeRef).initCapacity( | 1273 | inst_index, |
| 1235 | self.arena, | 1274 | self_ast_node_index, |
| 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, | | |
| 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 | .extended => { | 1277 | .extended => { |
| 1315 | // NOTE: this code + the subsequent defer block are working towards | 1278 | // NOTE: this code + the subsequent defer block are working towards |
| ... | @@ -1338,11 +1301,21 @@ fn walkInstruction( | ... | @@ -1338,11 +1301,21 @@ fn walkInstruction( |
| 1338 | const extended = data[inst_index].extended; | 1301 | const extended = data[inst_index].extended; |
| 1339 | switch (extended.opcode) { | 1302 | switch (extended.opcode) { |
| 1340 | else => { | 1303 | else => { |
| 1341 | std.debug.panic( | 1304 | panicWithContext( |
| 1342 | "TODO: implement `walkinstruction.extended` for {s}\n\n", | 1305 | file, |
| | 1306 | inst_index, |
| | 1307 | "TODO: implement `walkInstruction.extended` for {s}\n\n", |
| 1343 | .{@tagName(extended.opcode)}, | 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 | .variable => { | 1319 | .variable => { |
| 1347 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); | 1320 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| 1348 | var extra_index: usize = extended.operand; | 1321 | var extra_index: usize = extended.operand; |
| ... | @@ -2105,6 +2078,99 @@ fn tryResolveDeclPath( | ... | @@ -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 | fn collectUnionFieldInfo( | 2174 | fn collectUnionFieldInfo( |
| 2109 | self: *Autodoc, | 2175 | self: *Autodoc, |
| 2110 | file: *File, | 2176 | file: *File, |