Skip to content

Commit

Permalink
selectionRange: include function parameters in the result
Browse files Browse the repository at this point in the history
  • Loading branch information
matklad committed Jan 14, 2024
1 parent abe83cf commit b5c756c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
29 changes: 26 additions & 3 deletions src/features/selection_range.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const std = @import("std");
const Ast = std.zig.Ast;

const DocumentStore = @import("../DocumentStore.zig");
const ast = @import("../ast.zig");
const types = @import("../lsp.zig");
const offsets = @import("../offsets.zig");

Expand All @@ -24,11 +25,33 @@ pub fn generateSelectionRanges(
const index = offsets.positionToIndex(handle.tree.source, position, offset_encoding);

locs.clearRetainingCapacity();
for (0..handle.tree.nodes.len) |i| {
for (0..handle.tree.nodes.len, handle.tree.nodes.items(.tag)) |i, tag| {
const node = @as(Ast.Node.Index, @intCast(i));
const loc = offsets.nodeToLoc(handle.tree, node);
if (loc.start <= index and index <= loc.end) {
try locs.append(arena, loc);

if (!(loc.start <= index and index <= loc.end)) continue;

try locs.append(arena, loc);
switch (tag) {
// Function parameters are not stored in the AST explicitly, iterate over them
// manually.
.fn_proto, .fn_proto_multi, .fn_proto_one, .fn_proto_simple => {
var buffer: [1]Ast.Node.Index = undefined;
const fn_proto = handle.tree.fullFnProto(&buffer, node).?;
var it = fn_proto.iterate(&handle.tree);

while (ast.nextFnParam(&it)) |param| {
const loc = offsets.tokensToLoc(
handle.tree,
ast.paramFirstToken(handle.tree, param),
ast.paramLastToken(handle.tree, param),
);
if (loc.start <= index and index <= loc.end) {
try locs.append(arena, loc);
}
}
},
else => {},
}
}

Expand Down
10 changes: 9 additions & 1 deletion tests/lsp_features/selection_range.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@ test "selectionRange - empty" {
try testSelectionRange("<>", &.{});
}

test "seletionRange - smoke" {
test "selectionRange - smoke" {
try testSelectionRange(
\\fn main() void {
\\ const x = 1 <>+ 1;
\\}
, &.{ "1 + 1", "const x = 1 + 1", "{\n const x = 1 + 1;\n}" });
}

test "selectionRange - function parameter" {
try testSelectionRange(
\\fn f(x: i32, y: <>struct {}, z: f32) void {
\\
\\}
, &.{ "struct {}", "y: struct {}", "fn f(x: i32, y: struct {}, z: f32) void" });
}

fn testSelectionRange(source: []const u8, want: []const []const u8) !void {
var phr = try helper.collectClearPlaceholders(allocator, source);
defer phr.deinit(allocator);
Expand Down

0 comments on commit b5c756c

Please sign in to comment.