aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBradley Lewis <22850972+BradLewis@users.noreply.github.com>2025-11-17 18:20:46 +1100
committerGitHub <noreply@github.com>2025-11-17 18:20:46 +1100
commit161ce3ea1419517da6f7752acba9e4d02f2c4d4b (patch)
tree9e4c76b8de85ce39e1ae34da15bf22fa35add100
parentbf2ec00dc58e75ec6224e59172ae3c591c58bb9c (diff)
parent1c6273b714891c2bda3656dc0d538fd291b9b7b3 (diff)
Merge pull request #1186 from BradLewis/fix/implicit-selector-completion-improvements
Fix implicit selector completions for enumerated arrays
-rw-r--r--src/server/completion.odin130
-rw-r--r--tests/completions_test.odin49
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"})
+}