aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-09 09:45:33 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-09 10:11:41 -0400
commit5b4b6564584ccf544f5fe7e0ce9bafd2e77cdd09 (patch)
tree1f35776123ece621ad6309a142379c18a1b30467
parent3e183972229782baefc269d8ca940a60caad83c1 (diff)
Implement method to resolve poly return types based on the types of local variables
-rw-r--r--src/server/analysis.odin88
-rw-r--r--src/server/generics.odin5
-rw-r--r--src/server/symbol.odin4
-rw-r--r--tests/hover_test.odin35
4 files changed, 88 insertions, 44 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 47722e8..85a784e 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1586,62 +1586,62 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide
if global, ok := ast_context.globals[node.name];
ast_context.current_package == ast_context.document_package && ok {
return resolve_global_identifier(ast_context, node, &global)
- } else {
- switch node.name {
- case "context":
- for built in indexer.builtin_packages {
- if symbol, ok := lookup("Context", built); ok {
- symbol.type = .Variable
- return symbol, ok
- }
- }
- }
-
+ }
- //right now we replace the package ident with the absolute directory name, so it should have '/' which is not a valid ident character
- if strings.contains(node.name, "/") {
- symbol := Symbol {
- type = .Package,
- pkg = node.name,
- value = SymbolPackageValue{},
+ switch node.name {
+ case "context":
+ for built in indexer.builtin_packages {
+ if symbol, ok := lookup("Context", built); ok {
+ symbol.type = .Variable
+ return symbol, ok
}
+ }
+ }
- try_build_package(symbol.pkg)
- return symbol, true
+ //right now we replace the package ident with the absolute directory name, so it should have '/' which is not a valid ident character
+ if strings.contains(node.name, "/") {
+ symbol := Symbol {
+ type = .Package,
+ pkg = node.name,
+ value = SymbolPackageValue{},
}
- is_runtime := strings.contains(ast_context.current_package, "base/runtime")
+ try_build_package(symbol.pkg)
- if is_runtime {
- if symbol, ok := lookup(node.name, "$builtin"); ok {
- return resolve_symbol_return(ast_context, symbol)
- }
- }
+ return symbol, true
+ }
+
+ is_runtime := strings.contains(ast_context.current_package, "base/runtime")
- //last option is to check the index
- if symbol, ok := lookup(node.name, ast_context.current_package); ok {
+ if is_runtime {
+ if symbol, ok := lookup(node.name, "$builtin"); ok {
return resolve_symbol_return(ast_context, symbol)
}
+ }
- if !is_runtime {
- if symbol, ok := lookup(node.name, "$builtin"); ok {
- return resolve_symbol_return(ast_context, symbol)
- }
+ //last option is to check the index
+ if symbol, ok := lookup(node.name, ast_context.current_package); ok {
+ return resolve_symbol_return(ast_context, symbol)
+ }
+
+ if !is_runtime {
+ if symbol, ok := lookup(node.name, "$builtin"); ok {
+ return resolve_symbol_return(ast_context, symbol)
}
+ }
- for built in indexer.builtin_packages {
- if symbol, ok := lookup(node.name, built); ok {
- return resolve_symbol_return(ast_context, symbol)
- }
+ for built in indexer.builtin_packages {
+ if symbol, ok := lookup(node.name, built); ok {
+ return resolve_symbol_return(ast_context, symbol)
}
+ }
- for u in ast_context.usings {
- for imp in ast_context.imports {
- if strings.compare(imp.name, u.pkg_name) == 0 {
- if symbol, ok := lookup(node.name, imp.name); ok {
- return resolve_symbol_return(ast_context, symbol)
- }
+ for u in ast_context.usings {
+ for imp in ast_context.imports {
+ if strings.compare(imp.name, u.pkg_name) == 0 {
+ if symbol, ok := lookup(node.name, imp.name); ok {
+ return resolve_symbol_return(ast_context, symbol)
}
}
}
@@ -1720,6 +1720,8 @@ resolve_local_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, loca
return_symbol, ok = resolve_function_overload(ast_context, v^)
case ^ast.Array_Type:
return_symbol, ok = make_symbol_array_from_ast(ast_context, v^, node), true
+ case ^ast.Multi_Pointer_Type:
+ return_symbol, ok = make_symbol_multi_pointer_from_ast(ast_context, v^, node), true
case ^ast.Dynamic_Array_Type:
return_symbol, ok = make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
case ^ast.Matrix_Type:
@@ -3549,8 +3551,6 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co
result_i := min(len(results) - 1, i)
str := get_ast_node_string(name, file.src)
- call := false
-
store_local(
ast_context,
name,
@@ -3558,7 +3558,7 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co
value_decl.end.offset,
str,
ast_context.non_mutable_only,
- calls[result_i] or_else false,
+ false, // calls[result_i] or_else false, // TODO: find a good way to handle this
value_decl.is_mutable,
get_package_from_node(results[result_i]^),
false,
diff --git a/src/server/generics.odin b/src/server/generics.odin
index 1802efb..a629d3e 100644
--- a/src/server/generics.odin
+++ b/src/server/generics.odin
@@ -494,6 +494,7 @@ resolve_generic_function_symbol :: proc(
if symbol, ok := resolve_type_expression(ast_context, call_expr.args[i]); ok {
file := strings.trim_prefix(symbol.uri, "file://")
+
if file == "" {
file = call_expr.args[i].pos.file
}
@@ -522,6 +523,10 @@ resolve_generic_function_symbol :: proc(
}
}
+ // We set the offset so we can find it as a local if it's based on the type of a local var
+ symbol_expr.pos.offset = call_expr.pos.offset
+ symbol_expr.end.offset = call_expr.end.offset
+
symbol_expr = clone_expr(symbol_expr, ast_context.allocator, nil)
param_type := clone_expr(param.type, ast_context.allocator, nil)
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index a41a310..fbf4a54 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -773,6 +773,10 @@ symbol_to_expr :: proc(symbol: Symbol, file: string, allocator := context.temp_a
case SymbolBitFieldValue:
type := new_type(ast.Bit_Field_Type, pos, end, allocator)
return type
+ case SymbolMultiPointerValue:
+ type := new_type(ast.Multi_Pointer_Type, pos, end, allocator)
+ type.elem = v.expr
+ return type
case:
return nil
}
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index edba279..9a43587 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -3590,6 +3590,41 @@ ast_hover_parapoly_proc_dynamic_array_elems :: proc(t: ^testing.T) {
"test.elem: ^$T"
)
}
+
+@(test)
+ast_hover_parapoly_proc_slice_param :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ foo :: proc(x: $T) -> T {
+ return x
+ }
+
+ main :: proc() {
+ x : []u8
+ b{*}ar := foo(x)
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.bar: []u8")
+}
+
+@(test)
+ast_hover_parapoly_proc_multi_pointer_param :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package test
+ foo :: proc(x: ^$T) -> ^T {
+ return x
+ }
+
+
+ main :: proc() {
+ x : [^]u8
+ b{*}ar := foo(x)
+ }
+ `,
+ }
+ test.expect_hover(t, &source, "test.bar: ^[^]u8")
+}
/*
Waiting for odin fix