Skip to content

Commit b890cfb

Browse files
authored
phpactorGH-2603: Do not filter static method invocations and variadic (phpactor#2635)
1 parent eadaa21 commit b890cfb

File tree

5 files changed

+71
-27
lines changed

5 files changed

+71
-27
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ Improvements:
1111

1212
- Fix contextual completion in constructor agrument position #2504
1313
- Basic support for `array_reduce` stub #2576
14+
- Support variadics in contextual completion #2603
1415

1516
Bug fixes:
1617

18+
- Only filter new object expression names in contextual completion #2603
1719
- Fixing include and exclude patterns #2593 @mamazu
1820

1921
## 2024-03-09

lib/Completion/Bridge/WorseReflection/Completor/ContextSensitiveCompletor.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ public function __construct(private TolerantCompletor $inner, private Reflector
3535
public function complete(Node $node, TextDocument $source, ByteOffset $offset): Generator
3636
{
3737
$generator = $this->inner->complete($node, $source, $offset);
38+
if (
39+
!$node instanceof CallExpression &&
40+
($node instanceof QualifiedName && !$node->parent instanceof ObjectCreationExpression)
41+
) {
42+
yield from $generator;
43+
return $generator->getReturn();
44+
}
3845

3946
$type = $this->resolveFilterableType($node, $source, $offset);
4047
if (null === $type) {
@@ -77,6 +84,7 @@ private function resolveFilterableType(Node $node, TextDocument $source, ByteOff
7784
{
7885
$argumentNb = 0;
7986
$memberAccessOrObjectCreation = $node;
87+
$node = NodeUtil::firstDescendantNodeBeforeOffset($node, $offset->toInt());
8088
if ($node instanceof QualifiedName) {
8189
$memberAccessOrObjectCreation = null;
8290
$argumentExpression = $node->getFirstAncestor(ArgumentExpression::class);
@@ -89,9 +97,10 @@ private function resolveFilterableType(Node $node, TextDocument $source, ByteOff
8997
$memberAccessOrObjectCreation = $list->parent;
9098
}
9199
}
92-
if ($node instanceof ArgumentExpressionList) {
93-
$argumentNb = count(iterator_to_array($node->getValues()));
94-
$memberAccessOrObjectCreation = $node->parent;
100+
$argumentList = $node->getFirstAncestor(ArgumentExpressionList::class);
101+
if ($argumentList instanceof ArgumentExpressionList) {
102+
$argumentNb = max(0, count(iterator_to_array($argumentList->getValues())) - 1);
103+
$memberAccessOrObjectCreation = $argumentList->parent;
95104
}
96105

97106
if (!$memberAccessOrObjectCreation instanceof CallExpression && !$memberAccessOrObjectCreation instanceof ObjectCreationExpression) {
@@ -103,7 +112,6 @@ private function resolveFilterableType(Node $node, TextDocument $source, ByteOff
103112
return null;
104113
}
105114
try {
106-
;
107115
$memberAccessOrObjectCreation = $this->reflector->reflectOffset($source, $offset)->nodeContext();
108116
} catch (NotFound $e) {
109117
return null;
@@ -155,7 +163,14 @@ private function typeFromParameters(ReflectionParameterCollection $parameters, i
155163
{
156164
$parameter = $parameters->at($argumentNb);
157165
if (null === $parameter) {
158-
return null;
166+
$lastParameter = $parameters->lastOrNull();
167+
if (null === $lastParameter) {
168+
return null;
169+
}
170+
if (!$lastParameter->isVariadic()) {
171+
return null;
172+
}
173+
$parameter = $lastParameter;
159174
}
160175

161176
$type = $parameter->type();

lib/Completion/Tests/Unit/Bridge/WorseReflection/Completor/ContextSensitiveCompletorTest.php

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ class Obj {}
6060
class Foo { public function bar(Obj $obj){}}
6161
6262
$f = new Foo();
63-
$f->bar(<>)
63+
$f->bar(new <>)
6464
EOT,
6565
[
6666
'Bar\Obj',
6767
],
6868
];
69-
yield 'namespaced open method call' => [
69+
yield 'static call returns all' => [
7070
[
7171
'Bar\Foo',
7272
'Bar\Obj',
@@ -78,7 +78,26 @@ class Obj {}
7878
class Foo { public function bar(Obj $obj){}}
7979
8080
$f = new Foo();
81-
$f->bar(<>
81+
$f->bar(F<>)
82+
EOT,
83+
[
84+
'Bar\Foo',
85+
'Bar\Obj',
86+
],
87+
];
88+
yield 'namespaced method call' => [
89+
[
90+
'Bar\Foo',
91+
'Bar\Obj',
92+
],
93+
<<<'EOT'
94+
<?php
95+
namespace Bar;
96+
class Obj {}
97+
class Foo { public function bar(Obj $obj){}}
98+
99+
$f = new Foo();
100+
$f->bar(new <>)
82101
EOT,
83102
[
84103
'Bar\Obj',
@@ -95,7 +114,7 @@ class Obj {}
95114
class Foo { public function bar(Obj $obj){}}
96115
97116
$f = new Foo();
98-
$f->bar(<>
117+
$f->bar(new <>)
99118
EOT,
100119
[
101120
'Obj',
@@ -112,7 +131,7 @@ class Obj {}
112131
class Foo { public function bar(Obj $obj){}}
113132
114133
$f = new Foo();
115-
$f->bar(O<>
134+
$f->bar(new O<>
116135
EOT,
117136
[
118137
'Obj',
@@ -129,7 +148,7 @@ class Obj {}
129148
class Foo { public function bar($obj){}}
130149
131150
$f = new Foo();
132-
$f->bar(O<>
151+
$f->bar(new O<>
133152
EOT,
134153
[
135154
'Foo',
@@ -148,12 +167,13 @@ class Baz {}
148167
class Foo { public function bar(Obj $obj, Baz $baz){}}
149168
150169
$f = new Foo();
151-
$f->bar(Obj::new(),<>
170+
$f->bar(Obj::new(), new <>)
152171
EOT,
153172
[
154173
'Baz',
155174
],
156175
];
176+
157177
yield '2nd arg partial' => [
158178
[
159179
'Obj',
@@ -166,7 +186,7 @@ class Baz {}
166186
class Foo { public function bar(Obj $obj, Baz $baz){}}
167187
168188
$f = new Foo();
169-
$f->bar(Obj::new(),B<>
189+
$f->bar(Obj::new(),new B<>
170190
EOT,
171191
[
172192
'Baz',
@@ -184,20 +204,20 @@ class Baz {}
184204
class Foo { public function bar(Obj $obj, Baz ...$baz){}}
185205
186206
$f = new Foo();
187-
$f->bar(Obj::new(),B<>
207+
$f->bar(Obj::new(),new B<>
188208
EOT,
189209
[
190210
'Baz',
191211
],
192212
];
193-
yield 'new' => [
213+
yield 'enum' => [
194214
[
195215
'Obj',
196216
'Baz',
197217
],
198218
<<<'EOT'
199219
<?php
200-
class Obj {}
220+
enum Obj {}
201221
class Baz {}
202222
class Foo { public function bar(Obj $obj, Baz ...$baz){}}
203223
@@ -208,7 +228,7 @@ class Foo { public function bar(Obj $obj, Baz ...$baz){}}
208228
'Obj',
209229
],
210230
];
211-
yield 'enum' => [
231+
yield 'on static call' => [
212232
[
213233
'Obj',
214234
'Baz',
@@ -217,16 +237,15 @@ class Foo { public function bar(Obj $obj, Baz ...$baz){}}
217237
<?php
218238
enum Obj {}
219239
class Baz {}
220-
class Foo { public function bar(Obj $obj, Baz ...$baz){}}
240+
class Foo { public static function bar(Obj $obj, Baz ...$baz){}}
221241
222-
$f = new Foo();
223-
$f->bar(new O<>
242+
Foo::bar(new O<>
224243
EOT,
225244
[
226245
'Obj',
227246
],
228247
];
229-
yield 'static' => [
248+
yield 'on variadic' => [
230249
[
231250
'Obj',
232251
'Baz',
@@ -235,9 +254,9 @@ class Foo { public function bar(Obj $obj, Baz ...$baz){}}
235254
<?php
236255
enum Obj {}
237256
class Baz {}
238-
class Foo { public static function bar(Obj $obj, Baz ...$baz){}}
257+
class Foo { public static function bar(Obj ...$objz){}}
239258
240-
Foo::bar(new O<>
259+
Foo::bar(new Obj(), new Obj(), new O<>)
241260
EOT,
242261
[
243262
'Obj',

lib/Indexer/Model/IndexJob.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
namespace Phpactor\Indexer\Model;
44

55
use Generator;
6-
use Phar;
7-
use PharFileInfo;
86
use Phpactor\TextDocument\TextDocumentBuilder;
9-
use RecursiveIteratorIterator;
107
use SplFileInfo;
11-
use UnexpectedValueException;
128

139
class IndexJob
1410
{

lib/WorseReflection/Core/Reflection/Collection/AbstractReflectionCollection.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,18 @@ public function last()
116116
return end($this->items);
117117
}
118118

119+
/**
120+
* @return T|null
121+
*/
122+
public function lastOrNull()
123+
{
124+
if (empty($this->items)) {
125+
return null;
126+
}
127+
128+
return end($this->items);
129+
}
130+
119131
public function has(string $name): bool
120132
{
121133
return isset($this->items[$name]);

0 commit comments

Comments
 (0)