aboutsummaryrefslogtreecommitdiff
path: root/src/server/documentation.odin
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-17 08:39:46 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-17 08:39:46 -0400
commit508ebd3cf2799c67139d0edfdf443546b172091a (patch)
tree4953f509b28f611dc04851e890234c288ccf3474 /src/server/documentation.odin
parentd04d9bee6bfa157d863387d135d9d05315fcb864 (diff)
Pass string builder down when constructing nested hover docs
Diffstat (limited to 'src/server/documentation.odin')
-rw-r--r--src/server/documentation.odin326
1 files changed, 160 insertions, 166 deletions
diff --git a/src/server/documentation.odin b/src/server/documentation.odin
index a2c00aa..a27c32d 100644
--- a/src/server/documentation.odin
+++ b/src/server/documentation.odin
@@ -142,18 +142,23 @@ construct_symbol_docs :: proc(symbol: Symbol, markdown := true, allocator := con
// Returns the fully detailed signature for the symbol, including things like attributes and fields
get_signature :: proc(ast_context: ^AstContext, symbol: Symbol, depth := 0) -> string {
+ sb := strings.builder_make(ast_context.allocator)
+ write_signature(&sb, ast_context, symbol, depth)
+ return strings.to_string(sb)
+}
+
+write_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol: Symbol, depth := 0) {
pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator)
#partial switch v in symbol.value {
case SymbolEnumValue:
- sb := strings.builder_make(ast_context.allocator)
if len(v.names) == 0 {
- write_indent(&sb, depth)
- strings.write_string(&sb, "enum {}")
+ write_indent(sb, depth)
+ strings.write_string(sb, "enum {}")
if symbol.comment != "" {
- fmt.sbprintf(&sb, " %s", symbol.comment)
+ fmt.sbprintf(sb, " %s", symbol.comment)
}
- return strings.to_string(sb)
+ return
}
longestNameLen := 0
@@ -162,92 +167,87 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol, depth := 0) -> s
longestNameLen = len(name)
}
}
- strings.write_string(&sb, "enum ")
+ strings.write_string(sb, "enum ")
if v.base_type != nil {
- build_string_node(v.base_type, &sb, false)
- strings.write_string(&sb, " ")
+ build_string_node(v.base_type, sb, false)
+ strings.write_string(sb, " ")
}
- strings.write_string(&sb, "{\n")
+ strings.write_string(sb, "{\n")
for i in 0 ..< len(v.names) {
- write_docs(&sb, v.docs, i, depth + 1)
- write_indent(&sb, depth + 1)
- strings.write_string(&sb, v.names[i])
+ write_docs(sb, v.docs, i, depth + 1)
+ write_indent(sb, depth + 1)
+ strings.write_string(sb, v.names[i])
if i < len(v.values) && v.values[i] != nil {
- fmt.sbprintf(&sb, "%*s= ", longestNameLen - len(v.names[i]) + 1, "")
- build_string_node(v.values[i], &sb, false)
+ fmt.sbprintf(sb, "%*s= ", longestNameLen - len(v.names[i]) + 1, "")
+ build_string_node(v.values[i], sb, false)
}
- strings.write_string(&sb, ",")
- write_comments(&sb, v.comments, i)
- strings.write_string(&sb, "\n")
+ strings.write_string(sb, ",")
+ write_comments(sb, v.comments, i)
+ strings.write_string(sb, "\n")
}
- write_indent(&sb, depth)
- strings.write_string(&sb, "}")
- return strings.to_string(sb)
+ write_indent(sb, depth)
+ strings.write_string(sb, "}")
+ return
case SymbolStructValue:
- sb := strings.builder_make(ast_context.allocator)
if len(v.names) == 0 {
- strings.write_string(&sb, "struct {}")
+ strings.write_string(sb, "struct {}")
if symbol.comment != "" {
- fmt.sbprintf(&sb, " %s", symbol.comment)
+ fmt.sbprintf(sb, " %s", symbol.comment)
}
- return strings.to_string(sb)
+ return
}
- write_struct_hover(ast_context, &sb, v, depth)
- return strings.to_string(sb)
+ write_struct_hover(sb, ast_context, v, depth)
+ return
case SymbolUnionValue:
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, "union")
- write_poly_list(&sb, v.poly, v.poly_names)
+ strings.write_string(sb, "union")
+ write_poly_list(sb, v.poly, v.poly_names)
if v.kind != .Normal {
- write_union_kind(&sb, v.kind)
+ write_union_kind(sb, v.kind)
}
if v.align != nil {
- strings.write_string(&sb, " #align")
- build_string_node(v.align, &sb, false)
+ strings.write_string(sb, " #align")
+ build_string_node(v.align, sb, false)
}
if len(v.types) == 0 {
- strings.write_string(&sb, " {}")
- return strings.to_string(sb)
+ strings.write_string(sb, " {}")
+ return
}
- strings.write_string(&sb, " {\n")
+ strings.write_string(sb, " {\n")
for i in 0 ..< len(v.types) {
- write_docs(&sb, v.docs, i, depth + 1)
- write_indent(&sb, depth + 1)
- build_string_node(v.types[i], &sb, false)
- strings.write_string(&sb, ",")
- write_comments(&sb, v.comments, i)
- strings.write_string(&sb, "\n")
- }
- write_indent(&sb, depth)
- strings.write_string(&sb, "}")
- return strings.to_string(sb)
+ write_docs(sb, v.docs, i, depth + 1)
+ write_indent(sb, depth + 1)
+ build_string_node(v.types[i], sb, false)
+ strings.write_string(sb, ",")
+ write_comments(sb, v.comments, i)
+ strings.write_string(sb, "\n")
+ }
+ write_indent(sb, depth)
+ strings.write_string(sb, "}")
+ return
case SymbolAggregateValue:
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, "proc {\n")
+ strings.write_string(sb, "proc {\n")
for symbol in v.symbols {
if value, ok := symbol.value.(SymbolProcedureValue); ok {
- write_indent(&sb, depth + 1)
- fmt.sbprintf(&sb, "%s :: ", symbol.name)
- write_procedure_symbol_signature(&sb, value, detailed_signature = false)
- strings.write_string(&sb, ",\n")
+ write_indent(sb, depth + 1)
+ fmt.sbprintf(sb, "%s :: ", symbol.name)
+ write_procedure_symbol_signature(sb, value, detailed_signature = false)
+ strings.write_string(sb, ",\n")
}
}
- write_indent(&sb, depth)
- strings.write_string(&sb, "}")
- return strings.to_string(sb)
+ write_indent(sb, depth)
+ strings.write_string(sb, "}")
+ return
case SymbolProcedureValue:
- sb := strings.builder_make(ast_context.allocator)
- write_procedure_symbol_signature(&sb, v, detailed_signature = true)
- return strings.to_string(sb)
+ write_procedure_symbol_signature(sb, v, detailed_signature = true)
+ return
case SymbolBitFieldValue:
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, "bit_field ")
- build_string_node(v.backing_type, &sb, false)
+ strings.write_string(sb, "bit_field ")
+ build_string_node(v.backing_type, sb, false)
if len(v.names) == 0 {
- strings.write_string(&sb, " {}")
- return strings.to_string(sb)
+ strings.write_string(sb, " {}")
+ return
}
- strings.write_string(&sb, " {\n")
+ strings.write_string(sb, " {\n")
longest_name_len := 0
for name in v.names {
if len(name) > longest_name_len {
@@ -265,157 +265,153 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol, depth := 0) -> s
}
for name, i in v.names {
- write_docs(&sb, v.docs, i, depth + 1)
- write_indent(&sb, depth + 1)
- fmt.sbprintf(&sb, "%s:%*s", v.names[i], longest_name_len - len(name) + 1, "")
- fmt.sbprintf(&sb, "%s%*s| ", type_names[i], longest_type_len - len(type_names[i]) + 1, "")
- build_string_node(v.bit_sizes[i], &sb, false)
- strings.write_string(&sb, ",")
- write_comments(&sb, v.comments, i)
- strings.write_string(&sb, "\n")
- }
- write_indent(&sb, depth)
- strings.write_string(&sb, "}")
- return strings.to_string(sb)
+ write_docs(sb, v.docs, i, depth + 1)
+ write_indent(sb, depth + 1)
+ fmt.sbprintf(sb, "%s:%*s", v.names[i], longest_name_len - len(name) + 1, "")
+ fmt.sbprintf(sb, "%s%*s| ", type_names[i], longest_type_len - len(type_names[i]) + 1, "")
+ build_string_node(v.bit_sizes[i], sb, false)
+ strings.write_string(sb, ",")
+ write_comments(sb, v.comments, i)
+ strings.write_string(sb, "\n")
+ }
+ write_indent(sb, depth)
+ strings.write_string(sb, "}")
+ return
}
- return get_short_signature(ast_context, symbol)
+ write_short_signature(sb, ast_context, symbol)
}
get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
+ sb := strings.builder_make(ast_context.allocator)
+ write_short_signature(&sb, ast_context, symbol)
+ return strings.to_string(sb)
+}
+
+write_short_signature :: proc(sb: ^strings.Builder, ast_context: ^AstContext, symbol: Symbol) {
pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator)
#partial switch v in symbol.value {
case SymbolBasicValue:
- sb := strings.builder_make(ast_context.allocator)
if .Distinct in symbol.flags {
if symbol.type == .Keyword {
- strings.write_string(&sb, "distinct ")
- build_string_node(v.ident, &sb, false)
+ strings.write_string(sb, "distinct ")
+ build_string_node(v.ident, sb, false)
} else {
- fmt.sbprintf(&sb, "%s%s", pointer_prefix, symbol.name)
+ fmt.sbprintf(sb, "%s%s", pointer_prefix, symbol.name)
}
} else {
- strings.write_string(&sb, pointer_prefix)
- build_string_node(v.ident, &sb, false)
+ strings.write_string(sb, pointer_prefix)
+ build_string_node(v.ident, sb, false)
}
- return strings.to_string(sb)
+ return
case SymbolPolyTypeValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%s$", pointer_prefix)
- build_string_node(v.ident, &sb, false)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%s$", pointer_prefix)
+ build_string_node(v.ident, sb, false)
+ return
case SymbolBitSetValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%sbit_set[", pointer_prefix)
- build_string_node(v.expr, &sb, false)
- strings.write_string(&sb, "]")
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%sbit_set[", pointer_prefix)
+ build_string_node(v.expr, sb, false)
+ strings.write_string(sb, "]")
+ return
case SymbolEnumValue:
// TODO: we need a better way to do this for enum fields
if symbol.type == .Field && symbol.type_name == "" {
- return symbol.signature
+ strings.write_string(sb, symbol.signature)
+ return
}
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "enum")
+ strings.write_string(sb, pointer_prefix)
+ strings.write_string(sb, "enum")
if len(v.names) > 0 {
- strings.write_string(&sb, " {..}")
+ strings.write_string(sb, " {..}")
} else {
- strings.write_string(&sb, " {}")
+ strings.write_string(sb, " {}")
}
- return strings.to_string(sb)
+ return
case SymbolMapValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%smap[", pointer_prefix)
- build_string_node(v.key, &sb, false)
- strings.write_string(&sb, "]")
- write_node(ast_context, &sb, v.value, "", short_signature = true)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%smap[", pointer_prefix)
+ build_string_node(v.key, sb, false)
+ strings.write_string(sb, "]")
+ write_node(ast_context, sb, v.value, "", short_signature = true)
+ return
case SymbolProcedureValue:
- sb := strings.builder_make(ast_context.allocator)
- write_procedure_symbol_signature(&sb, v, detailed_signature = true)
- return strings.to_string(sb)
+ write_procedure_symbol_signature(sb, v, detailed_signature = true)
+ return
case SymbolAggregateValue:
- return "proc (..)"
+ strings.write_string(sb, "proc (..)")
+ return
case SymbolStructValue:
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "struct")
- write_poly_list(&sb, v.poly, v.poly_names)
+ strings.write_string(sb, pointer_prefix)
+ strings.write_string(sb, "struct")
+ write_poly_list(sb, v.poly, v.poly_names)
if len(v.types) > 0 {
- strings.write_string(&sb, " {..}")
+ strings.write_string(sb, " {..}")
} else {
- strings.write_string(&sb, " {}")
+ strings.write_string(sb, " {}")
}
- return strings.to_string(sb)
+ return
case SymbolUnionValue:
- sb := strings.builder_make(ast_context.allocator)
- strings.write_string(&sb, pointer_prefix)
- strings.write_string(&sb, "union")
- write_poly_list(&sb, v.poly, v.poly_names)
+ strings.write_string(sb, pointer_prefix)
+ strings.write_string(sb, "union")
+ write_poly_list(sb, v.poly, v.poly_names)
if len(v.types) > 0 {
- strings.write_string(&sb, " {..}")
+ strings.write_string(sb, " {..}")
} else {
- strings.write_string(&sb, " {}")
+ strings.write_string(sb, " {}")
}
- return strings.to_string(sb)
+ return
case SymbolBitFieldValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%sbit_field ", pointer_prefix)
- build_string_node(v.backing_type, &sb, false)
+ fmt.sbprintf(sb, "%sbit_field ", pointer_prefix)
+ build_string_node(v.backing_type, sb, false)
if len(v.types) > 0 {
- strings.write_string(&sb, " {..}")
+ strings.write_string(sb, " {..}")
} else {
- strings.write_string(&sb, " {}")
+ strings.write_string(sb, " {}")
}
- return strings.to_string(sb)
+ return
case SymbolMultiPointerValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%s[^]", pointer_prefix)
- write_node(ast_context, &sb, v.expr, "", short_signature = true)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%s[^]", pointer_prefix)
+ write_node(ast_context, sb, v.expr, "", short_signature = true)
+ return
case SymbolDynamicArrayValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%s[dynamic]", pointer_prefix)
- write_node(ast_context, &sb, v.expr, "", short_signature = true)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%s[dynamic]", pointer_prefix)
+ write_node(ast_context, sb, v.expr, "", short_signature = true)
+ return
case SymbolSliceValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%s[]", pointer_prefix)
- write_node(ast_context, &sb, v.expr, "", short_signature = true)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%s[]", pointer_prefix)
+ write_node(ast_context, sb, v.expr, "", short_signature = true)
+ return
case SymbolFixedArrayValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%s[", pointer_prefix)
- build_string_node(v.len, &sb, false)
- strings.write_string(&sb, "]")
- write_node(ast_context, &sb, v.expr, "", short_signature = true)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%s[", pointer_prefix)
+ build_string_node(v.len, sb, false)
+ strings.write_string(sb, "]")
+ write_node(ast_context, sb, v.expr, "", short_signature = true)
+ return
case SymbolMatrixValue:
- sb := strings.builder_make(ast_context.allocator)
- fmt.sbprintf(&sb, "%smatrix[", pointer_prefix)
- build_string_node(v.x, &sb, false)
- strings.write_string(&sb, ",")
- build_string_node(v.y, &sb, false)
- strings.write_string(&sb, "]")
- build_string_node(v.expr, &sb, false)
- return strings.to_string(sb)
+ fmt.sbprintf(sb, "%smatrix[", pointer_prefix)
+ build_string_node(v.x, sb, false)
+ strings.write_string(sb, ",")
+ build_string_node(v.y, sb, false)
+ strings.write_string(sb, "]")
+ build_string_node(v.expr, sb, false)
+ return
case SymbolPackageValue:
- return "package"
+ strings.write_string(sb, "package")
+ return
case SymbolUntypedValue:
switch v.type {
case .Float:
- return "float"
+ strings.write_string(sb, "float")
case .String:
- return "string"
+ strings.write_string(sb, "string")
case .Bool:
- return "bool"
+ strings.write_string(sb, "bool")
case .Integer:
- return "int"
+ strings.write_string(sb, "int")
}
+ return
}
- return ""
+ return
}
write_indent :: proc(sb: ^strings.Builder, level: int) {
@@ -524,7 +520,7 @@ write_procedure_symbol_signature :: proc(sb: ^strings.Builder, value: SymbolProc
}
}
-write_struct_hover :: proc(ast_context: ^AstContext, sb: ^strings.Builder, v: SymbolStructValue, depth: int) {
+write_struct_hover :: proc(sb: ^strings.Builder, ast_context: ^AstContext, v: SymbolStructValue, depth: int) {
using_prefix := "using "
longestNameLen := 0
for name, i in v.names {
@@ -668,11 +664,9 @@ write_node :: proc(
}
if ok {
if short_signature {
- inner_sig := get_short_signature(ast_context, symbol)
- strings.write_string(sb, inner_sig)
+ write_short_signature(sb, ast_context, symbol)
} else {
- inner_sig := get_signature(ast_context, symbol, depth)
- strings.write_string(sb, inner_sig)
+ write_signature(sb, ast_context, symbol, depth)
}
return
}