aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-03 09:17:09 -0400
committerBrad Lewis <22850972+BradLewis@users.noreply.github.com>2025-08-03 09:17:09 -0400
commit21df3b2d793448f445bc67e2d99b1f3b1f56042b (patch)
tree3713c2ea161e10b659274786b092412bfcf35c6b /src
parent526b55af850b8ee6a64b5f9ffe074bf708d0f655 (diff)
Improve and consolidate resolving implicit selector comp literals
Diffstat (limited to 'src')
-rw-r--r--src/server/analysis.odin110
-rw-r--r--src/server/completion.odin167
2 files changed, 101 insertions, 176 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 264dfe6..581a326 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -2009,15 +2009,68 @@ get_field_value_name :: proc(field_value: ^ast.Field_Value) -> (string, bool) {
return "", false
}
+get_struct_comp_lit_type :: proc(
+ position_context: ^DocumentPositionContext,
+ comp_lit: ^ast.Comp_Lit,
+ s: SymbolStructValue,
+ field_name: string,
+) -> ^ast.Expr {
+ elem_index := -1
+
+ for elem, i in comp_lit.elems {
+ if position_in_node(elem, position_context.position) {
+ elem_index = i
+ if field_value, ok := elem.derived.(^ast.Field_Value); ok {
+ // If our field is another comp_lit, check to see if we're actually in that one
+ if cl, ok := field_value.value.derived.(^ast.Comp_Lit); ok {
+ if type := get_struct_comp_lit_type(
+ position_context,
+ cl,
+ s,
+ field_name,
+ ); type != nil {
+ return type
+ }
+ }
+ }
+ }
+ }
+
+ if elem_index == -1 {
+ return nil
+ }
+
+ 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 && elem_index != -1 {
+ type = s.types[elem_index]
+ }
+
+ return type
+}
+
+
resolve_implicit_selector_comp_literal :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,
symbol: Symbol,
- field_name: string,
) -> (
Symbol,
bool,
) {
+ field_name := ""
+ if position_context.field_value != nil {
+ field_name, _ = get_field_value_name(position_context.field_value)
+ }
if comp_symbol, comp_lit, ok := resolve_type_comp_literal(
ast_context,
position_context,
@@ -2025,34 +2078,12 @@ resolve_implicit_selector_comp_literal :: proc(
position_context.parent_comp_lit,
); ok {
#partial switch v in comp_symbol.value {
- case SymbolEnumValue:
+ case SymbolEnumValue, SymbolBitSetValue:
return comp_symbol, ok
case SymbolStructValue:
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 v.names {
- if name != field_name {
- continue
- }
-
- type = v.types[i]
- break
- }
-
- if type == nil && elem_index != -1 && len(v.types) > elem_index {
- type = v.types[elem_index]
- }
+ type := get_struct_comp_lit_type(position_context, comp_lit, v, field_name)
return resolve_type_expression(ast_context, type)
case SymbolBitFieldValue:
@@ -2161,15 +2192,9 @@ resolve_implicit_selector :: proc(
}
}
- if position_context.comp_lit != nil &&
- position_context.parent_comp_lit != nil &&
- position_context.parent_comp_lit.type != nil {
- if position_context.field_value != nil {
- if field_name, ok := get_field_value_name(position_context.field_value); ok {
- if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok {
- return resolve_implicit_selector_comp_literal(ast_context, position_context, symbol, field_name)
- }
- }
+ if position_context.comp_lit != nil && position_context.parent_comp_lit != nil {
+ if symbol, ok := resolve_comp_literal(ast_context, position_context); ok {
+ return resolve_implicit_selector_comp_literal(ast_context, position_context, symbol)
}
}
@@ -2179,9 +2204,7 @@ resolve_implicit_selector :: proc(
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, symbol, field_name)
- }
+ return resolve_implicit_selector_comp_literal(ast_context, position_context, symbol)
}
}
}
@@ -2223,14 +2246,11 @@ resolve_implicit_selector :: proc(
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 resolve_implicit_selector_comp_literal(
+ ast_context,
+ position_context,
+ current_symbol,
+ )
}
return current_symbol, ok
}
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 4c39d04..a854f7d 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -889,23 +889,21 @@ get_implicit_completion :: proc(
}
} else if v, ok := symbol.value.(SymbolStructValue); ok {
if position_context.field_value != nil {
- if field_name, ok := get_field_value_name(position_context.field_value); ok {
- if symbol, ok := resolve_implicit_selector_comp_literal(ast_context, position_context, symbol, field_name); ok {
- if enum_value, ok := symbol.value.(SymbolEnumValue); ok {
- for name in enum_value.names {
- if position_context.comp_lit != nil && field_exists_in_comp_lit(position_context.comp_lit, name) {
- continue
- }
- item := CompletionItem {
- label = name,
- kind = .EnumMember,
- detail = name,
- }
- append(results, CompletionResult{completion_item = item})
+ if symbol, ok := resolve_implicit_selector_comp_literal(ast_context, position_context, symbol); ok {
+ if enum_value, ok := symbol.value.(SymbolEnumValue); ok {
+ for name in enum_value.names {
+ if position_context.comp_lit != nil && field_exists_in_comp_lit(position_context.comp_lit, name) {
+ continue
}
-
- return is_incomplete
+ item := CompletionItem {
+ label = name,
+ kind = .EnumMember,
+ detail = name,
+ }
+ append(results, CompletionResult{completion_item = item})
}
+
+ return is_incomplete
}
}
}
@@ -1030,81 +1028,37 @@ get_implicit_completion :: proc(
}
}
}
+
+ //infer bitset and enums based on the identifier comp_lit, i.e. a := My_Struct { my_ident = . }
+ if position_context.comp_lit != nil && position_context.parent_comp_lit != nil {
+ if symbol, ok := resolve_comp_literal(ast_context, position_context); ok {
+ if comp_symbol, ok := resolve_implicit_selector_comp_literal(ast_context, position_context, symbol); ok {
+ if enum_value, ok := comp_symbol.value.(SymbolEnumValue); ok {
+ for enum_name in enum_value.names {
+ item := CompletionItem {
+ label = enum_name,
+ kind = .EnumMember,
+ detail = enum_name,
+ }
- //infer bitset and enums based on the identifier comp_lit, i.e. a := My_Struct { my_ident = . }
- if position_context.comp_lit != nil {
- if position_context.parent_comp_lit != nil {
- field_name: string
+ append(results, CompletionResult{completion_item = item})
+ }
- if position_context.field_value != nil {
- if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok {
- field_name = field.name
- } else {
return is_incomplete
- }
- }
-
- if symbol, ok := resolve_comp_literal(ast_context, position_context); 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)
-
- type := get_struct_comp_lit_type(position_context, comp_lit, s, field_name)
-
- if enum_value, ok := unwrap_enum(ast_context, type); ok {
- for enum_name in enum_value.names {
- item := CompletionItem {
- label = enum_name,
- kind = .EnumMember,
- detail = enum_name,
- }
-
- append(results, CompletionResult{completion_item = item})
- }
-
- return is_incomplete
- } else if bitset_symbol, ok := resolve_type_expression(ast_context, type); ok {
- set_ast_package_set_scoped(ast_context, bitset_symbol.pkg)
-
- if value, ok := unwrap_bitset(ast_context, bitset_symbol); ok {
- for name in value.names {
-
- item := CompletionItem {
- label = name,
- kind = .EnumMember,
- detail = name,
- }
-
- append(results, CompletionResult{completion_item = item})
- }
- return is_incomplete
- }
+ } else if s, ok := unwrap_bitset(ast_context, comp_symbol); ok {
+ for enum_name in s.names {
+ item := CompletionItem {
+ label = enum_name,
+ kind = .EnumMember,
+ detail = enum_name,
}
- } else {
- set_ast_package_set_scoped(ast_context, comp_symbol.pkg)
- if s, ok := unwrap_bitset(ast_context, comp_symbol); ok {
- for enum_name in s.names {
- item := CompletionItem {
- label = enum_name,
- kind = .EnumMember,
- detail = enum_name,
- }
- append(results, CompletionResult{completion_item = item})
- }
-
- return is_incomplete
- }
+ append(results, CompletionResult{completion_item = item})
}
+
+ return is_incomplete
}
}
-
- reset_ast_context(ast_context)
}
}
@@ -1337,55 +1291,6 @@ get_implicit_completion :: proc(
return is_incomplete
}
-get_struct_comp_lit_type :: proc(
- position_context: ^DocumentPositionContext,
- comp_lit: ^ast.Comp_Lit,
- s: SymbolStructValue,
- field_name: string,
-) -> ^ast.Expr {
- elem_index := -1
-
- for elem, i in comp_lit.elems {
- if position_in_node(elem, position_context.position) {
- elem_index = i
- if field_value, ok := elem.derived.(^ast.Field_Value); ok {
- // If our field is another comp_lit, check to see if we're actually in that one
- if cl, ok := field_value.value.derived.(^ast.Comp_Lit); ok {
- if type := get_struct_comp_lit_type(
- position_context,
- cl,
- s,
- field_name,
- ); type != nil {
- return type
- }
- }
- }
- }
- }
-
- if elem_index == -1 {
- return nil
- }
-
- 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 && elem_index != -1 {
- type = s.types[elem_index]
- }
-
- return type
-}
-
get_identifier_completion :: proc(
ast_context: ^AstContext,
position_context: ^DocumentPositionContext,