aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-07-15 13:30:03 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-07-15 13:30:03 -0400
commit428b54c588ba00c84b60ed5d24cec1b264fa5589 (patch)
tree5c346c925af49394590f191f8b1c58a167971205
parent156d75278e86764f3754c68121f4ed347e167a8b (diff)
Correctly resolve references of proc parameter names
-rw-r--r--src/server/analysis.odin19
-rw-r--r--src/server/file_resolve.odin8
-rw-r--r--src/server/references.odin15
-rw-r--r--src/server/symbol.odin13
-rw-r--r--tests/references_test.odin52
5 files changed, 102 insertions, 5 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 182aed2..e3e1f6d 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -2213,6 +2213,25 @@ resolve_location_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -
return {}, false
}
+resolve_location_proc_param_name :: proc(
+ ast_context: ^AstContext,
+ position_context: ^DocumentPositionContext,
+) -> (
+ symbol: Symbol,
+ ok: bool,
+) {
+ ident := position_context.field_value.field.derived.(^ast.Ident) or_return
+ call := position_context.call.derived.(^ast.Call_Expr) or_return
+ symbol = resolve_type_expression(ast_context, call) or_return
+
+ if value, ok := symbol.value.(SymbolProcedureValue); ok {
+ if arg_name, ok := get_proc_arg_name_from_name(value, ident.name); ok {
+ symbol.range = common.get_token_range(arg_name, ast_context.file.src)
+ }
+ }
+ return symbol, true
+}
+
resolve_location_comp_lit_field :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,
diff --git a/src/server/file_resolve.odin b/src/server/file_resolve.odin
index 70a4b99..e930f9d 100644
--- a/src/server/file_resolve.odin
+++ b/src/server/file_resolve.odin
@@ -229,6 +229,14 @@ resolve_node :: proc(node: ^ast.Node, data: ^FileResolveData) {
}
resolve_node(n.value, data)
+ } else if data.flag != .None && data.position_context.call != nil {
+ if symbol, ok := resolve_location_proc_param_name(data.ast_context, data.position_context); ok {
+ data.symbols[cast(uintptr)node] = SymbolAndNode {
+ node = n.field,
+ symbol = symbol,
+ }
+ }
+ resolve_node(n.value, data)
} else {
resolve_node(n.field, data)
resolve_node(n.value, data)
diff --git a/src/server/references.odin b/src/server/references.odin
index 7e791b8..230243a 100644
--- a/src/server/references.odin
+++ b/src/server/references.odin
@@ -145,13 +145,18 @@ prepare_references :: proc(
}
} else if position_context.field_value != nil &&
- position_context.comp_lit != nil &&
!is_expr_basic_lit(position_context.field_value.field) &&
position_in_node(position_context.field_value.field, position_context.position) {
- symbol, ok = resolve_location_comp_lit_field(ast_context, position_context)
-
- if !ok {
- return
+ if position_context.comp_lit != nil {
+ symbol, ok = resolve_location_comp_lit_field(ast_context, position_context)
+ if !ok {
+ return
+ }
+ } else if position_context.call != nil {
+ symbol, ok = resolve_location_proc_param_name(ast_context, position_context)
+ if !ok {
+ return
+ }
}
resolve_flag = .Field
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 58b7e77..b65349c 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -562,6 +562,19 @@ get_proc_arg_type_from_name :: proc(v: SymbolProcedureValue, name: string) -> (^
return nil, false
}
+get_proc_arg_name_from_name :: proc(v: SymbolProcedureValue, name: string) -> (^ast.Ident, bool) {
+ for arg in v.arg_types {
+ for arg_name in arg.names {
+ if ident, ok := arg_name.derived.(^ast.Ident); ok {
+ if name == ident.name {
+ return ident, true
+ }
+ }
+ }
+ }
+ return nil, false
+}
+
new_clone_symbol :: proc(data: Symbol, allocator := context.allocator) -> ^Symbol {
new_symbol := new(Symbol, allocator)
new_symbol^ = data
diff --git a/tests/references_test.odin b/tests/references_test.odin
index 5a4836a..961c0cf 100644
--- a/tests/references_test.odin
+++ b/tests/references_test.odin
@@ -1001,3 +1001,55 @@ ast_reference_struct_field_map :: proc(t: ^testing.T) {
test.expect_reference_locations(t, &source, locations[:])
}
+
+@(test)
+ast_reference_named_parameter_same_as_variable :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+
+ foo :: proc(a: int) {}
+
+ main :: proc() {
+ b := "hellope"
+ foo(a{*} = 0)
+ }
+ `,
+ }
+
+ locations := []common.Location {
+ {range = {start = {line = 2, character = 14}, end = {line = 2, character = 15}}},
+ {range = {start = {line = 6, character = 7}, end = {line = 6, character = 8}}},
+ }
+ test.expect_reference_locations(t, &source, locations[:])
+}
+
+@(test)
+ast_reference_struct_comp_lit_field :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+
+ Foo :: enum {
+ A,
+ B,
+ }
+
+ Bar :: struct {
+ foo: Foo,
+ }
+
+ foo :: proc() -> Bar {
+ return Bar {
+ fo{*}o = .A,
+ }
+ }
+
+ `,
+ }
+
+ locations := []common.Location {
+ {range = {start = {line = 3, character = 3}, end = {line = 3, character = 4}}},
+ {range = {start = {line = 13, character = 11}, end = {line = 13, character = 12}}},
+ }
+
+ test.expect_reference_locations(t, &source, locations[:])
+}