Skip to content

Commit

Permalink
completions: Unwrap the field's type if it's an optional (#1533)
Browse files Browse the repository at this point in the history
Handles `x{.a_field_with_an_optional_type =`
  • Loading branch information
llogick authored Oct 17, 2023
1 parent a781897 commit e4593da
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/analysis.zig
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ fn resolveReturnType(analyser: *Analyser, fn_decl: Ast.full.FnProto, handle: *co
}

/// Resolves the child type of an optional type
fn resolveUnwrapOptionalType(analyser: *Analyser, opt: TypeWithHandle) !?TypeWithHandle {
pub fn resolveUnwrapOptionalType(analyser: *Analyser, opt: TypeWithHandle) !?TypeWithHandle {
const opt_node = switch (opt.type.data) {
.other => |n| n,
else => return null,
Expand Down
8 changes: 4 additions & 4 deletions src/features/completions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1363,9 +1363,7 @@ fn collectFieldAccessContainerNodes(
var node_type = try decl.resolveType(analyser) orelse continue;
// Unwrap `identifier.opt_enum_field = .` or `identifier.opt_cont_field = .{.`
if (dot_context.likely == .enum_assignment or dot_context.likely == .struct_field) {
if (node_type.type.data == .other and node_type.handle.tree.nodes.items(.tag)[node_type.type.data.other] == .optional_type) {
node_type = try analyser.resolveTypeOfNode(.{ .node = node_type.handle.tree.nodes.items(.data)[node_type.type.data.other].lhs, .handle = node_type.handle }) orelse return;
}
if (try analyser.resolveUnwrapOptionalType(node_type)) |unwrapped| node_type = unwrapped;
}
if (node_type.isFunc()) {
var buf: [1]Ast.Node.Index = undefined;
Expand Down Expand Up @@ -1426,7 +1424,9 @@ fn collectEnumLiteralContainerNodes(
else => continue,
};
const member_decl = try analyser.lookupSymbolContainer(.{ .node = node, .handle = container.handle }, alleged_field_name, .field) orelse continue;
const member_type = try member_decl.resolveType(analyser) orelse continue;
var member_type = try member_decl.resolveType(analyser) orelse continue;
// Unwrap `x{ .fld_w_opt_type =`
if (try analyser.resolveUnwrapOptionalType(member_type)) |unwrapped| member_type = unwrapped;
try types_with_handles.append(arena, member_type);
}
}
12 changes: 12 additions & 0 deletions tests/lsp_features/completion.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,18 @@ test "completion - struct init" {
// TODO `alpha` should be excluded
.{ .label = "alpha", .kind = .Field, .detail = "alpha: *const S" },
});
try testCompletion(
\\const S = struct {
\\ alpha: *const S,
\\ beta: u32,
\\ gamma: ?S,
\\};
\\const foo = S{ .gamma = .{.<cursor>};
, &.{
.{ .label = "gamma", .kind = .Field, .detail = "gamma: ?S" },
.{ .label = "beta", .kind = .Field, .detail = "beta: u32" },
.{ .label = "alpha", .kind = .Field, .detail = "alpha: *const S" },
});
// Aliases
try testCompletion(
\\pub const Outer = struct {
Expand Down

0 comments on commit e4593da

Please sign in to comment.