diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-15 13:30:03 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-15 13:30:03 -0400 |
| commit | 428b54c588ba00c84b60ed5d24cec1b264fa5589 (patch) | |
| tree | 5c346c925af49394590f191f8b1c58a167971205 | |
| parent | 156d75278e86764f3754c68121f4ed347e167a8b (diff) | |
Correctly resolve references of proc parameter names
| -rw-r--r-- | src/server/analysis.odin | 19 | ||||
| -rw-r--r-- | src/server/file_resolve.odin | 8 | ||||
| -rw-r--r-- | src/server/references.odin | 15 | ||||
| -rw-r--r-- | src/server/symbol.odin | 13 | ||||
| -rw-r--r-- | tests/references_test.odin | 52 |
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[:]) +} |