Skip to content
This repository was archived by the owner on Jul 18, 2018. It is now read-only.

Commit df088b4

Browse files
roblourenslialan
authored andcommitted
Fix variable type from method return value, add tests (felixfbecker#393)
1 parent f323f15 commit df088b4

File tree

53 files changed

+264
-61
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+264
-61
lines changed
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
class FooClass {
4+
public function foo(): FooClass {
5+
return $this;
6+
}
7+
}
8+
9+
$fc = new FooClass();
10+
$foo = $fc->foo();
11+
$foo->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
class FooClass {
4+
public static function staticFoo(): FooClass {
5+
return new FooClass();
6+
}
7+
8+
public function bar() { }
9+
}
10+
11+
$foo = FooClass::staticFoo();
12+
$foo->

src/DefinitionResolver.php

+10
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,16 @@ public function resolveExpressionNodeToType($expr)
633633
}
634634
}
635635

636+
// MEMBER CALL EXPRESSION/SCOPED PROPERTY CALL EXPRESSION
637+
// The type of the member/scoped property call expression is the type of the method, so resolve the
638+
// type of the callable expression.
639+
if ($expr instanceof Node\Expression\CallExpression && (
640+
$expr->callableExpression instanceof Node\Expression\MemberAccessExpression ||
641+
$expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression)
642+
) {
643+
return $this->resolveExpressionNodeToType($expr->callableExpression);
644+
}
645+
636646
// MEMBER ACCESS EXPRESSION
637647
if ($expr instanceof Node\Expression\MemberAccessExpression) {
638648
if ($expr->memberName instanceof Node\Expression) {

tests/LanguageServerTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function testIndexingWithDirectFileAccess()
5757
if ($msg->body->method === 'window/logMessage' && $promise->state === Promise::PENDING) {
5858
if ($msg->body->params->type === MessageType::ERROR) {
5959
$promise->reject(new Exception($msg->body->params->message));
60-
} else if (strpos($msg->body->params->message, 'All 27 PHP files parsed') !== false) {
60+
} else if (preg_match('/All \d+ PHP files parsed/', $msg->body->params->message)) {
6161
$promise->fulfill();
6262
}
6363
}
@@ -103,7 +103,7 @@ public function testIndexingWithFilesAndContentRequests()
103103
if ($promise->state === Promise::PENDING) {
104104
$promise->reject(new Exception($msg->body->params->message));
105105
}
106-
} else if (strpos($msg->body->params->message, 'All 27 PHP files parsed') !== false) {
106+
} else if (preg_match('/All \d+ PHP files parsed/', $msg->body->params->message)) {
107107
$promise->fulfill();
108108
}
109109
}

tests/Server/TextDocument/CompletionTest.php

+44
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,50 @@ public function testBarePhp()
499499
], true), $items);
500500
}
501501

502+
public function testMethodReturnType()
503+
{
504+
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/method_return_type.php');
505+
$this->loader->open($completionUri, file_get_contents($completionUri));
506+
$items = $this->textDocument->completion(
507+
new TextDocumentIdentifier($completionUri),
508+
new Position(10, 6)
509+
)->wait();
510+
$this->assertCompletionsListSubset(new CompletionList([
511+
new CompletionItem(
512+
'foo',
513+
CompletionItemKind::METHOD,
514+
'\FooClass',
515+
null,
516+
null,
517+
null,
518+
null,
519+
null
520+
)
521+
], true), $items);
522+
}
523+
524+
public function testStaticMethodReturnType()
525+
{
526+
$completionUri = pathToUri(__DIR__ . '/../../../fixtures/completion/static_method_return_type.php');
527+
$this->loader->open($completionUri, file_get_contents($completionUri));
528+
$items = $this->textDocument->completion(
529+
new TextDocumentIdentifier($completionUri),
530+
new Position(11, 6)
531+
)->wait();
532+
$this->assertCompletionsListSubset(new CompletionList([
533+
new CompletionItem(
534+
'bar',
535+
CompletionItemKind::METHOD,
536+
'mixed',
537+
null,
538+
null,
539+
null,
540+
null,
541+
null
542+
)
543+
], true), $items);
544+
}
545+
502546
private function assertCompletionsListSubset(CompletionList $subsetList, CompletionList $list)
503547
{
504548
foreach ($subsetList->items as $expectedItem) {

tests/Validation/ValidationTest.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,7 @@ private function getTestValuesFromDefs($definitions): array
132132
} elseif ($propertyName === 'extends') {
133133
$definition->$propertyName = $definition->$propertyName ?? [];
134134
} elseif ($propertyName === 'type' && $definition->type !== null) {
135-
// Class info is not captured by json_encode. It's important for 'type'.
136-
$defsForAssert[$fqn]['type__class'] = get_class($definition->type);
135+
$defsForAssert[$fqn]['type__tostring'] = (string)$definition->type;
137136
}
138137

139138
$defsForAssert[$fqn][$propertyName] = $definition->$propertyName;

tests/Validation/cases/WithReturnTypehints.php.expected.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
},
7070
"containerName": "Fixtures\\Prophecy\\WithReturnTypehints"
7171
},
72-
"type__class": "phpDocumentor\\Reflection\\Types\\Object_",
72+
"type__tostring": "\\self",
7373
"type": {},
7474
"declarationLine": "public function getSelf(): self {",
7575
"documentation": null
@@ -88,7 +88,7 @@
8888
},
8989
"containerName": "Fixtures\\Prophecy\\WithReturnTypehints"
9090
},
91-
"type__class": "phpDocumentor\\Reflection\\Types\\String_",
91+
"type__tostring": "string",
9292
"type": {},
9393
"declarationLine": "public function getName(): string {",
9494
"documentation": null
@@ -107,7 +107,7 @@
107107
},
108108
"containerName": "Fixtures\\Prophecy\\WithReturnTypehints"
109109
},
110-
"type__class": "phpDocumentor\\Reflection\\Types\\Object_",
110+
"type__tostring": "\\parent",
111111
"type": {},
112112
"declarationLine": "public function getParent(): parent {",
113113
"documentation": null

tests/Validation/cases/arrayValueShouldBeBoolean.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"containerName": "A"
3535
},
36-
"type__class": "phpDocumentor\\Reflection\\Types\\Array_",
36+
"type__tostring": "string[]",
3737
"type": {},
3838
"declarationLine": "protected $foo;",
3939
"documentation": null

tests/Validation/cases/classDefinition1.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "TestNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Integer",
61+
"type__tostring": "int",
6262
"type": {},
6363
"declarationLine": "public $a;",
6464
"documentation": null

tests/Validation/cases/classProperty1.php.expected.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "TestNamespace\\TestClass"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "public $testProperty;",
6464
"documentation": null
@@ -77,7 +77,7 @@
7777
},
7878
"containerName": "TestNamespace\\TestClass"
7979
},
80-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
80+
"type__tostring": "mixed",
8181
"type": {},
8282
"declarationLine": "public function testMethod($testParameter)",
8383
"documentation": null

tests/Validation/cases/constants.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "public static function suite()",
6464
"documentation": null

tests/Validation/cases/constants2.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "public static function suite()",
6464
"documentation": null

tests/Validation/cases/constants3.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "public static function suite()",
6464
"documentation": null

tests/Validation/cases/constants4.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "public function suite()",
6464
"documentation": null

tests/Validation/cases/constants5.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
},
5656
"containerName": "MyNamespace\\Mbstring"
5757
},
58-
"type__class": "phpDocumentor\\Reflection\\Types\\Object_",
58+
"type__tostring": "\\MyNamespace\\PHP_INT_MAX",
5959
"type": {},
6060
"declarationLine": "const MB_CASE_FOLD = PHP_INT_MAX;",
6161
"documentation": null

tests/Validation/cases/constantsInFunctionParamDefault.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
},
3838
"containerName": "A"
3939
},
40-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
40+
"type__tostring": "mixed",
4141
"type": {},
4242
"declarationLine": "function b ($a = MY_CONSTANT);",
4343
"documentation": null

tests/Validation/cases/magicConsts.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
},
3838
"containerName": "A"
3939
},
40-
"type__class": "phpDocumentor\\Reflection\\Types\\Array_",
40+
"type__tostring": "\\__CLASS__[]",
4141
"type": {},
4242
"declarationLine": "private static $deprecationsTriggered;",
4343
"documentation": null

tests/Validation/cases/memberAccess1.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "static function a() {",
6464
"documentation": null

tests/Validation/cases/memberAccess2.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
},
5959
"containerName": "MyNamespace\\A"
6060
},
61-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
61+
"type__tostring": "mixed",
6262
"type": {},
6363
"declarationLine": "static function a() {",
6464
"documentation": null

tests/Validation/cases/memberAccess3.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
},
7474
"containerName": "MyNamespace\\A"
7575
},
76-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
76+
"type__tostring": "mixed",
7777
"type": {},
7878
"declarationLine": "public static function getInitializer(ClassLoader $loader)",
7979
"documentation": null

tests/Validation/cases/memberAccess4.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
},
6565
"containerName": "MyNamespace\\A"
6666
},
67-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
67+
"type__tostring": "mixed",
6868
"type": {},
6969
"declarationLine": "public function testRequest()",
7070
"documentation": null

tests/Validation/cases/memberAccess5.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
},
5656
"containerName": "MyNamespace\\ParseErrorsTest"
5757
},
58-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
58+
"type__tostring": "mixed",
5959
"type": {},
6060
"declarationLine": "public function setUp()",
6161
"documentation": null

tests/Validation/cases/memberCall1.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
},
6262
"containerName": "MyNamespace\\ParseErrorsTest"
6363
},
64-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
64+
"type__tostring": "mixed",
6565
"type": {},
6666
"declarationLine": "public function setAccount(AccountInterface $account)",
6767
"documentation": null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
class FooClass {
4+
public function foo(): FooClass {
5+
return $this;
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"references": {
3+
"FooClass": [
4+
"./methodReturnType.php"
5+
]
6+
},
7+
"definitions": {
8+
"FooClass": {
9+
"fqn": "FooClass",
10+
"extends": [],
11+
"isGlobal": true,
12+
"isStatic": false,
13+
"canBeInstantiated": true,
14+
"symbolInformation": {
15+
"name": "FooClass",
16+
"kind": 5,
17+
"location": {
18+
"uri": "./methodReturnType.php"
19+
},
20+
"containerName": ""
21+
},
22+
"type": null,
23+
"declarationLine": "class FooClass {",
24+
"documentation": null
25+
},
26+
"FooClass->foo()": {
27+
"fqn": "FooClass->foo()",
28+
"extends": [],
29+
"isGlobal": false,
30+
"isStatic": false,
31+
"canBeInstantiated": false,
32+
"symbolInformation": {
33+
"name": "foo",
34+
"kind": 6,
35+
"location": {
36+
"uri": "./methodReturnType.php"
37+
},
38+
"containerName": "FooClass"
39+
},
40+
"type__tostring": "\\FooClass",
41+
"type": {},
42+
"declarationLine": "public function foo(): FooClass {",
43+
"documentation": null
44+
}
45+
}
46+
}

tests/Validation/cases/multipleNamespaces.php.expected.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
},
6565
"containerName": "MyNamespace1\\B"
6666
},
67-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
67+
"type__tostring": "mixed",
6868
"type": {},
6969
"declarationLine": "function b() {",
7070
"documentation": null
@@ -121,7 +121,7 @@
121121
},
122122
"containerName": "MyNamespace2\\A"
123123
},
124-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
124+
"type__tostring": "mixed",
125125
"type": {},
126126
"declarationLine": "function a () {",
127127
"documentation": null

tests/Validation/cases/multiplePreceedingComments.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"containerName": "Foo"
3535
},
36-
"type__class": "phpDocumentor\\Reflection\\Types\\Object_",
36+
"type__tostring": "\\Iterator",
3737
"type": {},
3838
"declarationLine": "public function fn()",
3939
"documentation": "Foo"

tests/Validation/cases/nameToken.php.expected.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"containerName": "A"
3535
},
36-
"type__class": "phpDocumentor\\Reflection\\Types\\Mixed",
36+
"type__tostring": "mixed",
3737
"type": {},
3838
"declarationLine": "function b() {",
3939
"documentation": null

0 commit comments

Comments
 (0)