diff options
| author | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-07 15:25:22 -0400 |
|---|---|---|
| committer | Brad Lewis <22850972+BradLewis@users.noreply.github.com> | 2025-07-07 15:27:22 -0400 |
| commit | aacea4ab65367e73fe31452981486038beb101e0 (patch) | |
| tree | 8ebf6ecf19e5506fdf73ba9876664b6bc90ef5b3 /src | |
| parent | eaed0e849f9f8be82703e8c9cc37540939216b12 (diff) | |
Correctly resolve references when returning a struct
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/analysis.odin | 202 |
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 } } |