From 9652ef501f0085fd5e335427de95482625b2d1ea Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Sat, 6 Apr 2024 14:25:02 +0200 Subject: Fix issues with objc completion and hover --- src/odin/printer/visit.odin | 5 +++ src/server/analysis.odin | 30 +++++++++----- src/server/completion.odin | 4 ++ src/server/hover.odin | 20 ++++++++- tests/objc_test.odin | 98 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 11 deletions(-) diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin index 92ebd92..1dac999 100644 --- a/src/odin/printer/visit.odin +++ b/src/odin/printer/visit.odin @@ -577,6 +577,11 @@ is_values_nestable_if_break_assign :: proc(list: []^ast.Expr) -> bool { #partial switch v in expr.derived { case ^ast.Call_Expr, ^ast.Comp_Lit, ^ast.Or_Return_Expr: return true + case ^ast.Unary_Expr: + #partial switch v2 in v.expr.derived { + case ^ast.Call_Expr: + return true + } } } return false diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 7ffc177..7f77958 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -961,7 +961,12 @@ internal_resolve_type_expression :: proc( v.expr, ); ok { ast_context.use_locals = false - ast_context.current_package = selector.pkg + + if selector.pkg != "" { + ast_context.current_package = selector.pkg + } else { + ast_context.current_package = ast_context.document_package + } #partial switch s in selector.value { case SymbolProcedureValue: @@ -982,6 +987,12 @@ internal_resolve_type_expression :: proc( ); ok { ast_context.use_locals = false + if selector.pkg != "" { + ast_context.current_package = selector.pkg + } else { + ast_context.current_package = ast_context.document_package + } + #partial switch s in selector.value { case SymbolFixedArrayValue: components_count := 0 @@ -1039,18 +1050,13 @@ internal_resolve_type_expression :: proc( ) selector_expr.expr = s.return_types[0].type selector_expr.field = v.field + return internal_resolve_type_expression( ast_context, selector_expr, ) } case SymbolStructValue: - if selector.pkg != "" { - ast_context.current_package = selector.pkg - } else { - ast_context.current_package = ast_context.document_package - } - for name, i in s.names { if v.field != nil && name == v.field.name { ast_context.field_name = v.field^ @@ -1063,8 +1069,6 @@ internal_resolve_type_expression :: proc( } } case SymbolPackageValue: - ast_context.current_package = selector.pkg - try_build_package(ast_context.current_package) if v.field != nil { @@ -4865,10 +4869,16 @@ get_document_position_node :: proc( case ^Selector_Call_Expr: if position_context.hint == .Definition || position_context.hint == .Hover || - position_context.hint == .SignatureHelp { + position_context.hint == .SignatureHelp || + position_context.hint == .Completion { position_context.selector = n.expr position_context.field = n.call position_context.selector_expr = cast(^Selector_Expr)node + + if _, ok := n.call.derived.(^ast.Call_Expr); ok { + position_context.call = n.call + } + get_document_position(n.expr, position_context) get_document_position(n.call, position_context) diff --git a/src/server/completion.odin b/src/server/completion.odin index c10a48b..e09aa0a 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -1099,6 +1099,10 @@ get_implicit_completion :: proc( ok && parameter_ok { ast_context.current_package = symbol.pkg + if .ObjC in symbol.flags { + parameter_index += 1 + } + if proc_value, ok := symbol.value.(SymbolProcedureValue); ok { if len(proc_value.arg_types) <= parameter_index { return diff --git a/src/server/hover.odin b/src/server/hover.odin index be6adad..c3dccbc 100644 --- a/src/server/hover.odin +++ b/src/server/hover.odin @@ -170,7 +170,9 @@ get_hover_information :: proc( } } - if position_context.selector != nil && position_context.identifier != nil { + if position_context.selector != nil && + position_context.identifier != nil && + position_context.field == position_context.identifier { hover.range = common.get_token_range( position_context.identifier^, ast_context.file.src, @@ -211,6 +213,7 @@ get_hover_information :: proc( } selector: Symbol + selector, ok = resolve_type_expression( &ast_context, position_context.selector, @@ -229,6 +232,21 @@ get_hover_information :: proc( } } + if v, is_proc := selector.value.(SymbolProcedureValue); is_proc { + if len(v.return_types) == 0 || v.return_types[0].type == nil { + return {}, false, false + } + + ast_context.current_package = selector.pkg + + if selector, ok = resolve_type_expression( + &ast_context, + v.return_types[0].type, + ); !ok { + return {}, false, false + } + } + ast_context.current_package = selector.pkg #partial switch v in selector.value { diff --git a/tests/objc_test.odin b/tests/objc_test.odin index c1b38bc..af17c0a 100644 --- a/tests/objc_test.odin +++ b/tests/objc_test.odin @@ -46,3 +46,101 @@ cobj_return_type_with_selector_expression :: proc(t: ^testing.T) { {"Window.initWithContentRect: my_package.Window_initWithContentRect"}, ) } + +@(test) +cobj_return_type_with_selector_expression_2 :: proc(t: ^testing.T) { + packages := make([dynamic]test.Package) + + append( + &packages, + test.Package { + pkg = "my_package", + source = `package my_package + @(objc_class="NSWindow") + Window :: struct { dummy: int} + + @(objc_type=Window, objc_name="alloc", objc_is_class_method=true) + Window_alloc :: proc "c" () -> ^Window { + } + @(objc_type=Window, objc_name="initWithContentRect") + Window_initWithContentRect :: proc (self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: BOOL) -> ^Window { + } + `, + }, + ) + + source := test.Source { + main = `package test + import "my_package" + + main :: proc() { + window := my_package.Window.alloc()->initWithContentRect( + {{0, 0}, {500, 400}}, + {.Titled, .Closable, .Resizable}, + .Buffered, + false, + ) + + window->{*} + } + `, + packages = packages[:], + } + + test.expect_completion_details( + t, + &source, + "->", + {"Window.initWithContentRect: my_package.Window_initWithContentRect"}, + ) +} + + +@(test) +cobj_hover_chained_selector :: proc(t: ^testing.T) { + packages := make([dynamic]test.Package) + + append( + &packages, + test.Package { + pkg = "my_package", + source = `package my_package + @(objc_class="NSWindow") + Window :: struct { dummy: int} + + @(objc_type=Window, objc_name="alloc", objc_is_class_method=true) + Window_alloc :: proc "c" () -> ^Window { + } + @(objc_type=Window, objc_name="initWithContentRect") + Window_initWithContentRect :: proc (self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: BOOL) -> ^Window { + } + + My_Struct :: struct { + dummy: int, + } + `, + }, + ) + + source := test.Source { + main = `package test + import "my_package" + + main :: proc() { + window := my_package.Window.alloc()->initWithConte{*}ntRect( + {{0, 0}, {500, 400}}, + {.Titled, .Closable, .Resizable}, + .Buffered, + false, + ) + } + `, + packages = packages[:], + } + + test.expect_hover( + t, + &source, + "Window.initWithContentRect: proc(self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: BOOL)", + ) +} -- cgit v1.2.3