const std = @import("std"); const mem = std.mem; const zls = @import("zls"); const builtin = @import("builtin"); const helper = @import("../helper.zig"); const Context = @import("../context.zig").Context; const ErrorBuilder = @import("../ErrorBuilder.zig"); const types = zls.types; const offsets = zls.offsets; const requests = zls.requests; const allocator: std.mem.Allocator = std.testing.allocator; test "definition - smoke" { try testDefinition( \\fn main() void { f<>oo(); } \\fn foo() void {} ); } test "definition - cursor is at the end of an identifier" { try testDefinition( \\fn main() void { foo<>(); } \\fn foo() void {} ); } test "definition - cursor is at the start of an identifier" { try testDefinition( \\fn main() void { <>foo(); } \\fn foo() void {} ); } fn testDefinition(source: []const u8) !void { var phr = try helper.collectClearPlaceholders(allocator, source); defer phr.deinit(allocator); var cursor: offsets.Loc = .{ .start = 0, .end = 0 }; var def_start: offsets.Loc = .{ .start = 0, .end = 0 }; var def_end: offsets.Loc = .{ .start = 0, .end = 0 }; for (phr.locations.items(.old), phr.locations.items(.new)) |old, new| { if (mem.eql(u8, source[old.start..old.end], "<>")) cursor = new; if (mem.eql(u8, source[old.start..old.end], "")) def_start = new; if (mem.eql(u8, source[old.start..old.end], "")) def_end = new; } const cursor_lsp = offsets.locToRange(phr.new_source, cursor, .@"utf-16").start; const def_range_lsp = offsets.locToRange(phr.new_source, .{ .start = def_start.end, .end = def_end.start }, .@"utf-16"); var ctx = try Context.init(); defer ctx.deinit(); const test_uri = try ctx.addDocument(phr.new_source); const params = types.TextDocumentPositionParams{ .textDocument = .{ .uri = test_uri }, .position = cursor_lsp, }; const response = try ctx.requestGetResponse(?types.Location, "textDocument/definition", params); const result = response.result orelse return error.UnresolvedDefinition; try std.testing.expectEqual(def_range_lsp, result.range); }