Skip to content

Commit b1cc7bf

Browse files
jens1ofelixfbecker
authored andcommitted
Support constants with define() (#347)
1 parent de6aed6 commit b1cc7bf

File tree

9 files changed

+126
-57
lines changed

9 files changed

+126
-57
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace HELLO {
4+
5+
/**
6+
* Does something really cool!
7+
*/
8+
function world() {
9+
10+
}
11+
12+
\HE
13+
}
14+
15+
namespace {
16+
17+
/**
18+
* Lorem ipsum dolor sit amet.
19+
*/
20+
define('HELLO', true);
21+
22+
HELLO\world();
23+
}

fixtures/global_symbols.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,10 @@ public function testMethod($testParameter)
9898
};
9999

100100
class ChildClass extends TestClass {}
101+
102+
/**
103+
* Lorem ipsum dolor sit amet, consectetur.
104+
*/
105+
define('TEST_DEFINE_CONSTANT', false);
106+
107+
print TEST_DEFINE_CONSTANT ? 'true' : 'false';

src/DefinitionResolver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,11 @@ public static function getDefinedFqn(Node $node)
882882
}
883883
return (string)$class->namespacedName . '::' . $node->name;
884884
}
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+
}
889+
return (string)$node->args[0]->value->value;
885890
}
886891
}
887892
}

src/Index/Index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function getDefinition(string $fqn, bool $globalFallback = false)
117117
* Registers a definition
118118
*
119119
* @param string $fqn The fully qualified name of the symbol
120-
* @param string $definition The Definition object
120+
* @param Definition $definition The Definition object
121121
* @return void
122122
*/
123123
public function setDefinition(string $fqn, Definition $definition)

src/Protocol/SymbolInformation.php

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,19 @@ public static function fromNode(Node $node, string $fqn = null)
5050
{
5151
$parent = $node->getAttribute('parentNode');
5252
$symbol = new self;
53-
if ($node instanceof Node\Stmt\Class_) {
54-
$symbol->kind = SymbolKind::CLASS_;
55-
} else if ($node instanceof Node\Stmt\Trait_) {
53+
54+
if (
55+
$node instanceof Node\Expr\FuncCall
56+
&& $node->name instanceof Node\Name
57+
&& strtolower((string)$node->name) === 'define'
58+
&& isset($node->args[0])
59+
&& $node->args[0]->value instanceof Node\Scalar\String_
60+
) {
61+
// constants with define() like
62+
// define('TEST_DEFINE_CONSTANT', false);
63+
$symbol->kind = SymbolKind::CONSTANT;
64+
$symbol->name = (string)$node->args[0]->value->value;
65+
} else if ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_) {
5666
$symbol->kind = SymbolKind::CLASS_;
5767
} else if ($node instanceof Node\Stmt\Interface_) {
5868
$symbol->kind = SymbolKind::INTERFACE;
@@ -80,17 +90,21 @@ public static function fromNode(Node $node, string $fqn = null)
8090
} else {
8191
return null;
8292
}
83-
if ($node instanceof Node\Name) {
84-
$symbol->name = (string)$node;
85-
} else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) {
86-
$symbol->name = $node->var->name;
87-
} else if ($node instanceof Node\Expr\ClosureUse) {
88-
$symbol->name = $node->var;
89-
} else if (isset($node->name)) {
90-
$symbol->name = (string)$node->name;
91-
} else {
92-
return null;
93+
94+
if (!isset($symbol->name)) {
95+
if ($node instanceof Node\Name) {
96+
$symbol->name = (string)$node;
97+
} else if ($node instanceof Node\Expr\Assign || $node instanceof Node\Expr\AssignOp) {
98+
$symbol->name = $node->var->name;
99+
} else if ($node instanceof Node\Expr\ClosureUse) {
100+
$symbol->name = $node->var;
101+
} else if (isset($node->name)) {
102+
$symbol->name = (string)$node->name;
103+
} else {
104+
return null;
105+
}
93106
}
107+
94108
$symbol->location = Location::fromNode($node);
95109
if ($fqn !== null) {
96110
$parts = preg_split('/(::|->|\\\\)/', $fqn);

tests/LanguageServerTest.php

Lines changed: 2 additions & 2 deletions
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 26 PHP files parsed') !== false) {
60+
} else if (strpos($msg->body->params->message, 'All 27 PHP files parsed') !== false) {
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 26 PHP files parsed') !== false) {
106+
} else if (strpos($msg->body->params->message, 'All 27 PHP files parsed') !== false) {
107107
$promise->fulfill();
108108
}
109109
}

tests/Server/ServerTestCase.php

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,19 @@ public function setUp()
7272
$this->definitionLocations = [
7373

7474
// Global
75-
'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
76-
'TestClass' => new Location($globalSymbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
77-
'ChildClass' => new Location($globalSymbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
78-
'TestTrait' => new Location($globalSymbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
79-
'TestInterface' => new Location($globalSymbolsUri, new Range(new Position(68, 0), new Position(71, 1))),
80-
'TestClass::TEST_CLASS_CONST' => new Location($globalSymbolsUri, new Range(new Position(27, 10), new Position(27, 32))),
81-
'TestClass::testProperty' => new Location($globalSymbolsUri, new Range(new Position(41, 11), new Position(41, 24))),
82-
'TestClass::staticTestProperty' => new Location($globalSymbolsUri, new Range(new Position(34, 18), new Position(34, 37))),
83-
'TestClass::staticTestMethod()' => new Location($globalSymbolsUri, new Range(new Position(46, 4), new Position(49, 5))),
84-
'TestClass::testMethod()' => new Location($globalSymbolsUri, new Range(new Position(57, 4), new Position(60, 5))),
85-
'test_function()' => new Location($globalSymbolsUri, new Range(new Position(78, 0), new Position(81, 1))),
86-
'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))),
75+
'TEST_DEFINE_CONSTANT' => new Location($globalSymbolsUri, new Range(new Position(104, 0), new Position(104, 37))),
76+
'TEST_CONST' => new Location($globalSymbolsUri, new Range(new Position( 9, 6), new Position( 9, 22))),
77+
'TestClass' => new Location($globalSymbolsUri, new Range(new Position(20, 0), new Position(61, 1))),
78+
'ChildClass' => new Location($globalSymbolsUri, new Range(new Position(99, 0), new Position(99, 37))),
79+
'TestTrait' => new Location($globalSymbolsUri, new Range(new Position(63, 0), new Position(66, 1))),
80+
'TestInterface' => new Location($globalSymbolsUri, new Range(new Position(68, 0), new Position(71, 1))),
81+
'TestClass::TEST_CLASS_CONST' => new Location($globalSymbolsUri, new Range(new Position(27, 10), new Position(27, 32))),
82+
'TestClass::testProperty' => new Location($globalSymbolsUri, new Range(new Position(41, 11), new Position(41, 24))),
83+
'TestClass::staticTestProperty' => new Location($globalSymbolsUri, new Range(new Position(34, 18), new Position(34, 37))),
84+
'TestClass::staticTestMethod()' => new Location($globalSymbolsUri, new Range(new Position(46, 4), new Position(49, 5))),
85+
'TestClass::testMethod()' => new Location($globalSymbolsUri, new Range(new Position(57, 4), new Position(60, 5))),
86+
'test_function()' => new Location($globalSymbolsUri, new Range(new Position(78, 0), new Position(81, 1))),
87+
'whatever()' => new Location($globalReferencesUri, new Range(new Position(21, 0), new Position(23, 1))),
8788

8889
// Namespaced
8990
'TestNamespace' => new Location($symbolsUri, new Range(new Position( 2, 10), new Position( 2, 23))),
@@ -163,6 +164,9 @@ public function setUp()
163164
],
164165

165166
// Global
167+
'TEST_DEFINE_CONSTANT' => [
168+
0 => new Location($globalSymbolsUri, new Range(new Position(106, 6), new Position(106, 26)))
169+
],
166170
'TEST_CONST' => [
167171
0 => new Location($referencesUri, new Range(new Position(29, 5), new Position(29, 15))),
168172
1 => new Location($globalReferencesUri, new Range(new Position(29, 5), new Position(29, 15)))

tests/Server/TextDocument/HoverTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ public function testHoverForConstant()
156156
], $reference->range), $result);
157157
}
158158

159+
public function testHoverForGlobalConstant()
160+
{
161+
// print TEST_DEFINE_CONSTANT ? 'true' : 'false';
162+
// Get hover for TEST_DEFINE_CONSTANT
163+
$reference = $this->getReferenceLocations('TEST_DEFINE_CONSTANT')[0];
164+
$result = $this->textDocument->hover(
165+
new TextDocumentIdentifier($reference->uri),
166+
$reference->range->end
167+
)->wait();
168+
$this->assertEquals(new Hover([
169+
new MarkedString('php', "<?php\n\\define('TEST_DEFINE_CONSTANT', \\false);"),
170+
'Lorem ipsum dolor sit amet, consectetur.'
171+
], $reference->range), $result);
172+
}
173+
159174
public function testHoverForVariable()
160175
{
161176
// echo $var;

0 commit comments

Comments
 (0)