| ... | @@ -252,6 +252,8 @@ const DocData = struct { | ... | @@ -252,6 +252,8 @@ const DocData = struct { |
| 252 | src: usize, // index into astNodes | 252 | src: usize, // index into astNodes |
| 253 | // typeRef: TypeRef, | 253 | // typeRef: TypeRef, |
| 254 | value: WalkResult, | 254 | value: WalkResult, |
| | 255 | // The index in astNodes of the `test declname { }` node |
| | 256 | decltest: ?usize = null, |
| 255 | }; | 257 | }; |
| 256 | | 258 | |
| 257 | const AstNode = struct { | 259 | const AstNode = struct { |
| ... | @@ -610,11 +612,7 @@ fn walkInstruction( | ... | @@ -610,11 +612,7 @@ fn walkInstruction( |
| 610 | //return self.walkRef(file, parent_scope, break_operand); | 612 | //return self.walkRef(file, parent_scope, break_operand); |
| 611 | //}, | 613 | //}, |
| 612 | .block_inline => { | 614 | .block_inline => { |
| 613 | const pl_node = data[inst_index].pl_node; | 615 | return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index)); |
| 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); | | |
| 618 | }, | 616 | }, |
| 619 | .func => { | 617 | .func => { |
| 620 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); | 618 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); |
| ... | @@ -947,13 +945,17 @@ fn walkInstruction( | ... | @@ -947,13 +945,17 @@ fn walkInstruction( |
| 947 | // Done to make sure that all decl refs can be resolved correctly, | 945 | // Done to make sure that all decl refs can be resolved correctly, |
| 948 | // even if we haven't fully analyzed the decl yet. | 946 | // even if we haven't fully analyzed the decl yet. |
| 949 | { | 947 | { |
| | 948 | var actual_decls_len: usize = 0; |
| 950 | var it = file.zir.declIterator(@intCast(u32, inst_index)); | 949 | var it = file.zir.declIterator(@intCast(u32, inst_index)); |
| 951 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); | | |
| 952 | var decls_slot_index = decls_first_index; | 950 | var decls_slot_index = decls_first_index; |
| 953 | while (it.next()) |d| : (decls_slot_index += 1) { | 951 | while (it.next()) |d| : (decls_slot_index += 1) { |
| 954 | const decl_name_index = file.zir.extra[d.sub_index + 5]; | 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 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); | 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 | extra_index = try self.walkDecls( | 961 | extra_index = try self.walkDecls( |
| ... | @@ -1042,7 +1044,7 @@ fn walkDecls( | ... | @@ -1042,7 +1044,7 @@ fn walkDecls( |
| 1042 | | 1044 | |
| 1043 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; | 1045 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; |
| 1044 | extra_index += 4; | 1046 | extra_index += 4; |
| 1045 | // const line = file.zir.extra[extra_index]; | 1047 | const line = file.zir.extra[extra_index]; |
| 1046 | extra_index += 1; | 1048 | extra_index += 1; |
| 1047 | const decl_name_index = file.zir.extra[extra_index]; | 1049 | const decl_name_index = file.zir.extra[extra_index]; |
| 1048 | extra_index += 1; | 1050 | extra_index += 1; |
| ... | @@ -1075,6 +1077,74 @@ fn walkDecls( | ... | @@ -1075,6 +1077,74 @@ fn walkDecls( |
| 1075 | break :blk if (is_exported) "usingnamespace" else "comptime"; | 1077 | break :blk if (is_exported) "usingnamespace" else "comptime"; |
| 1076 | } else if (decl_name_index == 1) { | 1078 | } else if (decl_name_index == 1) { |
| 1077 | break :blk "test"; | 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 | } else { | 1148 | } else { |
| 1079 | const raw_decl_name = file.zir.nullTerminatedString(decl_name_index); | 1149 | const raw_decl_name = file.zir.nullTerminatedString(decl_name_index); |
| 1080 | if (raw_decl_name.len == 0) { | 1150 | if (raw_decl_name.len == 0) { |
| ... | @@ -1095,7 +1165,7 @@ fn walkDecls( | ... | @@ -1095,7 +1165,7 @@ fn walkDecls( |
| 1095 | const idx = self.ast_nodes.items.len; | 1165 | const idx = self.ast_nodes.items.len; |
| 1096 | try self.ast_nodes.append(self.arena, .{ | 1166 | try self.ast_nodes.append(self.arena, .{ |
| 1097 | .file = 0, | 1167 | .file = 0, |
| 1098 | .line = 0, | 1168 | .line = line, |
| 1099 | .col = 0, | 1169 | .col = 0, |
| 1100 | .docs = doc_comment, | 1170 | .docs = doc_comment, |
| 1101 | .fields = null, // walkInstruction will fill `fields` if necessary | 1171 | .fields = null, // walkInstruction will fill `fields` if necessary |
| ... | @@ -1388,3 +1458,10 @@ fn walkResultToTypeRef(wr: DocData.WalkResult) DocData.TypeRef { | ... | @@ -1388,3 +1458,10 @@ fn walkResultToTypeRef(wr: DocData.WalkResult) DocData.TypeRef { |
| 1388 | //fn collectParamInfo(self: *Autodoc, file: *File, scope: *Scope, inst_idx: Zir.Index) void { | 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 | } |