aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-19 08:50:13 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-21 08:55:43 -0400
commit93401ea027155fd72ec7850bd0ed74ab9e2b8b07 (patch)
treeb52fbac24e4851b5754fea91811f4dfb24b2e101
parent035a0db206ae1651b8e853b5aff5c1562fc7715e (diff)
Improve hover information for constant proc lits
-rw-r--r--src/server/documentation.odin70
-rw-r--r--tests/completions_test.odin4
-rw-r--r--tests/hover_test.odin44
3 files changed, 99 insertions, 19 deletions
diff --git a/src/server/documentation.odin b/src/server/documentation.odin
index 53c9c36..fda1050 100644
--- a/src/server/documentation.odin
+++ b/src/server/documentation.odin
@@ -165,7 +165,7 @@ write_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol:
}
if len(v.names) == 0 {
write_indent(sb, depth)
- strings.write_string(sb, "enum {}")
+ strings.write_string(sb, "enum{}")
if symbol.comment != "" {
fmt.sbprintf(sb, " %s", symbol.comment)
}
@@ -220,7 +220,7 @@ write_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol:
}
write_where_clauses(sb, v.where_clauses)
if len(v.types) == 0 {
- strings.write_string(sb, " {}")
+ strings.write_string(sb, "{}")
return
}
strings.write_string(sb, " {\n")
@@ -332,7 +332,7 @@ write_short_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, sy
if len(v.names) > 0 {
strings.write_string(sb, " {..}")
} else {
- strings.write_string(sb, " {}")
+ strings.write_string(sb, "{}")
}
return
case SymbolMapValue:
@@ -354,7 +354,7 @@ write_short_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, sy
if len(v.types) > 0 {
strings.write_string(sb, " {..}")
} else {
- strings.write_string(sb, " {}")
+ strings.write_string(sb, "{}")
}
return
case SymbolUnionValue:
@@ -364,7 +364,7 @@ write_short_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, sy
if len(v.types) > 0 {
strings.write_string(sb, " {..}")
} else {
- strings.write_string(sb, " {}")
+ strings.write_string(sb, "{}")
}
return
case SymbolBitFieldValue:
@@ -595,36 +595,49 @@ write_struct_hover :: proc(sb: ^strings.Builder, ast_context: ^AstContext, v: Sy
strings.write_string(sb, "struct")
write_poly_list(sb, v.poly, v.poly_names)
+ wrote_tag := false
if v.max_field_align != nil {
strings.write_string(sb, " #max_field_align")
build_string_node(v.max_field_align, sb, false)
+ wrote_tag = true
}
if v.min_field_align != nil {
strings.write_string(sb, " #min_field_align")
build_string_node(v.min_field_align, sb, false)
+ wrote_tag = true
}
if v.align != nil {
strings.write_string(sb, " #align")
build_string_node(v.align, sb, false)
+ wrote_tag = true
}
for tag in v.tags {
switch tag {
case .Is_Raw_Union:
+ wrote_tag = true
strings.write_string(sb, " #raw_union")
case .Is_Packed:
+ wrote_tag = true
strings.write_string(sb, " #packed")
case .Is_No_Copy:
+ wrote_tag = true
strings.write_string(sb, " #no_copy")
}
}
- write_where_clauses(sb, v.where_clauses)
+ if len(v.where_clauses) > 0 {
+ write_where_clauses(sb, v.where_clauses)
+ wrote_tag = true
+ }
if len(v.names) == 0 {
- strings.write_string(sb, " {}")
+ if wrote_tag {
+ strings.write_string(sb, " ")
+ }
+ strings.write_string(sb, "{}")
return
}
@@ -765,6 +778,31 @@ write_node :: proc(
case ^ast.Proc_Type:
symbol = make_symbol_procedure_from_ast(ast_context, nil, n^, name, {}, true, .None, nil)
ok = true
+ case ^ast.Comp_Lit:
+ build_string(n.type, sb, false)
+ if len(n.elems) == 0 {
+ strings.write_string(sb, "{}")
+ return
+ }
+ if n.type != nil {
+ strings.write_string(sb, " {\n")
+ } else {
+ strings.write_string(sb, "{\n")
+ }
+
+ for elem, i in n.elems {
+ write_indent(sb, depth)
+ if field, ok := elem.derived.(^ast.Field_Value); ok {
+ build_string(field.field, sb, false)
+ strings.write_string(sb, " = ")
+ build_string(field.value, sb, false)
+ } else {
+ build_string(elem, sb, false)
+ }
+ strings.write_string(sb, ",\n")
+ }
+ strings.write_string(sb, "}")
+ return
}
if ok {
if short_signature {
@@ -808,12 +846,18 @@ construct_symbol_information :: proc(ast_context: ^AstContext, symbol: Symbol) -
}
if symbol.type != .Field && .Mutable not_in symbol.flags {
- if symbol.type_expr != nil && symbol.value_expr != nil {
- strings.write_string(&sb, " : ")
- build_string_node(symbol.type_expr, &sb, false)
- strings.write_string(&sb, " : ")
- build_string_node(symbol.value_expr, &sb, false)
- return strings.to_string(sb)
+ if symbol.value_expr != nil {
+ if symbol.type_expr != nil {
+ strings.write_string(&sb, " : ")
+ build_string_node(symbol.type_expr, &sb, false)
+ strings.write_string(&sb, " : ")
+ write_node(&sb, ast_context, symbol.value_expr, "", 1, false)
+ return strings.to_string(sb)
+ } else if _, ok := symbol.value_expr.derived.(^ast.Comp_Lit); ok {
+ strings.write_string(&sb, " :: ")
+ write_node(&sb, ast_context, symbol.value_expr, "", 1, false)
+ return strings.to_string(sb)
+ }
}
strings.write_string(&sb, " :: ")
} else {
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index 13196a3..a97ff0f 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -4681,7 +4681,7 @@ ast_completion_struct_field_name :: proc(t: ^testing.T) {
}
`,
}
- test.expect_completion_docs(t, &source, "", {}, {"test.Foo :: struct {}"})
+ test.expect_completion_docs(t, &source, "", {}, {"test.Foo :: struct{}"})
}
@(test)
@@ -4696,7 +4696,7 @@ ast_completion_struct_field_value :: proc(t: ^testing.T) {
}
`,
}
- test.expect_completion_docs(t, &source, "", {"test.Foo :: struct {}"})
+ test.expect_completion_docs(t, &source, "", {"test.Foo :: struct{}"})
}
@(test)
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index ee43c50..9f41c2c 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -237,7 +237,7 @@ ast_hover_on_array_infer_length_variable :: proc(t: ^testing.T) {
`,
}
- test.expect_hover(t, &source, "test.vec :: [?]f32")
+ test.expect_hover(t, &source, "test.vec :: [?]f32 {\n\t1,\n\t2,\n\t3,\n}")
}
@(test)
@@ -3192,7 +3192,7 @@ ast_hover_documentation_reexported :: proc(t: ^testing.T) {
`,
packages = packages[:],
}
- test.expect_hover(t, &source, "my_package.Foo :: struct {}\n Documentation for Foo")
+ test.expect_hover(t, &source, "my_package.Foo :: struct{}\n Documentation for Foo")
}
@(test)
@@ -3218,7 +3218,7 @@ ast_hover_override_documentation_reexported :: proc(t: ^testing.T) {
`,
packages = packages[:],
}
- test.expect_hover(t, &source, "my_package.Foo :: struct {}\n New docs for Foo")
+ test.expect_hover(t, &source, "my_package.Foo :: struct{}\n New docs for Foo")
}
@(test)
@@ -3913,7 +3913,7 @@ ast_hover_map_empty_struct_literal :: proc(t: ^testing.T) {
m{*}: map[int]struct{}
`,
}
- test.expect_hover(t, &source, "test.m: map[int]struct {}")
+ test.expect_hover(t, &source, "test.m: map[int]struct{}")
}
@(test)
@@ -4878,6 +4878,42 @@ ast_hover_const_untyped_value :: proc(t: ^testing.T) {
}
test.expect_hover(t, &source, "test.FOO :: 123")
}
+
+@(test)
+ast_hover_const_comp_lit :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ Foo :: struct {
+ a: int,
+ b: string,
+ }
+
+ F{*}OO :: Foo {
+ a = 1,
+ b = "b",
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.FOO :: Foo {\n\ta = 1,\n\tb = \"b\",\n}")
+}
+
+@(test)
+ast_hover_const_comp_lit_with_type :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ Foo :: struct {
+ a: int,
+ b: string,
+ }
+
+ F{*}OO : Foo : {
+ a = 1,
+ b = "b",
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.FOO : Foo : {\n\ta = 1,\n\tb = \"b\",\n}")
+}
/*
Waiting for odin fix