diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-06-12 18:06:21 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-06-13 15:23:36 -0400 |
| commit | 20b4d31f49be2f74a3a34d3177f018d358ef2cf8 (patch) | |
| tree | 16c27a841e3f24ab32d4b24dadd25c9872134a3e | |
| parent | 8816d531da666959b7df0c64401b8fa064b0cd3d (diff) | |
Correctly handle pointer types
| -rw-r--r-- | src/server/analysis.odin | 16 | ||||
| -rw-r--r-- | tests/type_definition_test.odin | 122 |
2 files changed, 133 insertions, 5 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 9e43467..5cd290d 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -813,8 +813,7 @@ resolve_location_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex return {}, false } - // TODO: there is likely more of these that will be needed as well. - // I think we'll need a better way to manage this all + // TODO: there is likely more of these that will need to be added #partial switch n in node.derived { case ^ast.Ident: if _, ok := common.keyword_map[n.name]; ok { @@ -825,6 +824,10 @@ resolve_location_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex return {}, true case ^ast.Array_Type: return resolve_location_type_expression(ast_context, n.elem) + case ^ast.Pointer_Type: + return resolve_location_type_expression(ast_context, n.elem) + case ^ast.Comp_Lit: + return resolve_location_type_expression(ast_context, n.type) } return resolve_type_expression(ast_context, node) } @@ -2024,8 +2027,7 @@ resolve_unresolved_symbol :: proc(ast_context: ^AstContext, symbol: ^Symbol) -> // Resolves the location of the underlying type of the identifier resolve_location_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (Symbol, bool) { - // TODO: will likely need to clean this up and find a way for this flow to make sense. - // Ideally we need a way to extract the full symbol of a global + // TODO: Will also likely need to add more cases here as they come up if local, ok := get_local(ast_context^, node); ok { #partial switch n in local.rhs.derived { case ^ast.Ident: @@ -2038,8 +2040,14 @@ resolve_location_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide } case ^ast.Selector_Expr: return resolve_selector_expression(ast_context, n) + case ^ast.Pointer_Type: + return resolve_location_type_expression(ast_context, n.elem) + case ^ast.Unary_Expr: + return resolve_location_type_expression(ast_context, n.expr) } } else if global, ok := ast_context.globals[node.name]; ok { + // Ideally we'd have a way to extract the full symbol of a global, but for now + // this seems to work. We may need to add more cases though. if v, ok := global.expr.derived.(^ast.Proc_Lit); ok { if symbol, ok := resolve_type_expression(ast_context, global.name_expr); ok { return symbol, ok diff --git a/tests/type_definition_test.odin b/tests/type_definition_test.odin index 851c2f4..4c0ef58 100644 --- a/tests/type_definition_test.odin +++ b/tests/type_definition_test.odin @@ -73,7 +73,7 @@ ast_type_definition_struct_field_definition_from_use :: proc(t: ^testing.T) { main :: proc() { bar := Bar{} - bar.ba{*}r = "Test" + bar.ba{*}r = Foo{} } `, } @@ -89,6 +89,126 @@ ast_type_definition_struct_field_definition_from_use :: proc(t: ^testing.T) { } @(test) +ast_type_definition_struct_from_rhs_use :: proc(t: ^testing.T) { + source := test.Source{ + main = `package test + Foo :: struct { + foo: string, + } + + Bar :: struct { + bar: Foo, + } + + main :: proc() { + bar := Bar{} + + foo := b{*}ar.bar + } + `, + } + + location := common.Location { + range = { + start = {line = 5, character = 2}, + end = {line = 5, character = 5}, + }, + } + + test.expect_type_definition_locations(t, &source, {location}) +} + +@(test) +ast_type_definition_struct_field_from_rhs_use :: proc(t: ^testing.T) { + source := test.Source{ + main = `package test + Foo :: struct { + foo: string, + } + + Bar :: struct { + bar: Foo, + } + + main :: proc() { + bar := Bar{} + + foo := bar.b{*}ar + } + `, + } + + location := common.Location { + range = { + start = {line = 1, character = 2}, + end = {line = 1, character = 5}, + }, + } + + test.expect_type_definition_locations(t, &source, {location}) +} + +@(test) +ast_type_definition_struct_field_pointer_from_rhs_use :: proc(t: ^testing.T) { + source := test.Source{ + main = `package test + Foo :: struct { + foo: string, + } + + Bar :: struct { + bar: ^Foo, + } + + main :: proc() { + bar := Bar{} + + foo := bar.b{*}ar + } + `, + } + + location := common.Location { + range = { + start = {line = 1, character = 2}, + end = {line = 1, character = 5}, + }, + } + + test.expect_type_definition_locations(t, &source, {location}) +} + +@(test) +ast_type_definition_local_pointer_from_rhs_use :: proc(t: ^testing.T) { + source := test.Source{ + main = `package test + Foo :: struct { + foo: string, + } + + Bar :: struct { + bar: ^Foo, + } + + main :: proc() { + bar := &Bar{} + + foo := b{*}ar.bar + } + `, + } + + location := common.Location { + range = { + start = {line = 5, character = 2}, + end = {line = 5, character = 5}, + }, + } + + test.expect_type_definition_locations(t, &source, {location}) +} + +@(test) ast_type_definition_struct_variable :: proc(t: ^testing.T) { source := test.Source{ main = `package test |