aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-16 18:02:47 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-09-16 18:02:47 -0400
commita31f9f0a97f543f51ca49a268f94c5078c9b9661 (patch)
treeac608f57e916ab461cc3c3334b76b9b53cf98ee0
parentf3223ddbaeed978da5de5d70667f146637b07293 (diff)
Correctly resolve generic types where the underlying identifier is a pointer
-rw-r--r--src/server/generics.odin6
-rw-r--r--src/server/position_context.odin31
-rw-r--r--src/server/type_definition.odin2
-rw-r--r--tests/hover_test.odin20
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