Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add enable_insert_helpers configuration option #1870

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/// Enables snippet completions when the client also supports them
enable_snippets: bool = true,

/// Whether or not to add things like parenthesis to completions
enable_insert_helpers: bool = false,

/// Whether to enable function argument placeholder completions
enable_argument_placeholders: bool = true,

Expand Down
34 changes: 24 additions & 10 deletions src/features/completions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ fn nodeToCompletion(

const func_name = orig_name orelse tree.tokenSlice(name_token);
const use_snippets = builder.server.config.enable_snippets and builder.server.client_capabilities.supports_snippets;
const use_insert_helpers = builder.server.config.enable_insert_helpers;

const func_ty = Analyser.Type{
.data = .{ .other = .{ .node = node, .handle = handle } }, // this assumes that function types can only be Ast nodes
Expand All @@ -266,23 +267,31 @@ fn nodeToCompletion(
.include_name = true,
.override_name = func_name,
.skip_first_param = skip_self_param,
.parameters = .{ .show = .{
.include_modifiers = true,
.include_names = true,
.include_types = true,
} },
.parameters = .{
.show = .{
.include_modifiers = true,
.include_names = true,
.include_types = true,
},
},
.include_return_type = false,
.snippet_placeholders = true,
})});
}

switch (func.ast.params.len) {
// No arguments, leave cursor at the end
0 => break :blk try std.fmt.allocPrint(builder.arena, "{s}()", .{func_name}),
0 => if (use_insert_helpers)
break :blk try std.fmt.allocPrint(builder.arena, "{s}()", .{func_name})
else
break :blk try std.fmt.allocPrint(builder.arena, "{s}", .{func_name}),
1 => {
if (skip_self_param) {
// The one argument is a self parameter, leave cursor at the end
break :blk try std.fmt.allocPrint(builder.arena, "{s}()", .{func_name});
if (use_insert_helpers)
break :blk try std.fmt.allocPrint(builder.arena, "{s}()", .{func_name})
else
break :blk try std.fmt.allocPrint(builder.arena, "{s}", .{func_name});
}

// Non-self parameter, leave the cursor in the parentheses
Expand Down Expand Up @@ -797,7 +806,7 @@ fn completeFileSystemStringLiteral(builder: *Builder, pos_context: Analyser.Posi
.label = try builder.arena.dupe(u8, entry.name),
.detail = if (pos_context == .cinclude_string_literal) path else null,
.insertText = if (entry.kind == .directory)
try std.fmt.allocPrint(builder.arena, "{s}/", .{entry.name})
try std.fmt.allocPrint(builder.arena, "{s}", .{entry.name})
else
null,
.kind = if (entry.kind == .file) .File else .Folder,
Expand Down Expand Up @@ -1247,6 +1256,7 @@ pub fn collectContainerFields(
container: Analyser.Type,
) error{OutOfMemory}!void {
const use_snippets = builder.server.config.enable_snippets and builder.server.client_capabilities.supports_snippets;
const use_insert_helpers = builder.server.config.enable_insert_helpers;
const node_handle = switch (container.data) {
.other => |n| n,
else => return,
Expand All @@ -1265,8 +1275,10 @@ pub fn collectContainerFields(
.detail = Analyser.getContainerFieldSignature(handle.tree, field),
.insertText = if (use_snippets)
try std.fmt.allocPrint(builder.arena, "{{ .{s} = $1 }}$0", .{name})
else if (use_insert_helpers)
try std.fmt.allocPrint(builder.arena, "{{ .{s} = ", .{name})
else
try std.fmt.allocPrint(builder.arena, "{{ .{s} = ", .{name}),
name,
.insertTextFormat = if (use_snippets) .Snippet else .PlainText,
});
} else try builder.completions.append(builder.arena, .{
Expand All @@ -1275,8 +1287,10 @@ pub fn collectContainerFields(
.detail = Analyser.getContainerFieldSignature(handle.tree, field),
.insertText = if (field.ast.tuple_like or likely == .enum_comparison or likely == .switch_case)
name
else if (use_insert_helpers)
try std.fmt.allocPrint(builder.arena, "{s} = ", .{name})
else
try std.fmt.allocPrint(builder.arena, "{s} = ", .{name}),
name,
});
}
}
Expand Down
24 changes: 24 additions & 0 deletions tests/lsp_features/completion.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2636,6 +2636,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",

.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2658,6 +2660,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "S.f()",
.expected_replace_line = "S.f()",

.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2670,6 +2674,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",

.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2682,6 +2688,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",

.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2694,6 +2702,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",

.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2706,6 +2716,8 @@ test "insert replace behaviour - function 'self parameter' detection" {
.label = "f",
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",

.enable_insert_helpers = true,
});
}

Expand Down Expand Up @@ -2754,6 +2766,7 @@ test "insert replace behaviour - function with snippets" {
.expected_insert_line = "S.f(${1:self: S})",
.expected_replace_line = "S.f(${1:self: S})",
.enable_snippets = true,
.enable_insert_helpers = true,
.enable_argument_placeholders = true,
});
try testCompletionTextEdit(.{
Expand All @@ -2768,6 +2781,7 @@ test "insert replace behaviour - function with snippets" {
.expected_insert_line = "s.f(${1:number: u32})",
.expected_replace_line = "s.f(${1:number: u32})",
.enable_snippets = true,
.enable_insert_helpers = true,
.enable_argument_placeholders = true,
});
try testCompletionTextEdit(.{
Expand All @@ -2782,6 +2796,7 @@ test "insert replace behaviour - function with snippets" {
.expected_insert_line = "s.f()",
.expected_replace_line = "s.f()",
.enable_snippets = true,
.enable_insert_helpers = true,
.enable_argument_placeholders = false,
});
try testCompletionTextEdit(.{
Expand All @@ -2795,6 +2810,7 @@ test "insert replace behaviour - function with snippets" {
.expected_insert_line = "S.f(${1:})",
.expected_replace_line = "S.f(${1:})",
.enable_snippets = true,
.enable_insert_helpers = true,
.enable_argument_placeholders = false,
});

Expand Down Expand Up @@ -2859,6 +2875,7 @@ test "insert replace behaviour - function alias" {
.label = "alias",
.expected_insert_line = "const foo = alias();",
.expected_replace_line = "const foo = alias();",
.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2870,6 +2887,7 @@ test "insert replace behaviour - function alias" {
.expected_insert_line = "const foo = alias();",
.expected_replace_line = "const foo = alias();",
.enable_snippets = true,
.enable_insert_helpers = true,
.enable_argument_placeholders = true,
});
}
Expand All @@ -2883,6 +2901,7 @@ test "insert replace behaviour - struct literal" {
.label = "alpha",
.expected_insert_line = "const foo: S = .{ .alpha = ",
.expected_replace_line = "const foo: S = .{ .alpha = ",
.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand All @@ -2893,6 +2912,7 @@ test "insert replace behaviour - struct literal" {
.expected_insert_line = "const foo: S = .{ .alpha = $1 }$0",
.expected_replace_line = "const foo: S = .{ .alpha = $1 }$0",
.enable_snippets = true,
.enable_insert_helpers = true,
});
}

Expand All @@ -2906,6 +2926,7 @@ test "insert replace behaviour - tagged union" {
.label = "alpha",
.expected_insert_line = "const foo: U = .{ .alpha = $1 }$0",
.expected_replace_line = "const foo: U = .{ .alpha = $1 }$0",
.enable_insert_helpers = true,
.enable_snippets = true,
});
try testCompletionTextEdit(.{
Expand All @@ -2917,6 +2938,7 @@ test "insert replace behaviour - tagged union" {
.label = "alpha",
.expected_insert_line = "const foo: U = .{ .alpha = ",
.expected_replace_line = "const foo: U = .{ .alpha = ",
.enable_insert_helpers = true,
});
try testCompletionTextEdit(.{
.source =
Expand Down Expand Up @@ -3279,6 +3301,7 @@ fn testCompletionTextEdit(

enable_argument_placeholders: bool = false,
enable_snippets: bool = false,
enable_insert_helpers: bool = false,
},
) !void {
const cursor_idx = std.mem.indexOf(u8, options.source, "<cursor>").?;
Expand All @@ -3300,6 +3323,7 @@ fn testCompletionTextEdit(

ctx.server.config.enable_argument_placeholders = options.enable_argument_placeholders;
ctx.server.config.enable_snippets = options.enable_snippets;
ctx.server.config.enable_insert_helpers = options.enable_insert_helpers;

const test_uri = try ctx.addDocument(text);
const handle = ctx.server.document_store.getHandle(test_uri).?;
Expand Down