diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-11-17 02:18:01 -0500 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-11-17 02:18:01 -0500 |
| commit | 1c6273b714891c2bda3656dc0d538fd291b9b7b3 (patch) | |
| tree | 9e4c76b8de85ce39e1ae34da15bf22fa35add100 | |
| parent | bf2ec00dc58e75ec6224e59172ae3c591c58bb9c (diff) | |
Fix implicit selector completions for enumerated arrays
| -rw-r--r-- | src/server/completion.odin | 130 | ||||
| -rw-r--r-- | tests/completions_test.odin | 49 |
2 files changed, 99 insertions, 80 deletions
diff --git a/src/server/completion.odin b/src/server/completion.odin index e1ebc87..8560ed3 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -1307,36 +1307,6 @@ get_implicit_completion :: proc( reset_ast_context(ast_context) } - /* - if it's comp literals for enumerated array: - asset_paths := [Asset]cstring { - .Layer0 = "assets/layer0.png", - } - - Right now `core:odin/parser` is not tolerant enough, so I just look at the type and if it's a enumerated array. I can't get the field value is on the left side. - */ - if position_context.comp_lit != nil { - if symbol, ok := resolve_type_expression(ast_context, position_context.comp_lit); ok { - if symbol_value, ok := symbol.value.(SymbolFixedArrayValue); ok { - if enum_value, unwrapped_super_enum, ok := unwrap_enum(ast_context, symbol_value.len); ok { - for enum_name in enum_value.names { - item := CompletionItem { - label = enum_name, - kind = .EnumMember, - detail = enum_name, - } - if unwrapped_super_enum { - add_implicit_selector_remove_edit(position_context, &item, enum_name, enum_value.names) - } - - append(results, CompletionResult{completion_item = item}) - } - return is_incomplete - } - } - } - } - //infer bitset and enums based on the identifier comp_lit, i.e. a := My_Struct { my_ident = . } if position_context.comp_lit != nil && position_context.parent_comp_lit != nil { if symbol, ok := resolve_comp_literal(ast_context, position_context); ok { @@ -1504,6 +1474,56 @@ get_implicit_completion :: proc( reset_ast_context(ast_context) } + if position_context.index != nil { + symbol: Symbol + ok := false + if position_context.previous_index != nil { + symbol, ok = resolve_type_expression(ast_context, position_context.previous_index) + if !ok { + return is_incomplete + } + } else { + symbol, ok = resolve_type_expression(ast_context, position_context.index.expr) + } + + #partial switch v in symbol.value { + case SymbolFixedArrayValue: + if enum_value, unwrapped_super_enum, ok := unwrap_enum(ast_context, v.len); ok { + for name in enum_value.names { + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + } + if unwrapped_super_enum { + add_implicit_selector_remove_edit(position_context, &item, name, enum_value.names) + } + + append(results, CompletionResult{completion_item = item}) + } + + return is_incomplete + } + case SymbolMapValue: + if enum_value, unwrapped_super_enum, ok := unwrap_enum(ast_context, v.key); ok { + for name in enum_value.names { + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + } + if unwrapped_super_enum { + add_implicit_selector_remove_edit(position_context, &item, name, enum_value.names) + } + + append(results, CompletionResult{completion_item = item}) + } + + return is_incomplete + } + } + } + if position_context.call != nil { if call, ok := position_context.call.derived.(^ast.Call_Expr); ok { parameter_index, parameter_ok := find_position_in_call_param(position_context, call^) @@ -1579,56 +1599,6 @@ get_implicit_completion :: proc( reset_ast_context(ast_context) } - - if position_context.index != nil { - symbol: Symbol - ok := false - if position_context.previous_index != nil { - symbol, ok = resolve_type_expression(ast_context, position_context.previous_index) - if !ok { - return is_incomplete - } - } else { - symbol, ok = resolve_type_expression(ast_context, position_context.index.expr) - } - - #partial switch v in symbol.value { - case SymbolFixedArrayValue: - if enum_value, unwrapped_super_enum, ok := unwrap_enum(ast_context, v.len); ok { - for name in enum_value.names { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - } - if unwrapped_super_enum { - add_implicit_selector_remove_edit(position_context, &item, name, enum_value.names) - } - - append(results, CompletionResult{completion_item = item}) - } - - return is_incomplete - } - case SymbolMapValue: - if enum_value, unwrapped_super_enum, ok := unwrap_enum(ast_context, v.key); ok { - for name in enum_value.names { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - } - if unwrapped_super_enum { - add_implicit_selector_remove_edit(position_context, &item, name, enum_value.names) - } - - append(results, CompletionResult{completion_item = item}) - } - - return is_incomplete - } - } - } return is_incomplete } diff --git a/tests/completions_test.odin b/tests/completions_test.odin index 43f4984..92fd332 100644 --- a/tests/completions_test.odin +++ b/tests/completions_test.odin @@ -5064,3 +5064,52 @@ ast_completion_union_option_with_using :: proc(t: ^testing.T) { } test.expect_completion_labels(t, &source, "", {"(^Foo)", "(^Bar)"}) } + +@(test) +ast_completion_implicit_selector_enumerated_array_value :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + A :: enum { + A1, + A2, + } + + B :: enum { + B1, + B2, + } + + A_TO_B :: [A]B{ + .A1 = .{*} + } + `, + } + test.expect_completion_docs(t, &source, "", {"B1", "B2"}) +} + +@(test) +ast_completion_implicit_selector_enumerated_array_in_proc_call_arg :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + A :: enum { + A1, + A2, + } + + B :: enum { + B1, + B2, + } + + A_TO_B :: [A]B{} + + foo :: proc(b: B) {} + + main :: proc() { + foo(A_TO_B[.{*}]) + + } + `, + } + test.expect_completion_docs(t, &source, "", {"A1", "A2"}) +} |