aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2024-05-11 21:34:45 +0200
committerDanielGavin <danielgavin5@hotmail.com>2024-05-11 21:34:45 +0200
commit1d2df42baa781a4838393b533601af35f9e30246 (patch)
treec8d1777dc588f8f63f4f49f6f3a56755e5d23d0b
parentf06cf17a90e8f181e8717588e1398efb06b802cc (diff)
Fix issues with the local evaluation of generic function in value decl, since we can't lazily evaluate it.
-rw-r--r--src/server/analysis.odin7
-rw-r--r--src/server/generics.odin16
-rw-r--r--tests/completions_test.odin110
3 files changed, 129 insertions, 4 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 2f6f20e..ce84579 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1308,7 +1308,8 @@ internal_resolve_type_identifier :: proc(
signature = node.name,
pkg = ast_context.current_package,
value = SymbolUntypedValue{type = .Bool},
- }, true
+ },
+ true
case:
return {
type = .Keyword,
@@ -1316,7 +1317,8 @@ internal_resolve_type_identifier :: proc(
name = ident.name,
pkg = ast_context.current_package,
value = SymbolBasicValue{ident = ident},
- }, true
+ },
+ true
}
}
@@ -3029,6 +3031,7 @@ get_generic_assignment :: proc(
ast_context.call = old_call
}
+ //We have to resolve early and can't rely on lazy evalutation because it can have multiple returns.
if symbol, ok := resolve_type_expression(ast_context, v.expr); ok {
if procedure, ok := symbol.value.(SymbolProcedureValue); ok {
for ret in procedure.return_types {
diff --git a/src/server/generics.odin b/src/server/generics.odin
index 329a244..a2393d0 100644
--- a/src/server/generics.odin
+++ b/src/server/generics.odin
@@ -351,31 +351,47 @@ find_and_replace_poly_type :: proc(
case ^ast.Matrix_Type:
if expr, ok := is_in_poly_map(v.elem, poly_map); ok {
v.elem = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
if expr, ok := is_in_poly_map(v.column_count, poly_map); ok {
v.column_count = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
if expr, ok := is_in_poly_map(v.row_count, poly_map); ok {
v.row_count = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
case ^ast.Dynamic_Array_Type:
if expr, ok := is_in_poly_map(v.elem, poly_map); ok {
v.elem = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
case ^ast.Array_Type:
if expr, ok := is_in_poly_map(v.elem, poly_map); ok {
v.elem = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
if expr, ok := is_in_poly_map(v.len, poly_map); ok {
v.len = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
case ^ast.Multi_Pointer_Type:
if expr, ok := is_in_poly_map(v.elem, poly_map); ok {
v.elem = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
case ^ast.Pointer_Type:
if expr, ok := is_in_poly_map(v.elem, poly_map); ok {
v.elem = expr
+ v.pos.file = expr.pos.file
+ v.end.file = expr.end.file
}
}
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index cde8ffd..fc0cc5c 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -481,7 +481,7 @@ ast_swizzle_completion :: proc(t: ^testing.T) {
t,
&source,
".",
- {
+ {
"x: f32",
"y: f32",
"z: f32",
@@ -2657,6 +2657,112 @@ ast_simple_bit_field_completion :: proc(t: ^testing.T) {
t,
&source,
".",
- {"My_Bit_Field.one: int", "My_Bit_Field.two: int", "My_Bit_Field.three: int"},
+ {
+ "My_Bit_Field.one: int",
+ "My_Bit_Field.two: int",
+ "My_Bit_Field.three: int",
+ },
+ )
+}
+
+
+@(test)
+ast_generics_function_with_struct_same_pkg :: proc(t: ^testing.T) {
+ packages := make([dynamic]test.Package)
+
+ append(
+ &packages,
+ test.Package {
+ pkg = "my_package",
+ source = `package my_package
+ DummyFunction :: proc(value: $T/[dynamic]$E, index: int) -> ^E
+ {
+ return &value[index]
+ }
+ `,
+ },
+ )
+
+ source := test.Source {
+ main = `package main
+ import "my_package"
+
+ CoolStruct :: struct
+ {
+ val1, val2, val3: int,
+ }
+
+ main :: proc()
+ {
+ testArray : [dynamic]CoolStruct
+
+ //no completion on function or new value
+ newValue := my_package.DummyFunction(testArray, 10)
+ newValue.{*}
+ }
+ `,
+ packages = packages[:],
+ }
+
+ test.expect_completion_details(
+ t,
+ &source,
+ ".",
+ {
+ "CoolStruct.val1: int",
+ "CoolStruct.val2: int",
+ "CoolStruct.val3: int",
+ },
+ )
+}
+
+
+@(test)
+ast_generics_function_with_struct_diff_pkg :: proc(t: ^testing.T) {
+ packages := make([dynamic]test.Package)
+
+ append(
+ &packages,
+ test.Package {
+ pkg = "my_package",
+ source = `package my_package
+ DummyFunction :: proc(value: $T/[dynamic]$E, index: int) -> ^E
+ {
+ return &value[index]
+ }
+
+ CoolStruct :: struct
+ {
+ val1, val2, val3: int,
+ }
+ `,
+ },
+ )
+
+ source := test.Source {
+ main = `package main
+ import "my_package"
+
+ main :: proc()
+ {
+ testArray : [dynamic]my_package.CoolStruct
+
+ //no completion on function or new value
+ newValue := my_package.DummyFunction(testArray, 10)
+ newValue.{*}
+ }
+ `,
+ packages = packages[:],
+ }
+
+ test.expect_completion_details(
+ t,
+ &source,
+ ".",
+ {
+ "CoolStruct.val1: int",
+ "CoolStruct.val2: int",
+ "CoolStruct.val3: int",
+ },
)
}