Skip to content

Commit 695a1d5

Browse files
FnControlOptionTechatrix
authored andcommitted
Deprioritize completions for fields with default value
1 parent 932e621 commit 695a1d5

2 files changed

Lines changed: 70 additions & 18 deletions

File tree

src/features/completions.zig

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -640,21 +640,22 @@ fn completeFieldAccess(builder: *Builder, loc: offsets.Loc) Analyser.Error!void
640640
try typeToCompletion(builder, ty);
641641
}
642642

643-
fn kindToSortScore(kind: types.completion.Item.Kind) []const u8 {
643+
fn kindToSortScore(kind: types.completion.Item.Kind) u4 {
644644
return switch (kind) {
645-
.Operator => "1",
646-
.Field, .EnumMember => "2",
647-
.Method => "3",
648-
.Function => "4",
645+
.Operator => 1,
646+
.Field, .EnumMember => 2,
647+
// Field with default value => 3
648+
.Method => 4,
649+
.Function => 5,
649650
.Text, // used for labels
650651
.Constant,
651652
.Variable,
652653
.Struct,
653654
.Enum,
654655
.TypeParameter,
655-
=> "5",
656-
.Snippet => "6",
657-
.Keyword => "7",
656+
=> 6,
657+
.Snippet => 7,
658+
.Keyword => 8,
658659

659660
// Used for `@import` completions. Must be set in `completeFileSystemStringLiteral`.
660661
.Module => unreachable,
@@ -665,20 +666,24 @@ fn kindToSortScore(kind: types.completion.Item.Kind) []const u8 {
665666
};
666667
}
667668

668-
fn itemSortScore(item: types.completion.Item) []const u8 {
669+
fn itemSortScore(item: types.completion.Item) u4 {
669670
// Completion items have two ways to mark deprecation; we need to check both.
670671
const deprecated: bool = item.deprecated orelse if (item.tags) |tags|
671672
std.mem.findScalar(types.completion.Item.Tag, tags, .Deprecated) != null
672673
else
673674
false;
674675

675676
if (deprecated) {
676-
return "9";
677+
return 9;
677678
} else {
678679
return kindToSortScore(item.kind.?);
679680
}
680681
}
681682

683+
fn generateSortText(allocator: std.mem.Allocator, score: u4, label: []const u8) ![]const u8 {
684+
return try std.fmt.allocPrint(allocator, "{}_{s}", .{ score, label });
685+
}
686+
682687
fn collectUsedMembersSet(builder: *Builder, likely: EnumLiteralContext.Likely, dot_token_index: Ast.TokenIndex) error{OutOfMemory}!std.BufSet {
683688
const tracy_zone = tracy.trace(@src());
684689
defer tracy_zone.end();
@@ -867,7 +872,7 @@ fn completeFileSystemStringLiteral(builder: *Builder, pos_context: Analyser.Posi
867872
.label = name,
868873
.kind = .Module,
869874
.detail = path,
870-
.sortText = "4",
875+
.sortText = try generateSortText(builder.arena, 4, name),
871876
});
872877
}
873878
} else switch (try builder.orig_handle.getAssociatedBuildFile(store)) {
@@ -892,7 +897,7 @@ fn completeFileSystemStringLiteral(builder: *Builder, pos_context: Analyser.Posi
892897
.label = try builder.arena.dupe(u8, name),
893898
.kind = .Module,
894899
.detail = try builder.arena.dupe(u8, root_source_file),
895-
.sortText = "4",
900+
.sortText = try generateSortText(builder.arena, 4, name),
896901
});
897902
}
898903
},
@@ -966,12 +971,14 @@ fn completeFileSystemStringLiteral(builder: *Builder, pos_context: Analyser.Posi
966971
else
967972
label;
968973

974+
const score: u4 = if (entry.kind == .file) 6 else 5;
975+
969976
try builder.completions.append(builder.arena, .{
970977
.label = label,
971978
.kind = if (entry.kind == .file) .File else .Folder,
972979
.detail = if (pos_context == .cinclude_string_literal) path else null,
973980
.textEdit = createTextEdit(builder, .{ .newText = insert_text, .insert = insert_range, .replace = replace_range }),
974-
.sortText = if (entry.kind == .file) "6" else "5",
981+
.sortText = try generateSortText(builder.arena, score, label),
975982
});
976983
} else |err| switch (err) {
977984
error.Canceled => return error.Canceled,
@@ -1051,7 +1058,7 @@ pub fn completionAtIndex(
10511058

10521059
if (item.sortText == null) {
10531060
const score = itemSortScore(item.*);
1054-
item.sortText = try std.fmt.allocPrint(arena, "{s}_{s}", .{ score, item.label });
1061+
item.sortText = try generateSortText(arena, score, item.label);
10551062
}
10561063
}
10571064

@@ -1436,8 +1443,11 @@ fn collectContainerFields(
14361443
=> {
14371444
const field = tree.fullContainerField(decl.ast_node).?;
14381445

1446+
const kind: types.completion.Item.Kind =
1447+
if (field.ast.tuple_like) .EnumMember else .Field;
1448+
14391449
const insert_text, const insert_text_format: types.InsertTextFormat = insert_text: {
1440-
if (likely != .struct_field and likely != .enum_comparison and likely != .switch_case and !field.ast.tuple_like) {
1450+
if (likely != .struct_field and likely != .enum_comparison and likely != .switch_case and kind == .Field) {
14411451
if (container.isTaggedUnion() and
14421452
maybe_resolved_ty != null and
14431453
maybe_resolved_ty.?.data == .ip_index and
@@ -1463,7 +1473,7 @@ fn collectContainerFields(
14631473
if (!builder.use_snippets)
14641474
break :insert_text .{ name, .PlainText };
14651475

1466-
if (field.ast.tuple_like or likely == .enum_comparison or likely == .switch_case)
1476+
if (kind == .EnumMember or likely == .enum_comparison or likely == .switch_case)
14671477
break :insert_text .{ name, .PlainText };
14681478

14691479
const is_following_by_equal_token = switch (offsets.sourceIndexToTokenIndex(&builder.orig_handle.tree, builder.source_index)) {
@@ -1480,15 +1490,18 @@ fn collectContainerFields(
14801490
};
14811491
};
14821492

1493+
var score = kindToSortScore(kind);
1494+
14831495
const detail = detail: {
14841496
const type_str = if (maybe_resolved_ty) |ty|
14851497
try ty.stringifyTypeOf(builder.analyser, .{ .truncate_container_decls = false })
14861498
else if (field.ast.type_expr.unwrap()) |type_expr| typ: {
14871499
const type_str = offsets.nodeToSlice(tree, type_expr);
1488-
if (std.mem.eql(u8, name, type_str) and field.ast.tuple_like) break :detail null;
1500+
if (std.mem.eql(u8, name, type_str) and kind == .EnumMember) break :detail null;
14891501
break :typ type_str;
14901502
} else break :detail null;
14911503
if (field.ast.value_expr.unwrap()) |value_expr| {
1504+
if (kind == .Field) score += 1;
14921505
const value_str = offsets.nodeToSlice(tree, value_expr);
14931506
break :detail try std.fmt.allocPrint(builder.arena, "{s} = {s}", .{ type_str, value_str });
14941507
} else {
@@ -1498,10 +1511,11 @@ fn collectContainerFields(
14981511

14991512
try builder.completions.append(builder.arena, .{
15001513
.label = name,
1501-
.kind = if (field.ast.tuple_like) .EnumMember else .Field,
1514+
.kind = kind,
15021515
.detail = detail,
15031516
.insertTextFormat = insert_text_format,
15041517
.insertText = insert_text,
1518+
.sortText = try generateSortText(builder.arena, score, name),
15051519
});
15061520
},
15071521
.global_var_decl,

tests/lsp_features/completion.zig

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,6 +1643,25 @@ test "enum" {
16431643
});
16441644
}
16451645

1646+
test "enum - explicit and implicit ordinal values" {
1647+
try testCompletionWithOptions(
1648+
\\const E = enum(u8) {
1649+
\\ alpha = 0,
1650+
\\ beta,
1651+
\\ gamma = 3,
1652+
\\ delta,
1653+
\\};
1654+
\\const foo: E = .<cursor>
1655+
, &.{
1656+
.{ .label = "alpha", .kind = .EnumMember },
1657+
.{ .label = "beta", .kind = .EnumMember },
1658+
.{ .label = "delta", .kind = .EnumMember },
1659+
.{ .label = "gamma", .kind = .EnumMember },
1660+
}, .{
1661+
.check_order = true,
1662+
});
1663+
}
1664+
16461665
test "decl literal" {
16471666
try testCompletion(
16481667
\\const S = struct {
@@ -2475,6 +2494,25 @@ test "structinit" {
24752494
});
24762495
}
24772496

2497+
test "structinit - fields with and without default value" {
2498+
try testCompletionWithOptions(
2499+
\\const S = struct {
2500+
\\ alpha: u32 = 0,
2501+
\\ beta: []const u8,
2502+
\\ gamma: bool = false,
2503+
\\ delta: f64,
2504+
\\};
2505+
\\const foo = S{ .<cursor> };
2506+
, &.{
2507+
.{ .label = "beta", .kind = .Field },
2508+
.{ .label = "delta", .kind = .Field },
2509+
.{ .label = "alpha", .kind = .Field },
2510+
.{ .label = "gamma", .kind = .Field },
2511+
}, .{
2512+
.check_order = true,
2513+
});
2514+
}
2515+
24782516
test "return - enum" {
24792517
try testCompletion(
24802518
\\const E = enum {

0 commit comments

Comments
 (0)