diff --git a/src/analysis.zig b/src/analysis.zig index 753b79dec..64fce4c47 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -1069,16 +1069,24 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, node_handle: NodeWithHandle) e .aligned_var_decl, => { const var_decl = tree.fullVarDecl(node).?; - if (var_decl.ast.type_node != 0) { - const decl_type = .{ .node = var_decl.ast.type_node, .handle = handle }; - if (try analyser.resolveTypeOfNodeInternal(decl_type)) |typ| - return typ.instanceTypeVal(); + var fallback_type: ?TypeWithHandle = null; + + if (var_decl.ast.type_node != 0) blk: { + const type_node = .{ .node = var_decl.ast.type_node, .handle = handle }; + const decl_type = try analyser.resolveTypeOfNodeInternal(type_node) orelse break :blk; + if (decl_type.isMetaType()) { + fallback_type = decl_type; + break :blk; + } + return decl_type.instanceTypeVal(); } - if (var_decl.ast.init_node == 0) - return null; - const value = .{ .node = var_decl.ast.init_node, .handle = handle }; - return try analyser.resolveTypeOfNodeInternal(value); + if (var_decl.ast.init_node != 0) blk: { + const value = .{ .node = var_decl.ast.init_node, .handle = handle }; + return try analyser.resolveTypeOfNodeInternal(value) orelse break :blk; + } + + return fallback_type; }, .identifier => { const name_token = main_tokens[node]; @@ -2061,6 +2069,15 @@ pub const TypeWithHandle = struct { }; } + pub fn isMetaType(self: TypeWithHandle) bool { + if (!self.type.is_type_val) return false; + switch (self.type.data) { + .other => |node| return Analyser.isMetaType(self.handle.tree, node), + .ip_index => |payload| return payload.index == .type_type, + else => return false, + } + } + pub fn isTypeFunc(self: TypeWithHandle) bool { var buf: [1]Ast.Node.Index = undefined; const tree = self.handle.tree; diff --git a/tests/lsp_features/completion.zig b/tests/lsp_features/completion.zig index cd022e735..6bbdac91a 100644 --- a/tests/lsp_features/completion.zig +++ b/tests/lsp_features/completion.zig @@ -1332,6 +1332,27 @@ test "completion - struct init" { } test "completion - declarations" { + try testCompletion( + \\const S = struct { + \\ pub const Public = u32; + \\ const Private = u32; + \\}; + \\const foo = S. + , &.{ + .{ .label = "Public", .kind = .Constant, .detail = "const Public = u32" }, + .{ .label = "Private", .kind = .Constant, .detail = "const Private = u32" }, + }); + try testCompletion( + \\const S: type = struct { + \\ pub const Public = u32; + \\ const Private: type = u32; + \\}; + \\const foo = S. + , &.{ + .{ .label = "Public", .kind = .Constant, .detail = "const Public = u32" }, + .{ .label = "Private", .kind = .Constant, .detail = "const Private: type = u32" }, + }); + try testCompletion( \\const S = struct { \\ pub fn public() S {} @@ -1345,7 +1366,7 @@ test "completion - declarations" { }); try testCompletion( - \\const S = struct { + \\const S: type = struct { \\ pub fn public() S {} \\ fn private() !void {} \\};