From fc61cb706555c41d8b5afe1cf2bc93d343d960e4 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Tue, 16 Sep 2025 14:52:54 -0400 Subject: Correctly resolve variadic args as a slice --- src/server/analysis.odin | 10 +++++++++- tests/hover_test.odin | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 570a035..856f0ae 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1124,7 +1124,15 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex case ^Helper_Type: return internal_resolve_type_expression(ast_context, v.type, out) case ^Ellipsis: - return internal_resolve_type_expression(ast_context, v.expr, out) + out.range = common.get_token_range(v.node, ast_context.file.src) + out.type = .Type + out.pkg = get_package_from_node(v.node) + out.name = ast_context.field_name.name + out.uri = common.create_uri(v.pos.file, ast_context.allocator).uri + out.value = SymbolSliceValue { + expr = v.expr, + } + return true case ^Implicit: ident := new_type(Ident, v.node.pos, v.node.end, ast_context.allocator) ident.name = v.tok.text diff --git a/tests/hover_test.odin b/tests/hover_test.odin index 37d0362..f1577c8 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -4738,6 +4738,28 @@ ast_hover_proc_group_parapoly_matrix :: proc(t: ^testing.T) { } test.expect_hover(t, &source, "test.c: matrix[3,2]int") } + +@(test) +ast_hover_proc_group_variadic_args :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + append_elems :: proc(array: ^$T/[dynamic]string, args: ..string) {} + append_elem :: proc(array: ^$T/[dynamic]string, arg: string) {} + + append :: proc { + append_elem, + append_elems, + } + + main :: proc() { + foos: [dynamic]string + bars: [dynamic]string + app{*}end(&bars, ..foos[:]) + } + `, + } + test.expect_hover(t, &source, "test.append: proc(array: ^$T/[dynamic]string, args: ..string)") +} /* Waiting for odin fix -- cgit v1.2.3 From f3223ddbaeed978da5de5d70667f146637b07293 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Tue, 16 Sep 2025 15:14:40 -0400 Subject: Correctly resolve generic variadic args --- src/server/generics.odin | 26 ++++++++++++++++++++++++++ tests/hover_test.odin | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/server/generics.odin b/src/server/generics.odin index cec9926..984cb8e 100644 --- a/src/server/generics.odin +++ b/src/server/generics.odin @@ -205,6 +205,26 @@ resolve_poly :: proc( } } + return found + } + case ^ast.Ellipsis: + if call_array, ok := call_node.derived.(^ast.Array_Type); ok { + found := false + + if array_is_soa(call_array^) { + return false + } + + if poly_type, ok := p.expr.derived.(^ast.Poly_Type); ok { + if ident, ok := unwrap_ident(poly_type.type); ok { + save_poly_map(ident, call_array.elem, poly_map) + } + + if poly_type.specialization != nil { + return resolve_poly(ast_context, call_array.elem, call_symbol, p.expr, poly_map) + } + found |= true + } return found } case ^ast.Map_Type: @@ -425,6 +445,12 @@ find_and_replace_poly_type :: proc(expr: ^ast.Expr, poly_map: ^map[string]^ast.E } } } + case ^ast.Ellipsis: + if expr, ok := get_poly_map(v.expr, poly_map); ok { + v.expr = expr + v.pos.file = expr.pos.file + v.end.file = expr.end.file + } } return visitor diff --git a/tests/hover_test.odin b/tests/hover_test.odin index f1577c8..2d50c51 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -4760,6 +4760,28 @@ ast_hover_proc_group_variadic_args :: proc(t: ^testing.T) { } test.expect_hover(t, &source, "test.append: proc(array: ^$T/[dynamic]string, args: ..string)") } + +@(test) +ast_hover_proc_group_variadic_args_with_generic_type :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E) {} + append_elem :: proc(array: ^$T/[dynamic]$E, arg: E) {} + + append :: proc { + append_elem, + append_elems, + } + + main :: proc() { + foos: [dynamic]string + bars: [dynamic]string + app{*}end(&bars, ..foos[:]) + } + `, + } + test.expect_hover(t, &source, "test.append: proc(array: ^$T/[dynamic]$E, args: ..E)") +} /* Waiting for odin fix -- cgit v1.2.3 From a31f9f0a97f543f51ca49a268f94c5078c9b9661 Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Tue, 16 Sep 2025 18:02:47 -0400 Subject: Correctly resolve generic types where the underlying identifier is a pointer --- src/server/generics.odin | 6 +++++- src/server/position_context.odin | 31 +++++++++++++++---------------- src/server/type_definition.odin | 2 +- tests/hover_test.odin | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/server/generics.odin b/src/server/generics.odin index 984cb8e..374ffc9 100644 --- a/src/server/generics.odin +++ b/src/server/generics.odin @@ -63,7 +63,8 @@ resolve_poly :: proc( if ident, ok := unwrap_ident(type); ok { call_node_id := reflect.union_variant_typeid(call_node.derived) specialization_id := reflect.union_variant_typeid(specialization.derived) - if call_node_id == specialization_id { + if ast_context.position_hint == .TypeDefinition && call_node_id == specialization_id { + // TODO: Fix this so it doesn't need to be aware that we're in a type definition // if the specialization type matches the type of the parameter passed to the proc // we store that rather than the specialization so we can follow it correctly // for things like `textDocument/typeDefinition` @@ -526,6 +527,9 @@ resolve_generic_function_symbol :: proc( ast_context.current_package = ast_context.document_package if symbol, ok := resolve_type_expression(ast_context, call_expr.args[i]); ok { + if ident, ok := call_expr.args[i].derived.(^ast.Ident); ok && symbol.name == "" { + symbol.name = ident.name + } file := strings.trim_prefix(symbol.uri, "file://") if file == "" { diff --git a/src/server/position_context.odin b/src/server/position_context.odin index d5e7d33..f3f2f68 100644 --- a/src/server/position_context.odin +++ b/src/server/position_context.odin @@ -14,6 +14,7 @@ DocumentPositionContextHint :: enum { SignatureHelp, Definition, Hover, + TypeDefinition, } DocumentPositionContext :: struct { @@ -629,27 +630,25 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP get_document_position(n.expr, position_context) get_document_position(n.args, position_context) case ^Selector_Call_Expr: - if position_context.hint == .Definition || - position_context.hint == .Hover || - position_context.hint == .SignatureHelp || - position_context.hint == .Completion { - position_context.selector = n.expr - position_context.field = n.call - position_context.selector_expr = node + position_context.selector = n.expr + position_context.field = n.call + position_context.selector_expr = node - if _, ok := n.call.derived.(^ast.Call_Expr); ok { - position_context.call = n.call - } + if _, ok := n.call.derived.(^ast.Call_Expr); ok { + position_context.call = n.call + } - get_document_position(n.expr, position_context) - get_document_position(n.call, position_context) + get_document_position(n.expr, position_context) + get_document_position(n.call, position_context) - if position_context.hint == .SignatureHelp { - position_context.arrow = true - } + if position_context.hint == .SignatureHelp { + position_context.arrow = true } case ^Selector_Expr: - if position_context.hint == .Definition || position_context.hint == .Hover && n.field != nil { + if (position_context.hint == .Definition || + position_context.hint == .Hover || + position_context.hint == .TypeDefinition) && + n.field != nil { position_context.selector = n.expr position_context.field = n.field position_context.selector_expr = node diff --git a/src/server/type_definition.odin b/src/server/type_definition.odin index 84d1f1a..532bfe9 100644 --- a/src/server/type_definition.odin +++ b/src/server/type_definition.odin @@ -27,7 +27,7 @@ get_type_definition_locations :: proc(document: ^Document, position: common.Posi uri: string locations := make([dynamic]common.Location, context.temp_allocator) - position_context, ok := get_document_position_context(document, position, .Definition) + position_context, ok := get_document_position_context(document, position, .TypeDefinition) if !ok { log.warn("Failed to get position context") diff --git a/tests/hover_test.odin b/tests/hover_test.odin index 2d50c51..3f6bb3b 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -4782,6 +4782,26 @@ ast_hover_proc_group_variadic_args_with_generic_type :: proc(t: ^testing.T) { } test.expect_hover(t, &source, "test.append: proc(array: ^$T/[dynamic]$E, args: ..E)") } + +@(test) +ast_hover_proc_group_with_generic_type_from_proc_param :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E) {} + append_elem :: proc(array: ^$T/[dynamic]$E, arg: E) {} + + append :: proc { + append_elem, + append_elems, + } + + foo :: proc(bars: ^[dynamic]string) { + app{*}end(bars, "test") + } + `, + } + test.expect_hover(t, &source, "test.append: proc(array: ^$T/[dynamic]$E, arg: E)") +} /* Waiting for odin fix -- cgit v1.2.3