| ... | ... | @@ -252,6 +252,8 @@ const DocData = struct { |
| 252 | 252 | src: usize, // index into astNodes |
| 253 | 253 | // typeRef: TypeRef, |
| 254 | 254 | value: WalkResult, |
| 255 | // The index in astNodes of the `test declname { }` node |
| 256 | decltest: ?usize = null, |
| 255 | 257 | }; |
| 256 | 258 | |
| 257 | 259 | const AstNode = struct { |
| ... | ... | @@ -610,11 +612,7 @@ fn walkInstruction( |
| 610 | 612 | //return self.walkRef(file, parent_scope, break_operand); |
| 611 | 613 | //}, |
| 612 | 614 | .block_inline => { |
| 613 | | const pl_node = data[inst_index].pl_node; |
| 614 | | const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 615 | | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 616 | | const break_operand = data[break_index].@"break".operand; |
| 617 | | return self.walkRef(file, parent_scope, break_operand); |
| 615 | return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index)); |
| 618 | 616 | }, |
| 619 | 617 | .func => { |
| 620 | 618 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); |
| ... | ... | @@ -947,13 +945,17 @@ fn walkInstruction( |
| 947 | 945 | // Done to make sure that all decl refs can be resolved correctly, |
| 948 | 946 | // even if we haven't fully analyzed the decl yet. |
| 949 | 947 | { |
| 948 | var actual_decls_len: usize = 0; |
| 950 | 949 | var it = file.zir.declIterator(@intCast(u32, inst_index)); |
| 951 | | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 952 | 950 | var decls_slot_index = decls_first_index; |
| 953 | 951 | while (it.next()) |d| : (decls_slot_index += 1) { |
| 954 | 952 | const decl_name_index = file.zir.extra[d.sub_index + 5]; |
| 953 | if (decl_name_index == 2) continue; // we don't do decltests here |
| 954 | actual_decls_len += 1; |
| 955 | 955 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| 956 | 956 | } |
| 957 | // we don't count decltests in our decls |
| 958 | try self.decls.resize(self.arena, decls_first_index + actual_decls_len); |
| 957 | 959 | } |
| 958 | 960 | |
| 959 | 961 | extra_index = try self.walkDecls( |
| ... | ... | @@ -1042,7 +1044,7 @@ fn walkDecls( |
| 1042 | 1044 | |
| 1043 | 1045 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; |
| 1044 | 1046 | extra_index += 4; |
| 1045 | | // const line = file.zir.extra[extra_index]; |
| 1047 | const line = file.zir.extra[extra_index]; |
| 1046 | 1048 | extra_index += 1; |
| 1047 | 1049 | const decl_name_index = file.zir.extra[extra_index]; |
| 1048 | 1050 | extra_index += 1; |
| ... | ... | @@ -1075,6 +1077,74 @@ fn walkDecls( |
| 1075 | 1077 | break :blk if (is_exported) "usingnamespace" else "comptime"; |
| 1076 | 1078 | } else if (decl_name_index == 1) { |
| 1077 | 1079 | break :blk "test"; |
| 1080 | } else if (decl_name_index == 2) { |
| 1081 | // it is a decltest |
| 1082 | const decl_being_tested = scope.resolveDeclName(doc_comment_index); |
| 1083 | const ast_node_index = idx: { |
| 1084 | const idx = self.ast_nodes.items.len; |
| 1085 | const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this |
| 1086 | const source_of_decltest_function = srcloc: { |
| 1087 | const func_index = getBlockInlineBreak(file.zir, decl_index); |
| 1088 | // a decltest is always a function |
| 1089 | const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?]; |
| 1090 | std.debug.assert(tag == .extended); |
| 1091 | |
| 1092 | const extended = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].extended; |
| 1093 | const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, extended.operand); |
| 1094 | const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small); |
| 1095 | |
| 1096 | var extra_index_for_this_func: usize = extra.end; |
| 1097 | if (small.has_lib_name) extra_index_for_this_func += 1; |
| 1098 | if (small.has_cc) extra_index_for_this_func += 1; |
| 1099 | if (small.has_align) extra_index_for_this_func += 1; |
| 1100 | |
| 1101 | const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len]; |
| 1102 | extra_index_for_this_func += ret_ty_body.len; |
| 1103 | |
| 1104 | const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len]; |
| 1105 | extra_index_for_this_func += body.len; |
| 1106 | |
| 1107 | var src_locs: Zir.Inst.Func.SrcLocs = undefined; |
| 1108 | if (body.len != 0) { |
| 1109 | src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data; |
| 1110 | } else { |
| 1111 | src_locs = .{ |
| 1112 | .lbrace_line = line, |
| 1113 | .rbrace_line = line, |
| 1114 | .columns = 0, // TODO get columns when body.len == 0 |
| 1115 | }; |
| 1116 | } |
| 1117 | break :srcloc src_locs; |
| 1118 | }; |
| 1119 | const source_slice = slice: { |
| 1120 | var start_byte_offset: u32 = 0; |
| 1121 | var end_byte_offset: u32 = 0; |
| 1122 | const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16); |
| 1123 | var lines: u32 = 0; |
| 1124 | for (file_source.bytes) |b, i| { |
| 1125 | if (b == '\n') { |
| 1126 | lines += 1; |
| 1127 | } |
| 1128 | if (lines == source_of_decltest_function.lbrace_line) { |
| 1129 | start_byte_offset = @intCast(u32, i); |
| 1130 | } |
| 1131 | if (lines == source_of_decltest_function.rbrace_line) { |
| 1132 | end_byte_offset = @intCast(u32, i) + rbrace_col; |
| 1133 | break; |
| 1134 | } |
| 1135 | } |
| 1136 | break :slice file_source.bytes[start_byte_offset..end_byte_offset]; |
| 1137 | }; |
| 1138 | try self.ast_nodes.append(self.arena, .{ |
| 1139 | .file = 0, |
| 1140 | .line = line, |
| 1141 | .col = 0, |
| 1142 | .name = try self.arena.dupe(u8, source_slice), |
| 1143 | }); |
| 1144 | break :idx idx; |
| 1145 | }; |
| 1146 | self.decls.items[decl_being_tested].decltest = ast_node_index; |
| 1147 | continue; |
| 1078 | 1148 | } else { |
| 1079 | 1149 | const raw_decl_name = file.zir.nullTerminatedString(decl_name_index); |
| 1080 | 1150 | if (raw_decl_name.len == 0) { |
| ... | ... | @@ -1095,7 +1165,7 @@ fn walkDecls( |
| 1095 | 1165 | const idx = self.ast_nodes.items.len; |
| 1096 | 1166 | try self.ast_nodes.append(self.arena, .{ |
| 1097 | 1167 | .file = 0, |
| 1098 | | .line = 0, |
| 1168 | .line = line, |
| 1099 | 1169 | .col = 0, |
| 1100 | 1170 | .docs = doc_comment, |
| 1101 | 1171 | .fields = null, // walkInstruction will fill `fields` if necessary |
| ... | ... | @@ -1388,3 +1458,10 @@ fn walkResultToTypeRef(wr: DocData.WalkResult) DocData.TypeRef { |
| 1388 | 1458 | //fn collectParamInfo(self: *Autodoc, file: *File, scope: *Scope, inst_idx: Zir.Index) void { |
| 1389 | 1459 | |
| 1390 | 1460 | //} |
| 1461 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { |
| 1462 | const data = zir.instructions.items(.data); |
| 1463 | const pl_node = data[inst_index].pl_node; |
| 1464 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 1465 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; |
| 1466 | return data[break_index].@"break".operand; |
| 1467 | } |