aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-07-07 15:25:22 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-07-07 15:27:22 -0400
commitaacea4ab65367e73fe31452981486038beb101e0 (patch)
tree8ebf6ecf19e5506fdf73ba9876664b6bc90ef5b3 /src/server
parenteaed0e849f9f8be82703e8c9cc37540939216b12 (diff)
Correctly resolve references when returning a struct
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin202
1 files changed, 110 insertions, 92 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index b91840e..c1d3038 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -1787,6 +1787,96 @@ resolve_comp_literal :: proc(
return symbol, true
}
+// Used to get the name of the field for resolving the implicit selectors
+get_field_value_name :: proc(field_value: ^ast.Field_Value) ->(string, bool) {
+ if field, ok := field_value.field.derived.(^ast.Ident); ok {
+ return field.name, true
+ } else if field, ok := field_value.field.derived.(^ast.Implicit_Selector_Expr); ok {
+ return field.field.name, true
+ }
+ return "", false
+}
+
+resolve_implicit_selector_comp_literal :: proc(
+ ast_context: ^AstContext,
+ position_context: ^DocumentPositionContext,
+ symbol: Symbol,
+ field_name: string,
+) -> (Symbol, bool) {
+ if comp_symbol, comp_lit, ok := resolve_type_comp_literal(
+ ast_context,
+ position_context,
+ symbol,
+ position_context.parent_comp_lit,
+ ); ok {
+ if s, ok := comp_symbol.value.(SymbolStructValue); ok {
+ set_ast_package_set_scoped(ast_context, comp_symbol.pkg)
+
+ //We can either have the final
+ elem_index := -1
+
+ for elem, i in comp_lit.elems {
+ if position_in_node(elem, position_context.position) {
+ elem_index = i
+ }
+ }
+
+ type: ^ast.Expr
+
+ for name, i in s.names {
+ if name != field_name {
+ continue
+ }
+
+ type = s.types[i]
+ break
+ }
+
+ if type == nil && len(s.types) > elem_index {
+ type = s.types[elem_index]
+ }
+
+ return resolve_type_expression(ast_context, type)
+ } else if s, ok := comp_symbol.value.(SymbolBitFieldValue); ok {
+ set_ast_package_set_scoped(ast_context, comp_symbol.pkg)
+
+ //We can either have the final
+ elem_index := -1
+
+ for elem, i in comp_lit.elems {
+ if position_in_node(elem, position_context.position) {
+ elem_index = i
+ }
+ }
+
+ type: ^ast.Expr
+
+ for name, i in s.names {
+ if name != field_name {
+ continue
+ }
+
+ type = s.types[i]
+ break
+ }
+
+ if type == nil && len(s.types) > elem_index {
+ type = s.types[elem_index]
+ }
+
+ return resolve_type_expression(ast_context, type)
+ } else if s, ok := comp_symbol.value.(SymbolFixedArrayValue); ok {
+ //This will be a comp_lit for an enumerated array
+ //EnumIndexedArray :: [TestEnum]u32 {
+ // .valueOne = 1,
+ // .valueTwo = 2,
+ //}
+ return resolve_type_expression(ast_context, s.len)
+ }
+ }
+ return {}, false
+}
+
resolve_implicit_selector :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,
@@ -1856,102 +1946,19 @@ resolve_implicit_selector :: proc(
}
}
- if position_context.value_decl != nil && position_context.value_decl.type != nil {
- return resolve_type_expression(ast_context, position_context.value_decl.type)
- }
-
- if position_context.comp_lit != nil {
- if position_context.parent_comp_lit.type == nil {
+ if position_context.comp_lit != nil && position_context.parent_comp_lit.type != nil {
+ if position_context.field_value == nil {
return {}, false
}
-
- field_name: string
-
- if position_context.field_value != nil {
- if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok {
- field_name = field.name
- } else if field, ok := position_context.field_value.field.derived.(^ast.Implicit_Selector_Expr); ok {
- field_name = field.field.name
- } else {
- return {}, false
- }
+ field_name, ok := get_field_value_name(position_context.field_value)
+ if !ok {
+ return {}, false
}
-
if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok {
- if comp_symbol, comp_lit, ok := resolve_type_comp_literal(
- ast_context,
- position_context,
- symbol,
- position_context.parent_comp_lit,
- ); ok {
- if s, ok := comp_symbol.value.(SymbolStructValue); ok {
- set_ast_package_set_scoped(ast_context, comp_symbol.pkg)
-
- //We can either have the final
- elem_index := -1
-
- for elem, i in comp_lit.elems {
- if position_in_node(elem, position_context.position) {
- elem_index = i
- }
- }
-
- type: ^ast.Expr
-
- for name, i in s.names {
- if name != field_name {
- continue
- }
-
- type = s.types[i]
- break
- }
-
- if type == nil && len(s.types) > elem_index {
- type = s.types[elem_index]
- }
-
- return resolve_type_expression(ast_context, type)
- } else if s, ok := comp_symbol.value.(SymbolBitFieldValue); ok {
- set_ast_package_set_scoped(ast_context, comp_symbol.pkg)
-
- //We can either have the final
- elem_index := -1
-
- for elem, i in comp_lit.elems {
- if position_in_node(elem, position_context.position) {
- elem_index = i
- }
- }
-
- type: ^ast.Expr
-
- for name, i in s.names {
- if name != field_name {
- continue
- }
-
- type = s.types[i]
- break
- }
-
- if type == nil && len(s.types) > elem_index {
- type = s.types[elem_index]
- }
-
- return resolve_type_expression(ast_context, type)
- } else if s, ok := comp_symbol.value.(SymbolFixedArrayValue); ok {
- /*
- This will be a comp_lit for an enumerated array
- EnumIndexedArray :: [TestEnum]u32 {
- .valueOne = 1,
- .valueTwo = 2,
- }
- */
- return resolve_type_expression(ast_context, s.len)
- }
- }
+ return resolve_implicit_selector_comp_literal(
+ ast_context, position_context, symbol, field_name,
+ )
}
}
@@ -1978,7 +1985,18 @@ resolve_implicit_selector :: proc(
}
if len(position_context.function.type.results.list) > return_index {
- return resolve_type_expression(ast_context, position_context.function.type.results.list[return_index].type)
+ current_symbol, ok := resolve_type_expression(ast_context, position_context.function.type.results.list[return_index].type)
+ if !ok {
+ return {}, false
+ }
+ if position_context.parent_comp_lit != nil && position_context.field_value != nil {
+ if field_name, ok := get_field_value_name(position_context.field_value); ok {
+ return resolve_implicit_selector_comp_literal(
+ ast_context, position_context, current_symbol, field_name,
+ )
+ }
+ }
+ return current_symbol, ok
}
}