From 207fe98a46b28297755608904dbf08d06fc50970 Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Tue, 12 Mar 2024 00:27:26 +0100 Subject: Support completion and gotos for comp literals in procs --- src/server/analysis.odin | 41 ++++++++++++++++++++++--- src/server/completion.odin | 74 +++++++++++++++++++-------------------------- tests/completions_test.odin | 25 +++++++++++++++ tests/definition_test.odin | 30 ++++++++++++++++++ 4 files changed, 123 insertions(+), 47 deletions(-) diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 2e3839c..e3857c1 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1690,10 +1690,43 @@ resolve_comp_literal :: proc( symbol: Symbol, ok: bool, ) { - symbol = resolve_type_expression( - ast_context, - position_context.parent_comp_lit.type, - ) or_return + if position_context.parent_comp_lit.type != nil { + symbol = resolve_type_expression( + ast_context, + position_context.parent_comp_lit.type, + ) or_return + } else if position_context.call != nil { + if call_expr, ok := position_context.call.derived.(^ast.Call_Expr); + ok { + arg_index := 0 + for arg, i in call_expr.args { + if position_in_node(arg, position_context.position) { + arg_index = i + break + } + } + + symbol = resolve_type_expression( + ast_context, + position_context.call, + ) or_return + + value := symbol.value.(SymbolProcedureValue) or_return + + if len(value.arg_types) <= arg_index { + return {}, false + } + + if value.arg_types[arg_index].type == nil { + return {}, false + } + + symbol = resolve_type_expression( + ast_context, + value.arg_types[arg_index].type, + ) or_return + } + } symbol, _ = resolve_type_comp_literal( ast_context, diff --git a/src/server/completion.odin b/src/server/completion.odin index 2f5c1ce..eb83432 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -222,57 +222,45 @@ get_comp_lit_completion :: proc( ) { items := make([dynamic]CompletionItem, context.temp_allocator) - if position_context.parent_comp_lit.type == nil { - return - } - if symbol, ok := resolve_type_expression( - ast_context, - position_context.parent_comp_lit.type, - ); ok { - if comp_symbol, _, ok := resolve_type_comp_literal( - ast_context, - position_context, - symbol, - position_context.parent_comp_lit, - ); ok { - ast_context.current_package = comp_symbol.pkg - #partial switch v in comp_symbol.value { - case SymbolStructValue: - for name, i in v.names { - if name == "_" { + if symbol, ok := resolve_comp_literal(ast_context, position_context); ok { + //ast_context.current_package = comp_symbol.pkg + #partial switch v in symbol.value { + case SymbolStructValue: + for name, i in v.names { + if name == "_" { + continue + } + + ast_context.current_package = symbol.pkg + + if resolved, ok := resolve_type_expression( + ast_context, + v.types[i], + ); ok { + if field_exists_in_comp_lit( + position_context.comp_lit, + name, + ) { continue } - ast_context.current_package = comp_symbol.pkg - - if resolved, ok := resolve_type_expression( - ast_context, - v.types[i], - ); ok { - if field_exists_in_comp_lit( - position_context.comp_lit, + item := CompletionItem { + label = name, + kind = .Field, + detail = fmt.tprintf( + "%v.%v: %v", + symbol.name, name, - ) { - continue - } - - item := CompletionItem { - label = name, - kind = .Field, - detail = fmt.tprintf( - "%v.%v: %v", - comp_symbol.name, - name, - common.node_to_string(v.types[i]), - ), - documentation = resolved.doc, - } - - append(&items, item) + common.node_to_string(v.types[i]), + ), + documentation = resolved.doc, } + + append(&items, item) } } + } } diff --git a/tests/completions_test.odin b/tests/completions_test.odin index 0330137..962e944 100644 --- a/tests/completions_test.odin +++ b/tests/completions_test.odin @@ -2607,3 +2607,28 @@ ast_poly_proc_matrix_whole :: proc(t: ^testing.T) { ) } + + +ast_completion_comp_lit_in_proc :: proc(t: ^testing.T) { + packages := make([dynamic]test.Package) + + source := test.Source { + main = `package test + My_Struct :: struct { + one: int, + two: int, + } + + my_function :: proc(my_struct: My_Struct) { + + } + + main :: proc() { + my_function({on{*}}) + } + `, + packages = {}, + } + + test.expect_completion_details(t, &source, "", {"My_Struct.one: int"}) +} diff --git a/tests/definition_test.odin b/tests/definition_test.odin index 6f4b982..bf9fcd7 100644 --- a/tests/definition_test.odin +++ b/tests/definition_test.odin @@ -59,3 +59,33 @@ ast_goto_comp_lit_field_indexed :: proc(t: ^testing.T) { test.expect_definition_locations(t, &source, {location}) } + +@(test) +ast_goto_untyped_comp_lit_in_proc :: proc(t: ^testing.T) { + source := test.Source { + main = `package test + My_Struct :: struct { + one: int, + two: int, + } + + my_function :: proc(my_struct: My_Struct) { + + } + + main :: proc() { + my_function({on{*}e = 2, two = 3}) + } + `, + packages = {}, + } + + location := common.Location { + range = { + start = {line = 2, character = 4}, + end = {line = 2, character = 7}, + }, + } + + test.expect_definition_locations(t, &source, {location}) +} -- cgit v1.2.3