Skip to content

Commit e946479

Browse files
committed
Optional and pointer strct parameter completions
1 parent 4944862 commit e946479

4 files changed

Lines changed: 169 additions & 4 deletions

File tree

src/analysis.zig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6783,6 +6783,11 @@ pub fn resolveExpressionTypeFromAncestors(
67836783
if (try analyser.resolveDerefType(expr_ty)) |ty| {
67846784
return ty;
67856785
}
6786+
if (try analyser.resolveOptionalUnwrap(expr_ty)) |ty| {
6787+
if (try analyser.resolveDerefType(ty)) |typ| {
6788+
return typ;
6789+
}
6790+
}
67866791

67876792
switch (expr_ty.data) {
67886793
.pointer => |info| switch (info.size) {

src/features/completions.zig

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ fn getEnumLiteralContext(
12021202

12031203
var dot_context: EnumLiteralContext = .{ .likely = .enum_literal };
12041204

1205-
switch (tree.tokenTag(token_index)) {
1205+
tag: switch (tree.tokenTag(token_index)) {
12061206
.equal => {
12071207
token_index -= 1;
12081208
dot_context.need_ret_type = tree.tokenTag(token_index) == .r_paren;
@@ -1249,6 +1249,10 @@ fn getEnumLiteralContext(
12491249
.l_brace, .comma, .l_paren => {
12501250
dot_context = getSwitchOrStructInitContext(tree, dot_token_index, nodes) orelse return null;
12511251
},
1252+
.ampersand => {
1253+
token_index -= 1;
1254+
continue :tag tree.tokenTag(token_index);
1255+
},
12521256
else => return null,
12531257
}
12541258
return dot_context;
@@ -1736,7 +1740,8 @@ fn collectVarAccessContainerNodes(
17361740

17371741
const symbol_decl = try analyser.lookupSymbolGlobal(handle, handle.tree.source[loc.start..loc.end], loc.end) orelse return;
17381742
const result = try symbol_decl.resolveType(analyser) orelse return;
1739-
const type_expr = try analyser.resolveDerefType(result) orelse result;
1743+
var type_expr = try analyser.resolveDerefType(result) orelse result;
1744+
type_expr = type_expr.resolveDeclLiteralResultType();
17401745
if (!type_expr.isFunc()) {
17411746
_ = try type_expr.getAllTypesWithHandlesArraySet(analyser, types_with_handles);
17421747
return;
@@ -1752,7 +1757,7 @@ fn collectVarAccessContainerNodes(
17521757
}
17531758
const param_index = dot_context.fn_arg_index;
17541759
if (param_index >= info.parameters.len) return;
1755-
const param_type = info.parameters[param_index].type;
1760+
const param_type = info.parameters[param_index].type.resolveDeclLiteralResultType();
17561761
_ = try param_type.getAllTypesWithHandlesArraySet(analyser, types_with_handles);
17571762
}
17581763

@@ -1786,7 +1791,7 @@ fn collectFieldAccessTypes(
17861791
const params = info.parameters;
17871792
const param_index = dot_context.fn_arg_index + @intFromBool(has_self_param);
17881793
if (param_index >= params.len) return;
1789-
const param_type = params[param_index].type;
1794+
const param_type = params[param_index].type.resolveDeclLiteralResultType();
17901795
_ = try param_type.getAllTypesWithHandlesArraySet(analyser, types_with_handles);
17911796
}
17921797

tests/lsp_features/completion.zig

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,67 @@ test "decl literal function call" {
17321732
});
17331733
}
17341734

1735+
test "function call struct parameter completion" {
1736+
try testCompletion(
1737+
\\fn foo(s: struct {field: u32}) void {}
1738+
\\fn bar() void {
1739+
\\ foo(.<cursor>);
1740+
\\}
1741+
, &.{
1742+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1743+
});
1744+
try testCompletion(
1745+
\\fn foo(s: struct {field: u32}) void {}
1746+
\\fn bar() void {
1747+
\\ foo(.{.<cursor>);
1748+
\\}
1749+
, &.{
1750+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1751+
});
1752+
try testCompletion(
1753+
\\fn foo(s: ?struct {field: u32}) void {}
1754+
\\fn bar() void {
1755+
\\ foo(.<cursor>);
1756+
\\}
1757+
, &.{
1758+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1759+
});
1760+
try testCompletion(
1761+
\\fn foo(s: ?struct {field: u32}) void {}
1762+
\\fn bar() void {
1763+
\\ foo(.{.<cursor>);
1764+
\\}
1765+
, &.{
1766+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1767+
});
1768+
try testCompletion(
1769+
\\fn foo(s: *const struct {field: u32}) void {}
1770+
\\fn bar() void {
1771+
\\ foo(.<cursor>);
1772+
\\}
1773+
, &.{
1774+
// While the completion won't actually result in code that will compile due to creating not a pointer
1775+
// This will still assist user in actually writing code - the compiler will do the rest.
1776+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1777+
});
1778+
try testCompletion(
1779+
\\fn foo(s: *const struct {field: u32}) void {}
1780+
\\fn bar() void {
1781+
\\ foo(.{.<cursor>);
1782+
\\}
1783+
, &.{
1784+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1785+
});
1786+
try testCompletion(
1787+
\\fn foo(s: *const struct {field: u32}) void {}
1788+
\\fn bar() void {
1789+
\\ foo(&.<cursor>);
1790+
\\}
1791+
, &.{
1792+
.{ .label = "field", .kind = .Field, .detail = "u32" },
1793+
});
1794+
}
1795+
17351796
test "enum literal" {
17361797
try testCompletion(
17371798
\\const literal = .foo;
@@ -2494,6 +2555,67 @@ test "structinit" {
24942555
});
24952556
}
24962557

2558+
test "structinit - anonymous" {
2559+
try testCompletion(
2560+
\\fn foo() E {
2561+
\\ const foo2: struct { alpha: u32 } = .a<cursor>
2562+
\\}
2563+
, &.{
2564+
.{ .label = "alpha", .kind = .Field, .detail = "u32" },
2565+
});
2566+
try testCompletion(
2567+
\\var foo: struct { alpha: u32 } = undefined;
2568+
\\foo = .<cursor>
2569+
, &.{
2570+
.{ .label = "alpha", .kind = .Field, .detail = "u32" },
2571+
});
2572+
// try testCompletion(
2573+
// \\fn foo() E {
2574+
// \\ const foo2: struct { alpha: u32 } = .{.<cursor>
2575+
// \\}
2576+
// , &.{
2577+
// .{ .label = "alpha", .kind = .Field, .detail = "u32" },
2578+
// });
2579+
// try testCompletion(
2580+
// \\fn foo() E {
2581+
// \\ const foo2: struct { alpha: u32 } = .<cursor>
2582+
// \\}
2583+
// , &.{
2584+
// .{ .label = "alpha", .kind = .Field, .detail = "u32" },
2585+
// });
2586+
// try testCompletion(
2587+
// \\const foo2: struct { alpha: u32 } = .a<cursor>
2588+
// , &.{
2589+
// .{ .label = "alpha", .kind = .Field, .detail = "u32" },
2590+
// });
2591+
}
2592+
2593+
test "structinit - address of" {
2594+
try testCompletion(
2595+
\\const T = struct { a: u32 };
2596+
\\var t: ?*const T = &.<cursor>
2597+
, &.{
2598+
.{ .label = "a", .kind = .Field, .detail = "u32" },
2599+
});
2600+
try testCompletion(
2601+
\\const T = struct { a: u32 };
2602+
\\var t: ?*const T = undefined;
2603+
\\t = &.<cursor>
2604+
, &.{
2605+
.{ .label = "a", .kind = .Field, .detail = "u32" },
2606+
});
2607+
// try testCompletion(
2608+
// \\var t: *const struct { a: u32 } = &.<cursor>
2609+
// , &.{
2610+
// .{ .label = "a", .kind = .Field, .detail = "u32" },
2611+
// });
2612+
// try testCompletion(
2613+
// \\var t: ?*const struct { a: u32 } = &.<cursor>
2614+
// , &.{
2615+
// .{ .label = "a", .kind = .Field, .detail = "u32" },
2616+
// });
2617+
}
2618+
24972619
test "structinit - fields with and without default value" {
24982620
try testCompletionWithOptions(
24992621
\\const S = struct {

tests/lsp_features/hover.zig

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,39 @@ test "inferred struct init" {
387387
\\
388388
\\Go to [S](untitled:///Untitled-0.zig#L1)
389389
);
390+
try testHover(
391+
\\const S = struct { a: u32 };
392+
\\var t: ?*const S = &.{ .a<cursor> = 5 };
393+
,
394+
\\```zig
395+
\\a: u32
396+
\\```
397+
\\```zig
398+
\\(u32)
399+
\\```
400+
);
401+
try testHover(
402+
\\var t: ?*const struct { a: u32 } = &.{ .a<cursor> = 5 };
403+
,
404+
\\```zig
405+
\\a: u32
406+
\\```
407+
\\```zig
408+
\\(u32)
409+
\\```
410+
);
411+
try testHover(
412+
\\const S = struct { a: u32 };
413+
\\var t: ?*const S = undefined;
414+
\\fn f(_: S) void { t = &.{ .a<cursor> = 5 }; }
415+
,
416+
\\```zig
417+
\\a: u32
418+
\\```
419+
\\```zig
420+
\\(u32)
421+
\\```
422+
);
390423
}
391424

392425
test "decl literal" {

0 commit comments

Comments
 (0)