aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-06-13 17:49:21 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-06-13 19:24:13 -0400
commitab0ff1ba4fd3e35e330deb6979c5c1aa75907a98 (patch)
tree95fe85408d8c6592f7c8c3d14dd6fe6a66474e1f
parent023c8a0fd1d8d8e54b38bf990a74816a31dee68e (diff)
Improve resolution of comp literals
-rw-r--r--src/server/analysis.odin8
-rw-r--r--src/server/completion.odin57
-rw-r--r--tests/completions_test.odin2
-rw-r--r--tests/hover_test.odin32
4 files changed, 59 insertions, 40 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 1a7e4a7..b2ab4f2 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -211,6 +211,14 @@ resolve_type_comp_literal :: proc(
^ast.Comp_Lit,
bool,
) {
+ // If the symbol is a MultiPointerValue, we retrieve the symbol of the underlying expression and
+ // retry with that.
+ if s, ok := current_symbol.value.(SymbolMultiPointerValue); ok {
+ if symbol, ok := resolve_type_expression(ast_context, s.expr); ok {
+ return resolve_type_comp_literal(ast_context, position_context, symbol, current_comp_lit)
+ }
+ }
+
if position_context.comp_lit == current_comp_lit {
return current_symbol, current_comp_lit, true
} else if current_comp_lit == nil {
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 5136518..df4c260 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -267,8 +267,6 @@ get_comp_lit_completion :: proc(
if symbol, ok := resolve_comp_literal(ast_context, position_context); ok {
#partial switch v in symbol.value {
case SymbolStructValue:
- get_struct_field_completion(ast_context, position_context, &items, symbol)
- case SymbolBitFieldValue:
for name, i in v.names {
if name == "_" {
continue
@@ -291,54 +289,33 @@ get_comp_lit_completion :: proc(
append(&items, item)
}
}
- case SymbolMultiPointerValue:
- if resolved, ok := resolve_type_expression(ast_context, v.expr); ok {
- if value, ok := resolved.value.(SymbolStructValue); ok {
- get_struct_field_completion(ast_context, position_context, &items, resolved)
+ case SymbolBitFieldValue:
+ for name, i in v.names {
+ if name == "_" {
+ continue
}
- }
- }
- }
- list.items = items[:]
-}
+ set_ast_package_set_scoped(ast_context, symbol.pkg)
-get_struct_field_completion :: proc(
- ast_context: ^AstContext,
- position_context: ^DocumentPositionContext,
- items: ^[dynamic]CompletionItem,
- symbol: Symbol,
-) {
- v := symbol.value.(SymbolStructValue)
- for name, i in v.names {
- if name == "_" {
- continue
- }
+ if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok {
+ if field_exists_in_comp_lit(position_context.comp_lit, name) {
+ continue
+ }
- set_ast_package_set_scoped(ast_context, symbol.pkg)
+ item := CompletionItem {
+ label = name,
+ kind = .Field,
+ detail = fmt.tprintf("%v.%v: %v", symbol.name, name, common.node_to_string(v.types[i])),
+ documentation = resolved.doc,
+ }
- if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok {
- if field_exists_in_comp_lit(position_context.comp_lit, name) {
- continue
- }
-
- if value, ok := resolved.value.(SymbolStructValue); ok {
- get_struct_field_completion(ast_context, position_context, items, resolved)
- continue
- } else {
- item := CompletionItem {
- label = name,
- kind = .Field,
- detail = fmt.tprintf("%v.%v: %v", symbol.name, name, common.node_to_string(v.types[i])),
- documentation = resolved.doc,
+ append(&items, item)
}
-
- append(items, item)
}
-
}
}
+ list.items = items[:]
}
get_selector_completion :: proc(
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index ee4b1e3..837e1d2 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -3245,6 +3245,8 @@ ast_completion_multi_pointer_nested :: proc(t: ^testing.T) {
S2 :: struct {
field: S3,
+ i: int,
+ s: int,
}
S3 :: struct {
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index cb46473..bf34137 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -946,6 +946,38 @@ ast_hover_empty_line_at_top_of_file :: proc(t: ^testing.T) {
test.expect_hover(t, &source, "test.Foo: struct {\n\tbar: int,\n}")
}
+
+@(test)
+ast_hover_inside_multi_pointer_struct :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+
+ S1 :: struct {
+ s2_ptr: [^]S2,
+ }
+
+ S2 :: struct {
+ field: S3,
+ i: int,
+ s: int,
+ }
+
+ S3 :: struct {
+ s3: int,
+ }
+
+ main :: proc() {
+ x := S1 {
+ s2_ptr = &S2 {
+ fi{*}eld = S3 {}
+ }
+ }
+ }
+ `
+ }
+
+ test.expect_hover(t, &source, "S2.field: S3")
+}
/*
Waiting for odin fix