aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-07-03 11:47:56 +0200
committerGitHub <noreply@github.com>2025-07-03 11:47:56 +0200
commit718fee642d34da5d43fe9bdeee54abdb34385bb8 (patch)
tree79b2170876a8492f7a427c637b3407eedfd9c48a
parent4ec40cec010b4c8c28fe4bb428c6b53a089a7d30 (diff)
parent5348ee2fc5b7609e58baaa835b4fb55d5c13fc3e (diff)
Merge pull request #710 from BradLewis/feat/improve-enum-completions
Enum completion improvements
-rw-r--r--src/server/analysis.odin15
-rw-r--r--src/server/completion.odin20
-rw-r--r--tests/completions_test.odin34
3 files changed, 60 insertions, 9 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index e7496da..9f7018f 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -3830,10 +3830,17 @@ unwrap_enum :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (SymbolEnumVal
}
if enum_symbol, ok := resolve_type_expression(ast_context, node); ok {
- if enum_value, ok := enum_symbol.value.(SymbolEnumValue); ok {
- return enum_value, true
- } else if union_value, ok := enum_symbol.value.(SymbolUnionValue); ok {
- return unwrap_super_enum(ast_context, union_value)
+ #partial switch value in enum_symbol.value {
+ case SymbolEnumValue:
+ return value, true
+ case SymbolUnionValue:
+ return unwrap_super_enum(ast_context, value)
+ case SymbolSliceValue:
+ return unwrap_enum(ast_context, value.expr)
+ case SymbolFixedArrayValue:
+ return unwrap_enum(ast_context, value.expr)
+ case SymbolDynamicArrayValue:
+ return unwrap_enum(ast_context, value.expr)
}
}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 6a172ef..80c5ae1 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -727,6 +727,7 @@ get_implicit_completion :: proc(
//value decl infer a : My_Enum = .*
if position_context.value_decl != nil && position_context.value_decl.type != nil {
enum_value: Maybe(SymbolEnumValue)
+ exclude_names := make([dynamic]string, context.temp_allocator)
if _enum_value, ok := unwrap_enum(ast_context, position_context.value_decl.type); ok {
enum_value = _enum_value
@@ -739,16 +740,25 @@ get_implicit_completion :: proc(
enum_value = _enum_value
}
}
+ for elem in position_context.comp_lit.elems {
+ if expr, ok := elem.derived.(^ast.Implicit_Selector_Expr); ok {
+ if expr.field.name != "_" {
+ append(&exclude_names, expr.field.name)
+ }
+ }
+ }
}
if ev, ok := enum_value.?; ok {
for name in ev.names {
- item := CompletionItem {
- label = name,
- kind = .EnumMember,
- detail = name,
+ if !slice.contains(exclude_names[:], name) {
+ item := CompletionItem {
+ label = name,
+ kind = .EnumMember,
+ detail = name,
+ }
+ append(&items, item)
}
- append(&items, item)
}
list.items = items[:]
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index ae3b023..a9c3f7b 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -3481,3 +3481,37 @@ ast_completion_poly_proc_mixed_packages :: proc(t: ^testing.T) {
test.expect_completion_details(t, &source, "", {"Bar.bar: int"})
}
+
+@(test)
+ast_completion_enum_slice :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ E :: enum { A, B }
+ Eslice :: []E
+
+ main :: proc() {
+ a: Eslice = { .{*} }
+ }
+ `,
+ }
+
+ test.expect_completion_details(t, &source, "", {"A", "B"})
+}
+
+@(test)
+ast_completion_bitset :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ E :: enum { A, B, C }
+
+ Ebitset :: bit_set[E]
+
+ main :: proc() {
+ b: Ebitset = { .A, .C, .{*} }
+ }
+ `,
+ }
+
+ // I think this test will pass even if there is A and C
+ test.expect_completion_details(t, &source, "", {"B"})
+}