Skip to content

Commit 08cf1a3

Browse files
sunverwerthfelixfbecker
authored andcommitted
Allow getting type from define() node (felixfbecker#363)
* Allow getting type from define() node - fixes felixfbecker#364 * Add test case for DefinitionResolver
1 parent b1cc7bf commit 08cf1a3

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

src/DefinitionResolver.php

+22-4
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,19 @@ private static function resolveClassNameToType(Node $class): Type
725725
*/
726726
public function getTypeFromNode(Node $node)
727727
{
728+
if (
729+
$node instanceof Node\Expr\FuncCall
730+
&& $node->name instanceof Node\Name
731+
&& strtolower((string)$node->name) === 'define'
732+
&& isset($node->args[0])
733+
&& $node->args[0]->value instanceof Node\Scalar\String_
734+
&& isset($node->args[1])
735+
) {
736+
// constants with define() like
737+
// define('TEST_DEFINE_CONSTANT', false);
738+
return $this->resolveExpressionNodeToType($node->args[1]->value);
739+
}
740+
728741
if ($node instanceof Node\Param) {
729742
// Parameters
730743
$docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock');
@@ -882,11 +895,16 @@ public static function getDefinedFqn(Node $node)
882895
}
883896
return (string)$class->namespacedName . '::' . $node->name;
884897
}
885-
} else if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name && strtolower((string)$node->name) === 'define') {
886-
if (!isset($node->args[0]) || !($node->args[0]->value instanceof Node\Scalar\String_)) {
887-
return null;
888-
}
898+
} else if (
899+
$node instanceof Node\Expr\FuncCall
900+
&& $node->name instanceof Node\Name
901+
&& strtolower((string)$node->name) === 'define'
902+
&& isset($node->args[0])
903+
&& $node->args[0]->value instanceof Node\Scalar\String_
904+
&& isset($node->args[1])
905+
) {
889906
return (string)$node->args[0]->value->value;
890907
}
908+
return null;
891909
}
892910
}

src/Protocol/SymbolInformation.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public static function fromNode(Node $node, string $fqn = null)
5757
&& strtolower((string)$node->name) === 'define'
5858
&& isset($node->args[0])
5959
&& $node->args[0]->value instanceof Node\Scalar\String_
60+
&& isset($node->args[1])
6061
) {
6162
// constants with define() like
6263
// define('TEST_DEFINE_CONSTANT', false);
@@ -90,7 +91,7 @@ public static function fromNode(Node $node, string $fqn = null)
9091
} else {
9192
return null;
9293
}
93-
94+
9495
if (!isset($symbol->name)) {
9596
if ($node instanceof Node\Name) {
9697
$symbol->name = (string)$node;

tests/DefinitionResolverTest.php

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace LanguageServer\Tests;
5+
6+
use PHPUnit\Framework\TestCase;
7+
use LanguageServer\Index\Index;
8+
use LanguageServer\{DefinitionResolver, Parser};
9+
10+
class DefinitionResolverTest extends TestCase
11+
{
12+
public function testCreateDefinitionFromNode()
13+
{
14+
$parser = new Parser;
15+
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
16+
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);
17+
18+
$index = new Index;
19+
$definitionResolver = new DefinitionResolver($index);
20+
$def = $definitionResolver->createDefinitionFromNode($stmts[0], '\TEST_DEFINE');
21+
22+
$this->assertInstanceOf(\phpDocumentor\Reflection\Types\Boolean::class, $def->type);
23+
}
24+
25+
public function testGetTypeFromNode()
26+
{
27+
$parser = new Parser;
28+
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
29+
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);
30+
31+
$index = new Index;
32+
$definitionResolver = new DefinitionResolver($index);
33+
$type = $definitionResolver->getTypeFromNode($stmts[0]);
34+
35+
$this->assertInstanceOf(\phpDocumentor\Reflection\Types\Boolean::class, $type);
36+
}
37+
38+
public function testGetDefinedFqnForIncompleteDefine()
39+
{
40+
// define('XXX') (only one argument) must not introduce a new symbol
41+
$parser = new Parser;
42+
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE');");
43+
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);
44+
45+
$index = new Index;
46+
$definitionResolver = new DefinitionResolver($index);
47+
$fqn = $definitionResolver->getDefinedFqn($stmts[0]);
48+
49+
$this->assertNull($fqn);
50+
}
51+
52+
public function testGetDefinedFqnForDefine()
53+
{
54+
$parser = new Parser;
55+
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
56+
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);
57+
58+
$index = new Index;
59+
$definitionResolver = new DefinitionResolver($index);
60+
$fqn = $definitionResolver->getDefinedFqn($stmts[0]);
61+
62+
$this->assertEquals('TEST_DEFINE', $fqn);
63+
}
64+
}

tests/MockPhpDocument.php

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace LanguageServer\Tests;
5+
6+
/**
7+
* A fake document for tests
8+
*/
9+
class MockPhpDocument
10+
{
11+
/**
12+
* Returns fake uri
13+
*
14+
* @return string
15+
*/
16+
public function getUri()
17+
{
18+
return 'file:///whatever';
19+
}
20+
}

0 commit comments

Comments
 (0)