From 219d0157cf409f23751b719080aa212cc1ebc1f5 Mon Sep 17 00:00:00 2001 From: pc Date: Tue, 27 Jan 2026 02:13:42 +0100 Subject: feat: add completion edit text test for proc group with single argument --- src/server/methods.odin | 19 +++++++++++++++++-- src/testing/testing.odin | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/completions_test.odin | 27 +++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/server/methods.odin b/src/server/methods.odin index 797a089..19d9ff4 100644 --- a/src/server/methods.odin +++ b/src/server/methods.odin @@ -250,8 +250,23 @@ add_proc_group_method_completion :: proc( references, dereferences := compute_pointer_adjustments(first_arg.pointers, pointers) - // Proc groups always have multiple args (the receiver plus at least one overload's additional args) - new_text := build_method_call_text(ast_context, symbol, receiver, references, dereferences, true) + // Check if any member of the proc group has additional arguments beyond the receiver + has_additional_args := false + for member_expr in proc_group.args { + member: Symbol + member, ok = resolve_type_expression(ast_context, member_expr) + if !ok { + continue + } + if proc_val, is_proc_val := member.value.(SymbolProcedureValue); is_proc_val { + if len(proc_val.arg_types) > 1 { + has_additional_args = true + break + } + } + } + + new_text := build_method_call_text(ast_context, symbol, receiver, references, dereferences, has_additional_args) item := CompletionItem { label = symbol.name, diff --git a/src/testing/testing.odin b/src/testing/testing.odin index 20327a7..0ba7b0f 100644 --- a/src/testing/testing.odin +++ b/src/testing/testing.odin @@ -321,6 +321,50 @@ expect_completion_insert_text :: proc( } } +expect_completion_edit_text :: proc( + t: ^testing.T, + src: ^Source, + trigger_character: string, + label: string, + expected_text: string, +) { + setup(src) + defer teardown(src) + + completion_context := server.CompletionContext { + triggerCharacter = trigger_character, + } + + completion_list, ok := server.get_completion_list(src.document, src.position, completion_context, &src.config) + + if !ok { + log.error("Failed get_completion_list") + } + + found := false + for completion in completion_list.items { + if completion.label == label { + found = true + if text_edit, has_edit := completion.textEdit.(server.TextEdit); has_edit { + if text_edit.newText != expected_text { + log.errorf( + "Completion '%v' expected textEdit.newText %q, but received %q", + label, + expected_text, + text_edit.newText, + ) + } + } else { + log.errorf("Completion '%v' has no textEdit", label) + } + break + } + } + if !found { + log.errorf("Expected completion label '%v' not found in %v", label, completion_list.items) + } +} + expect_hover :: proc(t: ^testing.T, src: ^Source, expect_hover_string: string) { setup(src) defer teardown(src) diff --git a/tests/completions_test.odin b/tests/completions_test.odin index 8ed9b43..f0fa8c1 100644 --- a/tests/completions_test.odin +++ b/tests/completions_test.odin @@ -5441,3 +5441,30 @@ ast_completion_fake_method_builtin_type_uses_builtin_pkg :: proc(t: ^testing.T) // the lookup correctly uses "$builtin" instead of "test" for the package test.expect_completion_labels(t, &source, ".", {"square", "cube"}) } + +@(test) +ast_completion_fake_method_proc_group_single_arg_cursor_position :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + import "methods" + main :: proc() { + n: int + n.{*} + } + `, + packages = { + { + pkg = "methods", + source = `package methods + // All members only take a single argument (the receiver) + negate_a :: proc(x: int) -> int { return -x } + negate_b :: proc(x: int) -> int { return 0 - x } + negate :: proc { negate_a, negate_b } + `, + }, + }, + config = {enable_fake_method = true}, + } + // The proc group 'negate' should have cursor AFTER parentheses since no additional args + test.expect_completion_edit_text(t, &source, ".", "negate", "methods.negate(n)$0") +} -- cgit v1.2.3