diff --git a/src/server/completion.odin b/src/server/completion.odin index d80e451f..2fcd7bed 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -772,99 +772,7 @@ get_selector_completion :: proc( case SymbolFixedArrayValue: is_incomplete = true append_magic_array_like_completion(position_context, selector, results) - - containsColor := 1 - containsCoord := 1 - - expr_len := 0 - - if v.len != nil { - if basic, ok := v.len.derived.(^ast.Basic_Lit); ok { - if expr_len, ok = strconv.parse_int(basic.tok.text); !ok { - expr_len = 0 - } - } - } - - if field != "" { - for i := 0; i < len(field); i += 1 { - c := field[i] - if _, ok := swizzle_color_map[c]; ok { - containsColor += 1 - } else if _, ok := swizzle_coord_map[c]; ok { - containsCoord += 1 - } else { - return is_incomplete - } - } - } - - if containsColor == 1 && containsCoord == 1 { - save := expr_len - for k in swizzle_color_components { - if expr_len <= 0 { - break - } - - expr_len -= 1 - - item := CompletionItem { - label = fmt.tprintf("%v%v", field, k), - kind = .Property, - detail = fmt.tprintf("%v%v: %v", field, k, node_to_string(v.expr)), - } - append(results, CompletionResult{completion_item = item}) - } - - expr_len = save - - for k in swizzle_coord_components { - if expr_len <= 0 { - break - } - - expr_len -= 1 - - item := CompletionItem { - label = fmt.tprintf("%v%v", field, k), - kind = .Property, - detail = fmt.tprintf("%v%v: %v", field, k, node_to_string(v.expr)), - } - append(results, CompletionResult{completion_item = item}) - } - } - - if containsColor > 1 { - for k in swizzle_color_components { - if expr_len <= 0 { - break - } - - expr_len -= 1 - - item := CompletionItem { - label = fmt.tprintf("%v%v", field, k), - kind = .Property, - detail = fmt.tprintf("%v%v: [%v]%v", field, k, containsColor, node_to_string(v.expr)), - } - append(results, CompletionResult{completion_item = item}) - } - } else if containsCoord > 1 { - for k in swizzle_coord_components { - if expr_len <= 0 { - break - } - - expr_len -= 1 - - item := CompletionItem { - label = fmt.tprintf("%v%v", field, k), - kind = .Property, - detail = fmt.tprintf("%v%v: [%v]%v", field, k, containsCoord, node_to_string(v.expr)), - } - append(results, CompletionResult{completion_item = item}) - } - } + add_fixed_array_selector_completions(v, field, results) add_soa_field_completion(ast_context, selector, v.expr, v.len, results, selector.name) case SymbolUnionValue: is_incomplete = false @@ -971,6 +879,13 @@ get_selector_completion :: proc( is_incomplete = false for name, i in v.names { if name == "_" { + if is_struct_field_using(v, i) { + if symbol, ok := resolve_type_expression(ast_context, v.types[i]); ok { + if value, ok := symbol.value.(SymbolFixedArrayValue); ok { + add_fixed_array_selector_completions(value, field, results) + } + } + } continue } @@ -991,6 +906,12 @@ get_selector_completion :: proc( construct_struct_field_symbol(&symbol, selector.name, v, i) append(results, CompletionResult{symbol = symbol}) + + if is_struct_field_using(v, i) { + if value, ok := symbol.value.(SymbolFixedArrayValue); ok { + add_fixed_array_selector_completions(value, field, results) + } + } } else { //just give some generic symbol with name. item := CompletionItem { @@ -1084,6 +1005,105 @@ get_selector_completion :: proc( return is_incomplete } +add_fixed_array_selector_completions :: proc( + v: SymbolFixedArrayValue, + field: string, + results: ^[dynamic]CompletionResult, +) { + containsColor := 1 + containsCoord := 1 + + expr_len := 0 + + if v.len != nil { + if basic, ok := v.len.derived.(^ast.Basic_Lit); ok { + if expr_len, ok = strconv.parse_int(basic.tok.text); !ok { + expr_len = 0 + } + } + } + + if field != "" { + for i := 0; i < len(field); i += 1 { + c := field[i] + if _, ok := swizzle_color_map[c]; ok { + containsColor += 1 + } else if _, ok := swizzle_coord_map[c]; ok { + containsCoord += 1 + } else { + return + } + } + } + + if containsColor == 1 && containsCoord == 1 { + save := expr_len + for k in swizzle_color_components { + if expr_len <= 0 { + break + } + + expr_len -= 1 + + item := CompletionItem { + label = fmt.tprintf("%v%v", field, k), + kind = .Property, + detail = fmt.tprintf("%v%v: %v", field, k, node_to_string(v.expr)), + } + append(results, CompletionResult{completion_item = item}) + } + + expr_len = save + + for k in swizzle_coord_components { + if expr_len <= 0 { + break + } + + expr_len -= 1 + + item := CompletionItem { + label = fmt.tprintf("%v%v", field, k), + kind = .Property, + detail = fmt.tprintf("%v%v: %v", field, k, node_to_string(v.expr)), + } + append(results, CompletionResult{completion_item = item}) + } + } + + if containsColor > 1 { + for k in swizzle_color_components { + if expr_len <= 0 { + break + } + + expr_len -= 1 + + item := CompletionItem { + label = fmt.tprintf("%v%v", field, k), + kind = .Property, + detail = fmt.tprintf("%v%v: [%v]%v", field, k, containsColor, node_to_string(v.expr)), + } + append(results, CompletionResult{completion_item = item}) + } + } else if containsCoord > 1 { + for k in swizzle_coord_components { + if expr_len <= 0 { + break + } + + expr_len -= 1 + + item := CompletionItem { + label = fmt.tprintf("%v%v", field, k), + kind = .Property, + detail = fmt.tprintf("%v%v: [%v]%v", field, k, containsCoord, node_to_string(v.expr)), + } + append(results, CompletionResult{completion_item = item}) + } + } +} + get_implicit_completion :: proc( ast_context: ^AstContext, position_context: ^DocumentPositionContext, diff --git a/src/server/symbol.odin b/src/server/symbol.odin index a5b8690d..956eaa9d 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -412,10 +412,8 @@ write_struct_type :: proc( } } } - s := Symbol{ - - } + s: Symbol if _, ok := get_attribute_objc_class_name(attributes); ok { b.symbol.flags |= {.ObjC} if get_attribute_objc_is_class_method(attributes) { @@ -629,6 +627,15 @@ expand_objc :: proc(ast_context: ^AstContext, b: ^SymbolStructValueBuilder) { } } +is_struct_field_using :: proc(v: SymbolStructValue, index: int) -> bool { + for i in v.usings { + if i == index { + return true + } + } + return false +} + get_proc_arg_count :: proc(v: SymbolProcedureValue) -> int { total := 0 for proc_arg in v.arg_types { diff --git a/tests/completions_test.odin b/tests/completions_test.odin index 3c34603c..6e1eba64 100644 --- a/tests/completions_test.odin +++ b/tests/completions_test.odin @@ -5238,3 +5238,39 @@ ast_completion_proc_arg_default_enum_alias :: proc(t: ^testing.T) { } test.expect_completion_docs(t, &source, "", {"A", "B"}) } + +@(test) +ast_completion_struct_using_anonymous_vector_types :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + Foo :: struct { + using _: [3]f32, + } + + main :: proc() { + foo: Foo + foo.{*} + } + + `, + } + test.expect_completion_docs(t, &source, "", {"r: f32", "x: f32"}) +} + +@(test) +ast_completion_struct_using_named_vector_types :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + Foo :: struct { + using bar: [3]f32, + } + + main :: proc() { + foo: Foo + foo.{*} + } + + `, + } + test.expect_completion_docs(t, &source, "", {"Foo.bar: [3]f32", "r: f32", "x: f32"}) +}