From 7db742dee3f490499f584e9e86d4665e9e523ef4 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Sat, 27 Feb 2021 11:36:19 -0500 Subject: [PATCH] Fix #5295 - offer static methods for completion too in instance mode --- src/Psalm/Codebase.php | 77 ++++++++++--------------- tests/LanguageServer/CompletionTest.php | 37 +++++++++++- 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index 0c22f2d83f3..c26087c27fa 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -1467,8 +1467,7 @@ public function getTypeContextAtPosition(string $file_path, Position $position): */ public function getCompletionItemsForClassishThing(string $type_string, string $gap) : array { - $instance_completion_items = []; - $static_completion_items = []; + $completion_items = []; $type = Type::parseString($type_string); @@ -1480,24 +1479,25 @@ public function getCompletionItemsForClassishThing(string $type_string, string $ foreach ($class_storage->appearing_method_ids as $declaring_method_id) { $method_storage = $this->methods->getStorage($declaring_method_id); - $completion_item = new \LanguageServerProtocol\CompletionItem( - $method_storage->cased_name, - \LanguageServerProtocol\CompletionItemKind::METHOD, - (string)$method_storage, - $method_storage->description, - (string)$method_storage->visibility, - $method_storage->cased_name, - $method_storage->cased_name . (count($method_storage->params) !== 0 ? '($0)' : '()'), - null, - null, - new Command('Trigger parameter hints', 'editor.action.triggerParameterHints') - ); - $completion_item->insertTextFormat = \LanguageServerProtocol\InsertTextFormat::SNIPPET; - - if ($method_storage->is_static) { - $static_completion_items[] = $completion_item; - } else { - $instance_completion_items[] = $completion_item; + if ($method_storage->is_static || $gap === '->') { + $completion_item = new \LanguageServerProtocol\CompletionItem( + $method_storage->cased_name, + \LanguageServerProtocol\CompletionItemKind::METHOD, + (string)$method_storage, + $method_storage->description, + (string)$method_storage->visibility, + $method_storage->cased_name, + $method_storage->cased_name . (count($method_storage->params) !== 0 ? '($0)' : '()'), + null, + null, + new Command('Trigger parameter hints', 'editor.action.triggerParameterHints'), + null, + 2 + ); + + $completion_item->insertTextFormat = \LanguageServerProtocol\InsertTextFormat::SNIPPET; + + $completion_items[] = $completion_item; } } @@ -1506,25 +1506,21 @@ public function getCompletionItemsForClassishThing(string $type_string, string $ $declaring_class . '::$' . $property_name ); - $completion_item = new \LanguageServerProtocol\CompletionItem( - '$' . $property_name, - \LanguageServerProtocol\CompletionItemKind::PROPERTY, - $property_storage->getInfo(), - $property_storage->description, - (string)$property_storage->visibility, - $property_name, - ($gap === '::' ? '$' : '') . $property_name - ); - - if ($property_storage->is_static) { - $static_completion_items[] = $completion_item; - } else { - $instance_completion_items[] = $completion_item; + if ($property_storage->is_static || $gap === '->') { + $completion_items[] = new \LanguageServerProtocol\CompletionItem( + '$' . $property_name, + \LanguageServerProtocol\CompletionItemKind::PROPERTY, + $property_storage->getInfo(), + $property_storage->description, + (string)$property_storage->visibility, + $property_name, + ($gap === '::' ? '$' : '') . $property_name + ); } } foreach ($class_storage->constants as $const_name => $const) { - $static_completion_items[] = new \LanguageServerProtocol\CompletionItem( + $completion_items[] = new \LanguageServerProtocol\CompletionItem( $const_name, \LanguageServerProtocol\CompletionItemKind::VARIABLE, 'const ' . $const_name, @@ -1541,15 +1537,6 @@ public function getCompletionItemsForClassishThing(string $type_string, string $ } } - if ($gap === '->') { - $completion_items = $instance_completion_items; - } else { - $completion_items = array_merge( - $instance_completion_items, - $static_completion_items - ); - } - return $completion_items; } @@ -1713,7 +1700,7 @@ public function getCompletionItemsForPartialSymbol( $function_name . (count($function->params) !== 0 ? '($0)' : '()'), null, null, - null, + new Command('Trigger parameter hints', 'editor.action.triggerParameterHints'), null, 2 ); diff --git a/tests/LanguageServer/CompletionTest.php b/tests/LanguageServer/CompletionTest.php index 5a6f729c5e5..ca28e6d0925 100644 --- a/tests/LanguageServer/CompletionTest.php +++ b/tests/LanguageServer/CompletionTest.php @@ -1390,7 +1390,6 @@ function my_func(string $arg_a, bool $arg_b) : string { public function testTypeContextForFunctionArgumentWithWhiteSpace(): void { - $codebase = $this->project_analyzer->getCodebase(); $config = $codebase->config; $config->throw_exception = false; @@ -1413,6 +1412,42 @@ function my_func(string $arg_a, bool $arg_b) : string { $this->assertSame('bool', (string) $type); } + public function testCallStaticInInstance(): void + { + $codebase = $this->project_analyzer->getCodebase(); + $config = $codebase->config; + $config->throw_exception = false; + + $this->addFile( + 'somefile.php', + ' + } + + public static function bar() : void {} + + public function baz() : void {} + }' + ); + + $codebase = $this->project_analyzer->getCodebase(); + + $codebase->file_provider->openFile('somefile.php'); + $codebase->scanFiles(); + $this->analyzeFile('somefile.php', new Context()); + + $completion_data = $codebase->getCompletionDataAtPosition('somefile.php', new Position(4, 31)); + + $this->assertSame(['Foo&static', '->', 129], $completion_data); + + $completion_items = $codebase->getCompletionItemsForClassishThing($completion_data[0], $completion_data[1]); + + $this->assertCount(3, $completion_items); + } + public function testCompletionsForType(): void { $codebase = $this->project_analyzer->getCodebase();