add multi-file support to ErrorBuilder
colorize ErrorBuilder output
This commit is contained in:
@@ -190,7 +190,7 @@ test "completion - captures" {
|
||||
, &.{
|
||||
.{ .label = "alpha", .kind = .Field, .detail = "alpha: u32" },
|
||||
});
|
||||
|
||||
|
||||
try testCompletion(
|
||||
\\const S = struct { alpha: u32 };
|
||||
\\fn foo(items: [2]S) void {
|
||||
@@ -452,10 +452,12 @@ fn testCompletion(source: []const u8, expected_completions: []const Completion)
|
||||
var unexpected = try set_difference(actual, expected);
|
||||
defer unexpected.deinit(allocator);
|
||||
|
||||
var error_builder = ErrorBuilder.init(allocator, text);
|
||||
var error_builder = ErrorBuilder.init(allocator);
|
||||
defer error_builder.deinit();
|
||||
errdefer error_builder.writeDebug();
|
||||
|
||||
try error_builder.addFile(test_uri, text);
|
||||
|
||||
for (found.keys()) |label| {
|
||||
const actual_completion: types.CompletionItem = blk: {
|
||||
for (completion_list.items) |item| {
|
||||
@@ -472,7 +474,7 @@ fn testCompletion(source: []const u8, expected_completions: []const Completion)
|
||||
};
|
||||
|
||||
if (actual_completion.kind == null or expected_completion.kind != actual_completion.kind.?) {
|
||||
try error_builder.msgAtIndex("label '{s}' should be of kind '{s}' but was '{?s}'!", cursor_idx, .err, .{
|
||||
try error_builder.msgAtIndex("label '{s}' should be of kind '{s}' but was '{?s}'!", test_uri, cursor_idx, .err, .{
|
||||
label,
|
||||
@tagName(expected_completion.kind),
|
||||
if (actual_completion.kind) |kind| @tagName(kind) else null,
|
||||
@@ -483,7 +485,7 @@ fn testCompletion(source: []const u8, expected_completions: []const Completion)
|
||||
if (expected_completion.detail == null) continue;
|
||||
if (actual_completion.detail != null and std.mem.eql(u8, expected_completion.detail.?, actual_completion.detail.?)) continue;
|
||||
|
||||
try error_builder.msgAtIndex("label '{s}' should have detail '{?s}' but was '{?s}'!", cursor_idx, .err, .{
|
||||
try error_builder.msgAtIndex("label '{s}' should have detail '{?s}' but was '{?s}'!", test_uri, cursor_idx, .err, .{
|
||||
label,
|
||||
expected_completion.detail,
|
||||
actual_completion.detail,
|
||||
@@ -499,7 +501,7 @@ fn testCompletion(source: []const u8, expected_completions: []const Completion)
|
||||
try printLabels(out, found, "found");
|
||||
try printLabels(out, missing, "missing");
|
||||
try printLabels(out, unexpected, "unexpected");
|
||||
try error_builder.msgAtIndex("invalid completions\n{s}", cursor_idx, .err, .{buffer.items});
|
||||
try error_builder.msgAtIndex("invalid completions\n{s}", test_uri, cursor_idx, .err, .{buffer.items});
|
||||
return error.InvalidCompletions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,10 +98,12 @@ fn testInlayHints(source: []const u8) !void {
|
||||
return error.InvalidResponse;
|
||||
};
|
||||
|
||||
var error_builder = ErrorBuilder.init(allocator, phr.new_source);
|
||||
var error_builder = ErrorBuilder.init(allocator);
|
||||
defer error_builder.deinit();
|
||||
errdefer error_builder.writeDebug();
|
||||
|
||||
try error_builder.addFile(test_uri, phr.new_source);
|
||||
|
||||
var i: usize = 0;
|
||||
outer: while (i < phr.locations.len) : (i += 1) {
|
||||
const old_loc = phr.locations.items(.old)[i];
|
||||
@@ -116,20 +118,20 @@ fn testInlayHints(source: []const u8) !void {
|
||||
if (position.line != hint.position.line or position.character != hint.position.character) continue;
|
||||
|
||||
if (!std.mem.endsWith(u8, hint.label, ":")) {
|
||||
try error_builder.msgAtLoc("label `{s}` must end with a colon!", new_loc, .err, .{hint.label});
|
||||
try error_builder.msgAtLoc("label `{s}` must end with a colon!", test_uri, new_loc, .err, .{hint.label});
|
||||
}
|
||||
const actual_label = hint.label[0 .. hint.label.len - 1];
|
||||
|
||||
if (!std.mem.eql(u8, expected_label, actual_label)) {
|
||||
try error_builder.msgAtLoc("expected label `{s}` here but got `{s}`!", new_loc, .err, .{ expected_label, actual_label });
|
||||
try error_builder.msgAtLoc("expected label `{s}` here but got `{s}`!", test_uri, new_loc, .err, .{ expected_label, actual_label });
|
||||
}
|
||||
if (hint.kind != types.InlayHintKind.Parameter) {
|
||||
try error_builder.msgAtLoc("hint kind should be `{s}` but got `{s}`!", new_loc, .err, .{ @tagName(types.InlayHintKind.Parameter), @tagName(hint.kind) });
|
||||
try error_builder.msgAtLoc("hint kind should be `{s}` but got `{s}`!", test_uri, new_loc, .err, .{ @tagName(types.InlayHintKind.Parameter), @tagName(hint.kind) });
|
||||
}
|
||||
|
||||
continue :outer;
|
||||
}
|
||||
try error_builder.msgAtLoc("expected hint `{s}` here", new_loc, .err, .{expected_label});
|
||||
try error_builder.msgAtLoc("expected hint `{s}` here", test_uri, new_loc, .err, .{expected_label});
|
||||
}
|
||||
|
||||
if (error_builder.hasMessages()) return error.InvalidResponse;
|
||||
|
||||
@@ -148,14 +148,16 @@ fn testReferences(source: []const u8) !void {
|
||||
|
||||
const response = try ctx.requestGetResponse(?[]types.Location, "textDocument/references", params);
|
||||
|
||||
var error_builder = ErrorBuilder.init(allocator, phr.new_source);
|
||||
var error_builder = ErrorBuilder.init(allocator);
|
||||
defer error_builder.deinit();
|
||||
errdefer {
|
||||
const note_loc = phr.locations.items(.new)[i];
|
||||
error_builder.msgAtLoc("asked for references here", note_loc, .info, .{}) catch {};
|
||||
error_builder.msgAtLoc("asked for references here", file_uri, note_loc, .info, .{}) catch {};
|
||||
error_builder.writeDebug();
|
||||
}
|
||||
|
||||
try error_builder.addFile(file_uri, phr.new_source);
|
||||
|
||||
const locations: []types.Location = response.result orelse {
|
||||
std.debug.print("Server returned `null` as the result\n", .{});
|
||||
return error.InvalidResponse;
|
||||
@@ -200,12 +202,12 @@ fn testReferences(source: []const u8) !void {
|
||||
if (expected_loc.end != actual_loc.end) continue;
|
||||
break :found_index idx;
|
||||
}
|
||||
try error_builder.msgAtLoc("server returned unexpected reference!", actual_loc, .err, .{});
|
||||
try error_builder.msgAtLoc("server returned unexpected reference!", file_uri, actual_loc, .err, .{});
|
||||
return error.UnexpectedReference;
|
||||
};
|
||||
|
||||
if (visited.isSet(index)) {
|
||||
try error_builder.msgAtLoc("server returned duplicate reference!", actual_loc, .err, .{});
|
||||
try error_builder.msgAtLoc("server returned duplicate reference!", file_uri, actual_loc, .err, .{});
|
||||
return error.DuplicateReference;
|
||||
} else {
|
||||
visited.set(index);
|
||||
@@ -215,7 +217,7 @@ fn testReferences(source: []const u8) !void {
|
||||
var has_unvisited = false;
|
||||
var unvisited_it = visited.iterator(.{ .kind = .unset });
|
||||
while (unvisited_it.next()) |index| {
|
||||
try error_builder.msgAtLoc("expected reference here!", expected_locs[index], .err, .{});
|
||||
try error_builder.msgAtLoc("expected reference here!", file_uri, expected_locs[index], .err, .{});
|
||||
has_unvisited = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -975,17 +975,19 @@ fn testSemanticTokens(source: [:0]const u8, expected_tokens: []const TokenData)
|
||||
const actual = response.result.data;
|
||||
try std.testing.expect(actual.len % 5 == 0); // every token is represented by 5 integers
|
||||
|
||||
var error_builder = ErrorBuilder.init(allocator, source);
|
||||
var error_builder = ErrorBuilder.init(allocator);
|
||||
defer error_builder.deinit();
|
||||
errdefer error_builder.writeDebug();
|
||||
|
||||
try error_builder.addFile(uri, source);
|
||||
|
||||
var token_it = std.mem.window(u32, actual, 5, 5);
|
||||
var position: types.Position = .{ .line = 0, .character = 0 };
|
||||
var last_token_end: usize = 0;
|
||||
|
||||
for (expected_tokens) |expected_token| {
|
||||
const token_data = token_it.next() orelse {
|
||||
try error_builder.msgAtIndex("expected a `{s}` token here", last_token_end, .err, .{expected_token.@"0"});
|
||||
try error_builder.msgAtIndex("expected a `{s}` token here", uri, last_token_end, .err, .{expected_token.@"0"});
|
||||
return error.ExpectedToken;
|
||||
};
|
||||
|
||||
@@ -1012,13 +1014,13 @@ fn testSemanticTokens(source: [:0]const u8, expected_tokens: []const TokenData)
|
||||
const expected_token_modifiers = expected_token.@"2";
|
||||
|
||||
if (!std.mem.eql(u8, expected_token_source, token_source)) {
|
||||
try error_builder.msgAtLoc("expected `{s}` as the next token but got `{s}` here", token_loc, .err, .{ expected_token_source, token_source });
|
||||
try error_builder.msgAtLoc("expected `{s}` as the next token but got `{s}` here", uri, token_loc, .err, .{ expected_token_source, token_source });
|
||||
return error.UnexpectedTokenContent;
|
||||
} else if (expected_token_type != token_type) {
|
||||
try error_builder.msgAtLoc("expected token type `{s}` but got `{s}`", token_loc, .err, .{ @tagName(expected_token_type), @tagName(token_type) });
|
||||
try error_builder.msgAtLoc("expected token type `{s}` but got `{s}`", uri, token_loc, .err, .{ @tagName(expected_token_type), @tagName(token_type) });
|
||||
return error.UnexpectedTokenType;
|
||||
} else if (!std.meta.eql(expected_token_modifiers, token_modifiers)) {
|
||||
try error_builder.msgAtLoc("expected token modifiers `{}` but got `{}`", token_loc, .err, .{ expected_token_modifiers, token_modifiers });
|
||||
try error_builder.msgAtLoc("expected token modifiers `{}` but got `{}`", uri, token_loc, .err, .{ expected_token_modifiers, token_modifiers });
|
||||
return error.UnexpectedTokenModifiers;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user