aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/analysis.odin56
-rw-r--r--tests/hover_test.odin50
2 files changed, 97 insertions, 9 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 1e570b4..8e1d7f0 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -340,25 +340,43 @@ are_symbol_basic_same_keywords :: proc(a, b: Symbol) -> bool {
if are_keyword_aliases(a.name, b.name) {
return true
}
- if a.name != b.name {
+ a_value, a_ok := a.value.(SymbolBasicValue)
+ if !a_ok {
return false
}
- if _, ok := a.value.(SymbolBasicValue); !ok {
+
+ b_value, b_ok := b.value.(SymbolBasicValue)
+ if !b_ok {
return false
}
- if _, ok := b.value.(SymbolBasicValue); !ok {
+ if a_value.ident.name != b_value.ident.name {
return false
}
- if _, ok := keyword_map[a.name]; !ok {
+ if _, ok := keyword_map[a_value.ident.name]; !ok {
return false
}
- if _, ok := keyword_map[b.name]; !ok {
+ if _, ok := keyword_map[b_value.ident.name]; !ok {
return false
}
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 {
@@ -718,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
@@ -726,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 {
@@ -744,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 {
@@ -783,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 3063d13..b2af26a 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -4999,6 +4999,56 @@ ast_hover_proc_overload_generic_map :: proc(t: ^testing.T) {
}
test.expect_hover(t, &source, "test.clear :: proc(m: ^$T/map[$K]$V)")
}
+
+@(test)
+ast_hover_proc_overload_basic_type_alias :: proc(t: ^testing.T) {
+ packages := make([dynamic]test.Package, context.temp_allocator)
+
+ append(&packages, test.Package{pkg = "my_package", source = `package my_package
+ Bar :: int
+ `})
+
+ source := test.Source {
+ main = `package test
+ import "my_package"
+
+ foo_int :: proc(i: int) {}
+ foo_string :: proc(s: string) {}
+ foo :: proc {
+ foo_int,
+ foo_string,
+ }
+
+ main :: proc() {
+ bar: my_package.Bar
+ f{*}oo(bar)
+ }
+ `,
+ packages = packages[:],
+ }
+ 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