| ... | @@ -567,6 +567,28 @@ pub const Wip = struct { | ... | @@ -567,6 +567,28 @@ pub const Wip = struct { |
| 567 | if (index == .none) return .none; | 567 | if (index == .none) return .none; |
| 568 | const other_sl = other.getSourceLocation(index); | 568 | const other_sl = other.getSourceLocation(index); |
| 569 | | 569 | |
| | 570 | var ref_traces: std.ArrayListUnmanaged(ReferenceTrace) = .{}; |
| | 571 | defer ref_traces.deinit(wip.gpa); |
| | 572 | |
| | 573 | if (other_sl.reference_trace_len > 0) { |
| | 574 | var ref_index = other.extraData(SourceLocation, @intFromEnum(index)).end; |
| | 575 | for (0..other_sl.reference_trace_len) |_| { |
| | 576 | const other_ref_trace_ed = other.extraData(ReferenceTrace, ref_index); |
| | 577 | const other_ref_trace = other_ref_trace_ed.data; |
| | 578 | ref_index = other_ref_trace_ed.end; |
| | 579 | |
| | 580 | const ref_trace: ReferenceTrace = if (other_ref_trace.src_loc == .none) .{ |
| | 581 | // sentinel ReferenceTrace does not store a string index in decl_name |
| | 582 | .decl_name = other_ref_trace.decl_name, |
| | 583 | .src_loc = .none, |
| | 584 | } else .{ |
| | 585 | .decl_name = try wip.addString(other.nullTerminatedString(other_ref_trace.decl_name)), |
| | 586 | .src_loc = try wip.addOtherSourceLocation(other, other_ref_trace.src_loc), |
| | 587 | }; |
| | 588 | try ref_traces.append(wip.gpa, ref_trace); |
| | 589 | } |
| | 590 | } |
| | 591 | |
| 570 | const src_loc = try wip.addSourceLocation(.{ | 592 | const src_loc = try wip.addSourceLocation(.{ |
| 571 | .src_path = try wip.addString(other.nullTerminatedString(other_sl.src_path)), | 593 | .src_path = try wip.addString(other.nullTerminatedString(other_sl.src_path)), |
| 572 | .line = other_sl.line, | 594 | .line = other_sl.line, |
| ... | @@ -581,7 +603,9 @@ pub const Wip = struct { | ... | @@ -581,7 +603,9 @@ pub const Wip = struct { |
| 581 | .reference_trace_len = other_sl.reference_trace_len, | 603 | .reference_trace_len = other_sl.reference_trace_len, |
| 582 | }); | 604 | }); |
| 583 | | 605 | |
| 584 | // TODO: also add the reference trace | 606 | for (ref_traces.items) |ref_trace| { |
| | 607 | try wip.addReferenceTrace(ref_trace); |
| | 608 | } |
| 585 | | 609 | |
| 586 | return src_loc; | 610 | return src_loc; |
| 587 | } | 611 | } |
| ... | @@ -615,3 +639,95 @@ pub const Wip = struct { | ... | @@ -615,3 +639,95 @@ pub const Wip = struct { |
| 615 | } | 639 | } |
| 616 | } | 640 | } |
| 617 | }; | 641 | }; |
| | 642 | |
| | 643 | test "addBundleAsRoots" { |
| | 644 | var bundle = bundle: { |
| | 645 | var wip: ErrorBundle.Wip = undefined; |
| | 646 | try wip.init(std.testing.allocator); |
| | 647 | errdefer wip.deinit(); |
| | 648 | |
| | 649 | var ref_traces: [3]ReferenceTrace = undefined; |
| | 650 | for (&ref_traces, 0..) |*ref_trace, i| { |
| | 651 | if (i == ref_traces.len - 1) { |
| | 652 | // sentinel reference trace |
| | 653 | ref_trace.* = .{ |
| | 654 | .decl_name = 3, // signifies 3 hidden references |
| | 655 | .src_loc = .none, |
| | 656 | }; |
| | 657 | } else { |
| | 658 | ref_trace.* = .{ |
| | 659 | .decl_name = try wip.addString("foo"), |
| | 660 | .src_loc = try wip.addSourceLocation(.{ |
| | 661 | .src_path = try wip.addString("foo"), |
| | 662 | .line = 1, |
| | 663 | .column = 2, |
| | 664 | .span_start = 3, |
| | 665 | .span_main = 4, |
| | 666 | .span_end = 5, |
| | 667 | .source_line = 0, |
| | 668 | }), |
| | 669 | }; |
| | 670 | } |
| | 671 | } |
| | 672 | |
| | 673 | const src_loc = try wip.addSourceLocation(.{ |
| | 674 | .src_path = try wip.addString("foo"), |
| | 675 | .line = 1, |
| | 676 | .column = 2, |
| | 677 | .span_start = 3, |
| | 678 | .span_main = 4, |
| | 679 | .span_end = 5, |
| | 680 | .source_line = try wip.addString("some source code"), |
| | 681 | .reference_trace_len = ref_traces.len, |
| | 682 | }); |
| | 683 | for (&ref_traces) |ref_trace| { |
| | 684 | try wip.addReferenceTrace(ref_trace); |
| | 685 | } |
| | 686 | |
| | 687 | try wip.addRootErrorMessage(ErrorMessage{ |
| | 688 | .msg = try wip.addString("hello world"), |
| | 689 | .src_loc = src_loc, |
| | 690 | .notes_len = 1, |
| | 691 | }); |
| | 692 | const i = try wip.reserveNotes(1); |
| | 693 | const note_index = @intFromEnum(wip.addErrorMessageAssumeCapacity(.{ |
| | 694 | .msg = try wip.addString("this is a note"), |
| | 695 | .src_loc = try wip.addSourceLocation(.{ |
| | 696 | .src_path = try wip.addString("bar"), |
| | 697 | .line = 1, |
| | 698 | .column = 2, |
| | 699 | .span_start = 3, |
| | 700 | .span_main = 4, |
| | 701 | .span_end = 5, |
| | 702 | .source_line = try wip.addString("another line of source"), |
| | 703 | }), |
| | 704 | })); |
| | 705 | wip.extra.items[i] = note_index; |
| | 706 | |
| | 707 | break :bundle try wip.toOwnedBundle(""); |
| | 708 | }; |
| | 709 | defer bundle.deinit(std.testing.allocator); |
| | 710 | |
| | 711 | const ttyconf: std.io.tty.Config = .no_color; |
| | 712 | |
| | 713 | var bundle_buf = std.ArrayList(u8).init(std.testing.allocator); |
| | 714 | defer bundle_buf.deinit(); |
| | 715 | try bundle.renderToWriter(.{ .ttyconf = ttyconf }, bundle_buf.writer()); |
| | 716 | |
| | 717 | var copy = copy: { |
| | 718 | var wip: ErrorBundle.Wip = undefined; |
| | 719 | try wip.init(std.testing.allocator); |
| | 720 | errdefer wip.deinit(); |
| | 721 | |
| | 722 | try wip.addBundleAsRoots(bundle); |
| | 723 | |
| | 724 | break :copy try wip.toOwnedBundle(""); |
| | 725 | }; |
| | 726 | defer copy.deinit(std.testing.allocator); |
| | 727 | |
| | 728 | var copy_buf = std.ArrayList(u8).init(std.testing.allocator); |
| | 729 | defer copy_buf.deinit(); |
| | 730 | try copy.renderToWriter(.{ .ttyconf = ttyconf }, copy_buf.writer()); |
| | 731 | |
| | 732 | try std.testing.expectEqualStrings(bundle_buf.items, copy_buf.items); |
| | 733 | } |