aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBradley Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-20 09:00:01 -0400
committerGitHub <noreply@github.com>2025-09-20 09:00:01 -0400
commitc8060630c01f8f46ae12dcc60b96b77a22f29751 (patch)
tree11c19677b34befd6d98d2d5613733cf7ea5f0671
parent7ff84eb0b24912db1b3f3b0cff323e1728f47b0b (diff)
parentcad50369b0756958e826d7e964b1a3b7ed1504d5 (diff)
Merge pull request #1032 from BradLewis/fix/completion-matching-unary-improvements
Check to see if completion already includes `&` before adding it when matching
-rw-r--r--src/server/completion.odin28
-rw-r--r--src/server/position_context.odin6
-rw-r--r--tests/completions_test.odin40
3 files changed, 71 insertions, 3 deletions
diff --git a/src/server/completion.odin b/src/server/completion.odin
index aceff60..38b5cbe 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -237,7 +237,7 @@ convert_completion_results :: proc(
position_context: ^DocumentPositionContext,
results: []CompletionResult,
completion_type: Completion_Type,
- symbol: Maybe(Symbol),
+ target_symbol: Maybe(Symbol),
config: ^common.Config,
) -> []CompletionItem {
for &result in results {
@@ -334,7 +334,7 @@ convert_completion_results :: proc(
}
if config.enable_completion_matching {
- if s, ok := symbol.(Symbol); ok && (completion_type == .Selector || completion_type == .Identifier) {
+ if s, ok := target_symbol.(Symbol); ok && (completion_type == .Selector || completion_type == .Identifier) {
handle_matching(ast_context, position_context, result.symbol, s, &item, completion_type)
}
}
@@ -431,6 +431,12 @@ handle_matching :: proc(
return false
}
+ if r, ok := result_symbol.value.(SymbolBasicValue); ok {
+ if a, ok := arg_symbol.value.(SymbolBasicValue); ok {
+ return r.ident.name != a.ident.name
+ }
+ }
+
if _, ok := arg_symbol.value.(SymbolSliceValue); ok {
if _, ok := result_symbol.value.(SymbolDynamicArrayValue); ok {
return false
@@ -456,6 +462,21 @@ handle_matching :: proc(
return false
}
+ contains_unary :: proc(arg: ^ast.Expr) -> bool {
+ if arg == nil {
+ return false
+ }
+
+ #partial switch n in arg.derived {
+ case ^ast.Unary_Expr:
+ return true
+ case ^ast.Field_Value:
+ return contains_unary(n.value)
+ }
+
+ return false
+ }
+
if should_skip(arg_symbol, result_symbol) {
return
}
@@ -473,7 +494,8 @@ handle_matching :: proc(
if diff > 0 {
suffix = repeat("^", diff, context.temp_allocator)
}
- if diff < 0 {
+
+ if diff < 0 && !contains_unary(position_context.call_arg) {
prefix = "&"
}
diff --git a/src/server/position_context.odin b/src/server/position_context.odin
index f3f2f68..1aa2ec1 100644
--- a/src/server/position_context.odin
+++ b/src/server/position_context.odin
@@ -34,6 +34,7 @@ DocumentPositionContext :: struct {
tag: ^ast.Node,
field: ^ast.Expr, //used for completion
call: ^ast.Expr, //used for signature help
+ call_arg: ^ast.Expr, //used for completion
returns: ^ast.Return_Stmt, //used for completion
comp_lit: ^ast.Comp_Lit, //used for completion
parent_comp_lit: ^ast.Comp_Lit, //used for completion
@@ -628,6 +629,11 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
case ^Call_Expr:
position_context.call = n
get_document_position(n.expr, position_context)
+ for arg in n.args {
+ if position_in_node(arg, position_context.position) {
+ position_context.call_arg = arg
+ }
+ }
get_document_position(n.args, position_context)
case ^Selector_Call_Expr:
position_context.selector = n.expr
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index d3a2eb7..7b42568 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -4698,3 +4698,43 @@ ast_completion_struct_field_value :: proc(t: ^testing.T) {
}
test.expect_completion_docs(t, &source, "", {"test.Foo: struct {}"})
}
+
+@(test)
+ast_completion_handle_matching_with_unary :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ Foo :: struct{}
+
+ do_foo :: proc(foo: ^Foo){}
+
+ main :: proc() {
+ foo: Foo
+ do_foo(&f{*})
+ }
+ `,
+ config = {
+ enable_completion_matching = true,
+ },
+ }
+ test.expect_completion_insert_text(t, &source, "", {"foo"})
+}
+
+@(test)
+ast_completion_handle_matching_field_with_unary :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ Foo :: struct{}
+
+ do_foo :: proc(foo: ^Foo){}
+
+ main :: proc() {
+ foo: Foo
+ do_foo(foo = &f{*})
+ }
+ `,
+ config = {
+ enable_completion_matching = true,
+ },
+ }
+ test.expect_completion_insert_text(t, &source, "", {"foo"})
+}