aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-07 22:06:22 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-11 16:34:21 -0400
commit151fb26f5957338f670d2d6dbef01d75ff28cc8e (patch)
tree2864c82b068f56c5bc7b69874cf97f8f8ca8ceae
parent790cf8a16315d65bd80478aecfb34d7ff5dae31b (diff)
Attempt consolidate structure for writing docs
-rw-r--r--src/server/documentation.odin189
-rw-r--r--src/server/hover.odin10
-rw-r--r--tests/hover_test.odin36
3 files changed, 127 insertions, 108 deletions
diff --git a/src/server/documentation.odin b/src/server/documentation.odin
index f0e7b1b..7b839c8 100644
--- a/src/server/documentation.odin
+++ b/src/server/documentation.odin
@@ -283,16 +283,11 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol, depth := 0) -> s
}
get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
- // TODO: this is also a bit much, might need to clean it up into a function
- show_type_info := (symbol.type == .Variable || symbol.type == .Field) && !(.Anonymous in symbol.flags) && symbol.type_name != ""
-
pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator)
#partial switch v in symbol.value {
case SymbolBasicValue:
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_symbol_type_information(ast_context, &sb, symbol, pointer_prefix)
- } else if .Distinct in symbol.flags {
+ if .Distinct in symbol.flags {
if symbol.type == .Keyword {
strings.write_string(&sb, "distinct ")
build_string_node(v.ident, &sb, false)
@@ -321,12 +316,8 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string
return symbol.signature
}
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_type_information(&sb, ast_context, symbol, pointer_prefix)
- } else {
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "enum {..}")
- }
+ strings.write_string(&sb, pointer_prefix)
+ strings.write_string(&sb, "enum {..}")
return strings.to_string(sb)
case SymbolMapValue:
sb := strings.builder_make(ast_context.allocator)
@@ -337,47 +328,29 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string
return strings.to_string(sb)
case SymbolProcedureValue:
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_type_information(&sb, ast_context, symbol, pointer_prefix)
- strings.write_string(&sb, " :: ")
- }
write_procedure_symbol_signature(&sb, v, detailed_signature=true)
return strings.to_string(sb)
case SymbolAggregateValue:
return "proc (..)"
case SymbolStructValue:
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_type_information(&sb, ast_context, symbol, pointer_prefix)
- write_poly_list(&sb, v.poly, v.poly_names)
- } else {
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "struct")
- write_poly_list(&sb, v.poly, v.poly_names)
- strings.write_string(&sb, " {..}")
- }
+ strings.write_string(&sb, pointer_prefix)
+ strings.write_string(&sb, "struct")
+ write_poly_list(&sb, v.poly, v.poly_names)
+ strings.write_string(&sb, " {..}")
return strings.to_string(sb)
case SymbolUnionValue:
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_type_information(&sb, ast_context, symbol, pointer_prefix)
- write_poly_list(&sb, v.poly, v.poly_names)
- } else {
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "union")
- write_poly_list(&sb, v.poly, v.poly_names)
- strings.write_string(&sb, " {..}")
- }
+ strings.write_string(&sb, pointer_prefix)
+ strings.write_string(&sb, "union")
+ write_poly_list(&sb, v.poly, v.poly_names)
+ strings.write_string(&sb, " {..}")
return strings.to_string(sb)
case SymbolBitFieldValue:
sb := strings.builder_make(ast_context.allocator)
- if show_type_info {
- write_type_information(&sb, ast_context, symbol, pointer_prefix)
- } else {
- fmt.sbprintf(&sb, "%sbit_field ", pointer_prefix)
- build_string_node(v.backing_type, &sb, false)
- strings.write_string(&sb, " {..}")
- }
+ fmt.sbprintf(&sb, "%sbit_field ", pointer_prefix)
+ build_string_node(v.backing_type, &sb, false)
+ strings.write_string(&sb, " {..}")
return strings.to_string(sb)
case SymbolMultiPointerValue:
@@ -453,20 +426,6 @@ get_bit_field_field_signature :: proc(value: SymbolBitFieldValue, index: int, al
return strings.to_string(sb)
}
-write_symbol_type_information :: proc(ast_context: ^AstContext, sb: ^strings.Builder, symbol: Symbol, pointer_prefix: string) {
- append_type_pkg := false
- pkg_name := get_pkg_name(ast_context, symbol.type_pkg)
- if pkg_name != "" && pkg_name != "$builtin" {
- if _, ok := keywords_docs[symbol.type_name]; !ok {
- append_type_pkg = true
- }
- }
- if append_type_pkg {
- fmt.sbprintf(sb, "%s%s.%s", pointer_prefix, pkg_name, symbol.type_name)
- } else {
- fmt.sbprintf(sb, "%s%s", pointer_prefix, symbol.type_name)
- }
-}
write_proc_param_list_and_return :: proc(sb: ^strings.Builder, value: SymbolProcedureValue) {
strings.write_string(sb, "(")
@@ -670,20 +629,6 @@ write_node :: proc(ast_context: ^AstContext, sb: ^strings.Builder, node: ^ast.No
build_string_node(node, sb, false)
}
-write_type_information :: proc(
- sb: ^strings.Builder,
- ast_context: ^AstContext,
- symbol: Symbol,
- pointer_prefix: string,
-) {
- pkg_name := get_pkg_name(ast_context, symbol.type_pkg)
- if pkg_name == "" || pkg_name == "$builtin"{
- fmt.sbprintf(sb, "%s%s", pointer_prefix, symbol.type_name)
- return
- }
- fmt.sbprintf(sb, "%s%s.%s", pointer_prefix, pkg_name, symbol.type_name)
- return
-}
write_docs :: proc(sb: ^strings.Builder, docs: []^ast.Comment_Group, index: int, depth := 0) {
if index < len(docs) && docs[index] != nil {
@@ -701,46 +646,118 @@ write_comments :: proc(sb: ^strings.Builder, comments: []^ast.Comment_Group, ind
}
}
+// We concat the symbol information as follows
+// attribute | variable | type | signature
+// attributes and type information is optional
+
concatenate_symbol_information :: proc {
concatenate_raw_symbol_information,
concatenate_raw_string_information,
}
-concatenate_raw_symbol_information :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
+construct_symbol_information :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
+ sb := strings.builder_make(ast_context.allocator)
+ write_symbol_attributes(&sb, symbol)
+ write_symbol_name(&sb, symbol)
+
+ if symbol.type == .Package {
+ return strings.to_string(sb)
+ }
+
+ if write_symbol_type_information(&sb, ast_context, symbol) {
+ return strings.to_string(sb)
+ }
+ strings.write_string(&sb, symbol.signature)
+
+ return strings.to_string(sb)
+}
+
+write_symbol_attributes :: proc(sb: ^strings.Builder, symbol: Symbol) {
+ // Currently only attributes for procedures are supported
if v, ok := symbol.value.(SymbolProcedureValue); ok {
pkg := path.base(symbol.pkg, false, context.temp_allocator)
- sb := strings.builder_make(context.temp_allocator)
for attribute in v.attributes {
if len(attribute.elems) == 0 {
- strings.write_string(&sb, "@()\n")
+ strings.write_string(sb, "@()\n")
continue
}
- strings.write_string(&sb, "@(")
+ strings.write_string(sb, "@(")
for elem, i in attribute.elems {
if directive, ok := elem.derived.(^ast.Field_Value); ok {
- build_string_node(directive.field, &sb, false)
- strings.write_string(&sb, "=")
- build_string_node(directive.value, &sb, false)
+ build_string_node(directive.field, sb, false)
+ strings.write_string(sb, "=")
+ build_string_node(directive.value, sb, false)
} else {
- build_string_node(elem, &sb, false)
+ build_string_node(elem, sb, false)
}
if i != len(attribute.elems) - 1 {
- strings.write_string(&sb, ", ")
+ strings.write_string(sb, ", ")
}
}
- strings.write_string(&sb, ")\n")
+ strings.write_string(sb, ")\n")
}
+ }
+}
- if pkg != "" && pkg != "$builtin" {
- fmt.sbprintf(&sb, "%v.", pkg)
- }
- fmt.sbprintf(&sb, "%v", symbol.name)
- if symbol.signature != "" {
- fmt.sbprintf(&sb, ": %v", symbol.signature)
+write_symbol_name :: proc(sb: ^strings.Builder, symbol: Symbol) {
+ pkg := path.base(symbol.pkg, false, context.temp_allocator)
+
+ if symbol.type == .Package {
+ fmt.sbprintf(sb, "%v: package", symbol.name)
+ return
+ }
+ if pkg != "" && pkg != "$builtin" {
+ fmt.sbprintf(sb, "%v.", pkg)
+ }
+ strings.write_string(sb, symbol.name)
+ strings.write_string(sb, ": ")
+}
+
+write_symbol_type_information :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol: Symbol) -> bool {
+ show_type_info := (symbol.type == .Variable || symbol.type == .Field) &&
+ !(.Anonymous in symbol.flags) && symbol.type_name != ""
+
+ if !show_type_info {
+ return false
+ }
+
+ if _, ok := symbol.value.(SymbolBasicValue); ok {
+ return false
+ }
+
+ if _, ok := symbol.value.(SymbolUntypedValue); ok {
+ return false
+ }
+
+ pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator)
+
+ append_type_pkg := false
+ pkg_name := get_pkg_name(ast_context, symbol.type_pkg)
+ if pkg_name != "" && pkg_name != "$builtin" {
+ if _, ok := keywords_docs[symbol.type_name]; !ok {
+ append_type_pkg = true
}
- return strings.to_string(sb)
}
+ if append_type_pkg {
+ fmt.sbprintf(sb, "%s%s.%s", pointer_prefix, pkg_name, symbol.type_name)
+ } else {
+ fmt.sbprintf(sb, "%s%s", pointer_prefix, symbol.type_name)
+ }
+ return true
+}
+
+concatenate_raw_symbol_information :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
+
+ // if pkg != "" && pkg != "$builtin" {
+ // fmt.sbprintf(&sb, "%v.", pkg)
+ // }
+ // fmt.sbprintf(&sb, "%v", symbol.name)
+ // if symbol.signature != "" {
+ // fmt.sbprintf(&sb, ": %v", symbol.signature)
+ // }
+ // return strings.to_string(sb)
+ //}
return concatenate_raw_string_information(
ast_context,
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 4719685..cba2234 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -34,7 +34,7 @@ write_hover_content :: proc(ast_context: ^AstContext, symbol: Symbol) -> MarkupC
}
}
- cat := concatenate_symbol_information(ast_context, symbol)
+ cat := construct_symbol_information(ast_context, symbol)
doc := construct_symbol_docs(symbol)
if cat != "" {
@@ -410,9 +410,11 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
}
if resolved, ok := resolve_type_identifier(&ast_context, ident); ok {
- resolved.type_name = resolved.name
- resolved.type_pkg = resolved.pkg
- resolved.name = ident.name
+ if resolved.name != ident.name {
+ resolved.type_name = resolved.name
+ resolved.type_pkg = resolved.pkg
+ resolved.name = ident.name
+ }
if resolved.type == .Variable {
resolved.pkg = ast_context.document_package
}
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index f3c0af7..766b501 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -106,7 +106,7 @@ ast_hover_external_package_parameter :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.cool: my_package.My_Struct :: struct {\n\tone: int,\n\ttwo: int,\n\tthree: int,\n}",
+ "test.cool: my_package.My_Struct",
)
}
@@ -140,7 +140,7 @@ ast_hover_external_package_parameter_pointer :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.cool: ^my_package.My_Struct :: struct {\n\tone: int,\n\ttwo: int,\n\tthree: int,\n}",
+ "test.cool: ^my_package.My_Struct",
)
}
@@ -577,7 +577,7 @@ ast_hover_struct_variable :: proc(t: ^testing.T) {
`,
}
- test.expect_hover(t, &source, "test.foo: test.Foo :: struct {\n\tbar: int,\n\tf: proc(a: int) -> int,\n}")
+ test.expect_hover(t, &source, "test.foo: test.Foo")
}
@(test)
@@ -609,7 +609,7 @@ ast_hover_enum_variable :: proc(t: ^testing.T) {
`,
}
- test.expect_hover(t, &source, "test.foo: test.Foo :: enum {\n\tFoo1,\n\tFoo2,\n}")
+ test.expect_hover(t, &source, "test.foo: test.Foo")
}
@(test)
@@ -641,7 +641,7 @@ ast_hover_union_variable :: proc(t: ^testing.T) {
`,
}
- test.expect_hover(t, &source, "test.foo: test.Foo :: union {\n\tstring,\n\tint,\n}")
+ test.expect_hover(t, &source, "test.foo: test.Foo")
}
@(test)
@@ -1327,7 +1327,7 @@ ast_hover_proc_overloading_parametric_type :: proc(t: ^testing.T) {
packages = packages[:],
}
- test.expect_hover(t, &source, "test.foo: ^my_package.Foo :: struct {}")
+ test.expect_hover(t, &source, "test.foo: ^my_package.Foo")
}
@(test)
@@ -1365,7 +1365,7 @@ ast_hover_proc_overloading_parametric_type_external_package :: proc(t: ^testing.
packages = packages[:],
}
- test.expect_hover(t, &source, "test.foo: ^my_package.Foo :: struct {}")
+ test.expect_hover(t, &source, "test.foo: ^my_package.Foo")
}
@(test)
@@ -1622,7 +1622,7 @@ ast_hover_poly_type :: proc(t: ^testing.T) {
`,
}
- test.expect_hover(t, &source, "test.foo: test.Foo :: struct {\n\tfoo: int,\n}")
+ test.expect_hover(t, &source, "test.foo: test.Foo")
}
@(test)
@@ -1668,7 +1668,7 @@ ast_hover_poly_type_external_package :: proc(t: ^testing.T) {
packages = packages[:],
}
- test.expect_hover(t, &source, "test.foo: test.Foo :: struct {\n\tfoo: int,\n}")
+ test.expect_hover(t, &source, "test.foo: test.Foo")
}
@(test)
@@ -1716,7 +1716,7 @@ ast_hover_poly_type_external_package_with_external_type :: proc(t: ^testing.T) {
packages = packages[:],
}
- test.expect_hover(t, &source, "test.foo: small_array.Foo :: struct {}")
+ test.expect_hover(t, &source, "test.foo: small_array.Foo")
}
@(test)
@@ -1768,7 +1768,7 @@ ast_hover_poly_proc_mixed_packages :: proc(t: ^testing.T) {
packages = packages[:],
}
- test.expect_hover(t, &source, "test.f: bar_package.Bar :: struct {\n\tbar: int,\n}")
+ test.expect_hover(t, &source, "test.f: bar_package.Bar")
}
@(test)
@@ -1890,7 +1890,7 @@ ast_hover_bitset_enum_for_loop :: proc(t: ^testing.T) {
}
`,
}
- test.expect_hover(t, &source, "test.f: test.Foo :: enum {\n\tA,\n\tB,\n}")
+ test.expect_hover(t, &source, "test.f: test.Foo")
}
@(test)
@@ -2634,7 +2634,7 @@ ast_hover_named_parameter_with_default_value_struct :: proc(t: ^testing.T) {
}
`,
}
- test.expect_hover(t, &source, "foo.a: test.Bar :: struct {\n\tbar: int,\n}")
+ test.expect_hover(t, &source, "foo.a: test.Bar")
}
@(test)
@@ -3238,7 +3238,7 @@ ast_hover_switch_initialiser :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.c: test.A :: enum {\n\tB,\n\tC,\n}",
+ "test.c: test.A",
)
}
@@ -3277,7 +3277,7 @@ ast_hover_type_switch_with_using :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.v: ^my_package.Foo :: struct {}",
+ "test.v: ^my_package.Foo",
)
}
@@ -3298,7 +3298,7 @@ ast_hover_union_with_poly :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.foo: test.Foo :: union(int) {\n\tint,\n}",
+ "test.foo: test.Foo",
)
}
@@ -3331,7 +3331,7 @@ ast_hover_union_with_poly_from_package :: proc(t: ^testing.T) {
test.expect_hover(
t,
&source,
- "test.foo: my_package.Foo :: union(int) {\n\tint,\n}",
+ "test.foo: my_package.Foo",
)
}
@@ -3444,7 +3444,7 @@ ast_hover_chained_call_expr_with_named_proc_return :: proc(t: ^testing.T) {
}
`,
}
- test.expect_hover(t, &source, "test.b: test.Foo :: struct {\n\tsomeData: int,\n}")
+ test.expect_hover(t, &source, "test.b: test.Foo")
}
@(test)