diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2024-05-11 21:34:45 +0200 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2024-05-11 21:34:45 +0200 |
| commit | 1d2df42baa781a4838393b533601af35f9e30246 (patch) | |
| tree | c8d1777dc588f8f63f4f49f6f3a56755e5d23d0b | |
| parent | f06cf17a90e8f181e8717588e1398efb06b802cc (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.odin | 7 | ||||
| -rw-r--r-- | src/server/generics.odin | 16 | ||||
| -rw-r--r-- | tests/completions_test.odin | 110 |
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", + }, ) } |