aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-07-04 10:24:02 +0200
committerGitHub <noreply@github.com>2025-07-04 10:24:02 +0200
commit2efeb965d91c2f8544fda10ac3f16fff44c3716b (patch)
tree28eda75b917c3422beafe721c69a6d7c51ee0d61 /src
parent56a6c4ef51116f9a7e33b9a4b5fda95baaa0f5a0 (diff)
parenteac2491844c158cbf70146f3b61a9b82a87b8de5 (diff)
Merge pull request #716 from BradLewis/fix/map-key-resolution
Improvements to enum resolution and documentation
Diffstat (limited to 'src')
-rw-r--r--src/server/analysis.odin27
-rw-r--r--src/server/collector.odin19
-rw-r--r--src/server/completion.odin20
-rw-r--r--src/server/documentation.odin28
-rw-r--r--src/server/hover.odin72
-rw-r--r--src/server/symbol.odin11
6 files changed, 145 insertions, 32 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 7170935..597c2cd 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1842,8 +1842,11 @@ resolve_implicit_selector :: proc(
}
}
- if array, ok := symbol.value.(SymbolFixedArrayValue); ok {
- return resolve_type_expression(ast_context, array.len)
+ #partial switch value in symbol.value {
+ case SymbolFixedArrayValue:
+ return resolve_type_expression(ast_context, value.len)
+ case SymbolMapValue:
+ return resolve_type_expression(ast_context, value.key)
}
}
@@ -2754,33 +2757,37 @@ make_symbol_enum_from_ast :: proc(
names := make([dynamic]string, ast_context.allocator)
ranges := make([dynamic]common.Range, ast_context.allocator)
+ values := make([dynamic]^ast.Expr, ast_context.allocator)
for n in v.fields {
- name, range := get_enum_field_name_and_range(n, ast_context.file.src)
+ name, range, value := get_enum_field_name_range_value(n, ast_context.file.src)
append(&names, name)
append(&ranges, range)
+ append(&values, value)
}
symbol.value = SymbolEnumValue {
- names = names[:],
- ranges = ranges[:],
+ names = names[:],
+ ranges = ranges[:],
+ base_type = v.base_type,
+ values = values[:],
}
return symbol
}
-get_enum_field_name_and_range :: proc(n: ^ast.Expr, document_text: string) -> (string, common.Range) {
+get_enum_field_name_range_value :: proc(n: ^ast.Expr, document_text: string) -> (string, common.Range, ^ast.Expr) {
if ident, ok := n.derived.(^ast.Ident); ok {
- return ident.name, common.get_token_range(ident, document_text)
+ return ident.name, common.get_token_range(ident, document_text), nil
}
if field, ok := n.derived.(^ast.Field_Value); ok {
if ident, ok := field.field.derived.(^ast.Ident); ok {
- return ident.name, common.get_token_range(ident, document_text)
+ return ident.name, common.get_token_range(ident, document_text), field.value
} else if binary, ok := field.field.derived.(^ast.Binary_Expr); ok {
- return binary.left.derived.(^ast.Ident).name, common.get_token_range(binary, document_text)
+ return binary.left.derived.(^ast.Ident).name, common.get_token_range(binary, document_text), binary.right
}
}
- return "", {}
+ return "", {}, nil
}
make_symbol_bitset_from_ast :: proc(
diff --git a/src/server/collector.odin b/src/server/collector.odin
index b2c2d66..22aba08 100644
--- a/src/server/collector.odin
+++ b/src/server/collector.odin
@@ -151,7 +151,7 @@ collect_struct_fields :: proc(
}
value := to_symbol_struct_value(b)
- value.poly = cast(^ast.Field_List)clone_type(struct_type.poly_params, collection.allocator, &collection.unique_strings)
+ value.poly = cast(^ast.Field_List)clone_type(struct_type.poly_params, collection.allocator, &collection.unique_strings)
return value
}
@@ -189,23 +189,26 @@ collect_bit_field_fields :: proc(
collect_enum_fields :: proc(
collection: ^SymbolCollection,
- fields: []^ast.Expr,
+ enum_type: ast.Enum_Type,
package_map: map[string]string,
file: ast.File,
) -> SymbolEnumValue {
names := make([dynamic]string, 0, collection.allocator)
ranges := make([dynamic]common.Range, 0, collection.allocator)
+ values := make([dynamic]^ast.Expr, 0, collection.allocator)
- //ERROR no hover on n in the for, but elsewhere is fine
- for n in fields {
- name, range := get_enum_field_name_and_range(n, file.src)
+ for n in enum_type.fields {
+ name, range, value := get_enum_field_name_range_value(n, file.src)
append(&names, strings.clone(name, collection.allocator))
append(&ranges, range)
+ append(&values, clone_type(value, collection.allocator, &collection.unique_strings))
}
value := SymbolEnumValue {
- names = names[:],
- ranges = ranges[:],
+ names = names[:],
+ ranges = ranges[:],
+ values = values[:],
+ base_type = clone_type(enum_type.base_type, collection.allocator, &collection.unique_strings),
}
return value
@@ -529,7 +532,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
case ^ast.Enum_Type:
token = v^
token_type = .Enum
- symbol.value = collect_enum_fields(collection, v.fields, package_map, file)
+ symbol.value = collect_enum_fields(collection, v^, package_map, file)
symbol.signature = "enum"
case ^ast.Union_Type:
token = v^
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 4544143..b4f86a8 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -1196,8 +1196,24 @@ get_implicit_completion :: proc(
symbol, ok = resolve_type_expression(ast_context, position_context.index.expr)
}
- if array, ok := symbol.value.(SymbolFixedArrayValue); ok {
- if enum_value, ok := unwrap_enum(ast_context, array.len); ok {
+ #partial switch v in symbol.value {
+ case SymbolFixedArrayValue:
+ if enum_value, ok := unwrap_enum(ast_context, v.len); ok {
+ for name in enum_value.names {
+ item := CompletionItem {
+ label = name,
+ kind = .EnumMember,
+ detail = name,
+ }
+
+ append(&items, item)
+ }
+
+ list.items = items[:]
+ return
+ }
+ case SymbolMapValue:
+ if enum_value, ok := unwrap_enum(ast_context, v.key); ok {
for name in enum_value.names {
item := CompletionItem {
label = name,
diff --git a/src/server/documentation.odin b/src/server/documentation.odin
index c0853d7..b52d259 100644
--- a/src/server/documentation.odin
+++ b/src/server/documentation.odin
@@ -19,10 +19,26 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string {
append_variable_full_name(&sb, ast_context, symbol, pointer_prefix)
strings.write_string(&sb, " :: ")
}
- strings.write_string(&sb, "enum {\n")
+
+ longestNameLen := 0
+ for name in v.names {
+ if len(name) > longestNameLen {
+ longestNameLen = len(name)
+ }
+ }
+ strings.write_string(&sb, "enum ")
+ if v.base_type != nil {
+ build_string_node(v.base_type, &sb, false)
+ strings.write_string(&sb, " ")
+ }
+ strings.write_string(&sb, "{\n")
for i in 0 ..< len(v.names) {
strings.write_string(&sb, "\t")
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)
+ }
strings.write_string(&sb, ",\n")
}
strings.write_string(&sb, "}")
@@ -211,6 +227,16 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string
return ""
}
+get_enum_field_signature :: proc(value: SymbolEnumValue, index: int) -> string {
+ sb := strings.builder_make(context.temp_allocator)
+ fmt.sbprintf(&sb, ".%s", value.names[index])
+ if index < len(value.values) && value.values[index] != nil {
+ strings.write_string(&sb, " = ")
+ build_string_node(value.values[index], &sb, false)
+ }
+ 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)
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 52663a8..4965621 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -112,12 +112,54 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
}
}
- if position_context.struct_type != nil {
- for field in position_context.struct_type.fields.list {
- for name in field.names {
- if position_in_node(name, position_context.position) {
- if identifier, ok := name.derived.(^ast.Ident); ok && field.type != nil {
- if position_context.value_decl != nil && len(position_context.value_decl.names) != 0 {
+ if position_context.value_decl != nil && len(position_context.value_decl.names) != 0 {
+ if position_context.enum_type != nil {
+ if enum_symbol, ok := resolve_type_expression(&ast_context, position_context.value_decl.names[0]); ok {
+ if v, ok := enum_symbol.value.(SymbolEnumValue); ok {
+ for field in position_context.enum_type.fields {
+ if ident, ok := field.derived.(^ast.Ident); ok {
+ if position_in_node(ident, position_context.position) {
+ for name, i in v.names {
+ if name == ident.name {
+ symbol := Symbol {
+ pkg = ast_context.current_package,
+ name = enum_symbol.name,
+ range = common.get_token_range(ident, ast_context.file.src),
+ signature = get_enum_field_signature(v, i),
+ }
+ hover.contents = write_hover_content(&ast_context, symbol)
+ return hover, true, true
+ }
+ }
+ }
+ } else if value, ok := field.derived.(^ast.Field_Value); ok {
+ if position_in_node(value.field, position_context.position) {
+ if ident, ok := value.field.derived.(^ast.Ident); ok {
+ for name, i in v.names {
+ if name == ident.name {
+ symbol := Symbol {
+ pkg = ast_context.current_package,
+ range = common.get_token_range(value.field, ast_context.file.src),
+ name = enum_symbol.name,
+ signature = get_enum_field_signature(v, i),
+ }
+ hover.contents = write_hover_content(&ast_context, symbol)
+ }
+ }
+ }
+ return hover, true, true
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if position_context.struct_type != nil {
+ for field in position_context.struct_type.fields.list {
+ for name in field.names {
+ if position_in_node(name, position_context.position) {
+ if identifier, ok := name.derived.(^ast.Ident); ok && field.type != nil {
if symbol, ok := resolve_type_expression(&ast_context, field.type); ok {
if struct_symbol, ok := resolve_type_expression(
&ast_context,
@@ -139,7 +181,9 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
break
}
}
- if index != -1 && value.comments[index] != nil && len(value.comments[index].list) > 0 {
+ if index != -1 &&
+ value.comments[index] != nil &&
+ len(value.comments[index].list) > 0 {
symbol.comment = value.comments[index].list[0].text
}
}
@@ -301,6 +345,18 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
}
}
}
+ case SymbolEnumValue:
+ for name, i in v.names {
+ if name == field {
+ symbol := Symbol {
+ name = selector.name,
+ pkg = selector.pkg,
+ signature = get_enum_field_signature(v, i),
+ }
+ hover.contents = write_hover_content(&ast_context, symbol)
+ return hover, true, true
+ }
+ }
}
} else if position_context.implicit_selector_expr != nil {
implicit_selector := position_context.implicit_selector_expr
@@ -309,7 +365,7 @@ get_hover_information :: proc(document: ^Document, position: common.Position) ->
case SymbolEnumValue:
for name, i in v.names {
if strings.compare(name, implicit_selector.field.name) == 0 {
- symbol.signature = fmt.tprintf(".%s", name)
+ symbol.signature = get_enum_field_signature(v, i)
hover.contents = write_hover_content(&ast_context, symbol)
return hover, true, true
}
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 2d99d22..fddc775 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -67,8 +67,10 @@ SymbolAggregateValue :: struct {
}
SymbolEnumValue :: struct {
- names: []string,
- ranges: []common.Range,
+ names: []string,
+ values: []^ast.Expr,
+ base_type: ^ast.Expr,
+ ranges: []common.Range,
}
SymbolUnionValue :: struct {
@@ -345,7 +347,10 @@ write_struct_type :: proc(
}
write_symbol_struct_value :: proc(
- ast_context: ^AstContext, b: ^SymbolStructValueBuilder, v: SymbolStructValue, base_using_index: int
+ ast_context: ^AstContext,
+ b: ^SymbolStructValueBuilder,
+ v: SymbolStructValue,
+ base_using_index: int,
) {
base_index := len(b.names)
for name in v.names {