diff options
| -rw-r--r-- | src/server/analysis.odin | 43 | ||||
| -rw-r--r-- | tests/hover_test.odin | 21 |
2 files changed, 60 insertions, 4 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 25f85c5..8e1d7f0 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -362,6 +362,21 @@ are_symbol_basic_same_keywords :: proc(a, b: Symbol) -> bool { return true } +is_valid_nil_symbol :: proc(symbol: Symbol) -> bool { + if symbol.pointers > 0 { + return true + } + + #partial switch v in symbol.value { + case SymbolMapValue, SymbolSliceValue, SymbolProcedureValue, SymbolDynamicArrayValue: + return true + case SymbolUnionValue: + return v.kind != .no_nil + } + + return false +} + is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: Symbol, flags: ast.Field_Flags = {}) -> bool { // In order to correctly equate the symbols for overloaded functions, we need to check both directions if same, ok := are_symbol_untyped_basic_same_typed(a, b); ok { @@ -721,6 +736,7 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou call_symbol: Symbol arg_symbol: Symbol ok: bool + is_call_arg_nil: bool if _, ok = call_arg.derived.(^ast.Bad_Expr); ok { continue @@ -729,9 +745,14 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou //named parameter if field, is_field := call_arg.derived.(^ast.Field_Value); is_field { named = true - call_symbol, ok = resolve_call_arg_type_expression(ast_context, field.value) - if !ok { - break next_fn + if ident, is_ident := field.field.derived.(^ast.Ident); is_ident && ident.name == "nil" { + is_call_arg_nil = true + ok = true + } else { + call_symbol, ok = resolve_call_arg_type_expression(ast_context, field.value) + if !ok { + break next_fn + } } if ident, is_ident := field.field.derived.(^ast.Ident); is_ident { @@ -747,7 +768,12 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou log.error("Expected name parameter after starting named parmeter phase") return {}, false } - call_symbol, ok = resolve_call_arg_type_expression(ast_context, call_arg) + if ident, is_ident := call_arg.derived.(^ast.Ident); is_ident && ident.name == "nil" { + is_call_arg_nil = true + ok = true + } else { + call_symbol, ok = resolve_call_arg_type_expression(ast_context, call_arg) + } } if !ok { @@ -786,6 +812,15 @@ resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Grou break next_fn } + if is_call_arg_nil { + if is_valid_nil_symbol(arg_symbol) { + continue + } else { + break next_fn + } + + } + if !is_symbol_same_typed(ast_context, call_symbol, arg_symbol, proc_arg.flags) { found := false // Are we a union variant diff --git a/tests/hover_test.odin b/tests/hover_test.odin index 9d65d8c..b2af26a 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -5028,6 +5028,27 @@ ast_hover_proc_overload_basic_type_alias :: proc(t: ^testing.T) { } test.expect_hover(t, &source, "test.foo :: proc(i: int)") } + +@(test) +ast_hover_proc_overload_nil_pointer :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + import "my_package" + + foo_int :: proc(i: int) {} + foo_ptr :: proc(s: ^string) {} + foo :: proc { + foo_int, + foo_ptr, + } + + main :: proc() { + f{*}oo(nil) + } + `, + } + test.expect_hover(t, &source, "test.foo :: proc(s: ^string)") +} /* Waiting for odin fix |