Skip to content

Commit

Permalink
textDocument/selectionRange
Browse files Browse the repository at this point in the history
closes #777
  • Loading branch information
matklad committed Nov 26, 2022
1 parent 369b851 commit 1d85b0a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
46 changes: 45 additions & 1 deletion src/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,7 @@ fn initializeHandler(server: *Server, writer: anytype, id: types.RequestId, req:
.documentFormattingProvider = true,
.documentRangeFormattingProvider = false,
.foldingRangeProvider = true,
.selectionRangeProvider = false,
.selectionRangeProvider = true,
.workspaceSymbolProvider = false,
.rangeProvider = false,
.documentProvider = true,
Expand Down Expand Up @@ -2690,6 +2690,49 @@ fn foldingRangeHandler(server: *Server, writer: anytype, id: types.RequestId, re
});
}

fn selectionRangeHandler(server: *Server, writer: anytype, id: types.RequestId, req: requests.SelectionRange) !void {
const Loc = std.zig.Token.Loc;

const allocator = server.arena.allocator();
const handle = server.document_store.getHandle(req.params.textDocument.uri) orelse {
log.warn("Trying to get selection range of non existent document {s}", .{req.params.textDocument.uri});
return try respondGeneric(writer, id, null_result_response);
};

var result = try allocator.alloc(*types.SelectionRange, req.params.positions.len);
var locs = try std.ArrayListUnmanaged(Loc).initCapacity(allocator, 8);
for (req.params.positions) |position, position_index| {
const index = offsets.positionToIndex(handle.text, position, server.offset_encoding);

locs.clearRetainingCapacity();
for (handle.tree.nodes.items(.data)) |_, i| {
const node = @intCast(u32, i);
const loc = offsets.nodeToLoc(handle.tree, node);
if (loc.start <= index and index <= loc.end) {
(try locs.addOne(allocator)).* = loc;
}
}

std.sort.sort(Loc, locs.items, {}, locLessThan);

var selection_ranges = try allocator.alloc(types.SelectionRange, locs.items.len);
for (selection_ranges) |*range, i| {
range.range = offsets.locToRange(handle.text, locs.items[i], server.offset_encoding);
range.parent = if (i + 1 < selection_ranges.len) &selection_ranges[i + 1] else null;
}
result[position_index] = &selection_ranges[0];
}

try send(writer, allocator, types.Response{
.id = id,
.result = .{ .SelectionRange = result },
});
}

fn locLessThan(_: void, lhs: std.zig.Token.Loc, rhs: std.zig.Token.Loc) bool {
return (lhs.end - lhs.start) < (rhs.end - rhs.start);
}

// Needed for the hack seen below.
fn extractErr(val: anytype) anyerror {
val catch |e| return e;
Expand Down Expand Up @@ -2836,6 +2879,7 @@ pub fn processJsonRpc(server: *Server, writer: anytype, json: []const u8) !void
.{ "textDocument/codeAction", requests.CodeAction, codeActionHandler },
.{ "workspace/didChangeConfiguration", Config.DidChangeConfigurationParams, didChangeConfigurationHandler },
.{ "textDocument/foldingRange", requests.FoldingRange, foldingRangeHandler },
.{ "textDocument/selectionRange", requests.SelectionRange, selectionRangeHandler },
};

if (zig_builtin.zig_backend == .stage1) {
Expand Down
7 changes: 7 additions & 0 deletions src/requests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,10 @@ pub const FoldingRange = struct {
textDocument: TextDocumentIdentifier,
},
};

pub const SelectionRange = struct {
params: struct {
textDocument: TextDocumentIdentifier,
positions: []types.Position,
},
};
8 changes: 7 additions & 1 deletion src/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub const ResponseParams = union(enum) {
CodeAction: []CodeAction,
ApplyEdit: ApplyWorkspaceEditParams,
FoldingRange: []FoldingRange,
SelectionRange: []*SelectionRange,
};

pub const Response = struct {
Expand Down Expand Up @@ -525,6 +526,11 @@ pub const DocumentHighlight = struct {
};

pub const FoldingRange = struct {
startLine: usize,
startLine: usize,
endLine: usize,
};

pub const SelectionRange = struct {
range: Range,
parent: ?*SelectionRange,
};

0 comments on commit 1d85b0a

Please sign in to comment.