Skip to content

Allow getting type from define() node #363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions src/DefinitionResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,19 @@ private static function resolveClassNameToType(Node $class): Type
*/
public function getTypeFromNode(Node $node)
{
if (
$node instanceof Node\Expr\FuncCall
&& $node->name instanceof Node\Name
&& strtolower((string)$node->name) === 'define'
&& isset($node->args[0])
&& $node->args[0]->value instanceof Node\Scalar\String_
&& isset($node->args[1])
) {
// constants with define() like
// define('TEST_DEFINE_CONSTANT', false);
return $this->resolveExpressionNodeToType($node->args[1]->value);
}

if ($node instanceof Node\Param) {
// Parameters
$docBlock = $node->getAttribute('parentNode')->getAttribute('docBlock');
Expand Down Expand Up @@ -882,11 +895,16 @@ public static function getDefinedFqn(Node $node)
}
return (string)$class->namespacedName . '::' . $node->name;
}
} else if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name && strtolower((string)$node->name) === 'define') {
if (!isset($node->args[0]) || !($node->args[0]->value instanceof Node\Scalar\String_)) {
return null;
}
} else if (
$node instanceof Node\Expr\FuncCall
&& $node->name instanceof Node\Name
&& strtolower((string)$node->name) === 'define'
&& isset($node->args[0])
&& $node->args[0]->value instanceof Node\Scalar\String_
&& isset($node->args[1])
) {
return (string)$node->args[0]->value->value;
}
return null;
}
}
3 changes: 2 additions & 1 deletion src/Protocol/SymbolInformation.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public static function fromNode(Node $node, string $fqn = null)
&& strtolower((string)$node->name) === 'define'
&& isset($node->args[0])
&& $node->args[0]->value instanceof Node\Scalar\String_
&& isset($node->args[1])
) {
// constants with define() like
// define('TEST_DEFINE_CONSTANT', false);
Expand Down Expand Up @@ -90,7 +91,7 @@ public static function fromNode(Node $node, string $fqn = null)
} else {
return null;
}

if (!isset($symbol->name)) {
if ($node instanceof Node\Name) {
$symbol->name = (string)$node;
Expand Down
64 changes: 64 additions & 0 deletions tests/DefinitionResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\Tests;

use PHPUnit\Framework\TestCase;
use LanguageServer\Index\Index;
use LanguageServer\{DefinitionResolver, Parser};

class DefinitionResolverTest extends TestCase
{
public function testCreateDefinitionFromNode()
{
$parser = new Parser;
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);

$index = new Index;
$definitionResolver = new DefinitionResolver($index);
$def = $definitionResolver->createDefinitionFromNode($stmts[0], '\TEST_DEFINE');

$this->assertInstanceOf(\phpDocumentor\Reflection\Types\Boolean::class, $def->type);
}

public function testGetTypeFromNode()
{
$parser = new Parser;
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);

$index = new Index;
$definitionResolver = new DefinitionResolver($index);
$type = $definitionResolver->getTypeFromNode($stmts[0]);

$this->assertInstanceOf(\phpDocumentor\Reflection\Types\Boolean::class, $type);
}

public function testGetDefinedFqnForIncompleteDefine()
{
// define('XXX') (only one argument) must not introduce a new symbol
$parser = new Parser;
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE');");
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);

$index = new Index;
$definitionResolver = new DefinitionResolver($index);
$fqn = $definitionResolver->getDefinedFqn($stmts[0]);

$this->assertNull($fqn);
}

public function testGetDefinedFqnForDefine()
{
$parser = new Parser;
$stmts = $parser->parse("<?php\ndefine('TEST_DEFINE', true);");
$stmts[0]->setAttribute('ownerDocument', new MockPhpDocument);

$index = new Index;
$definitionResolver = new DefinitionResolver($index);
$fqn = $definitionResolver->getDefinedFqn($stmts[0]);

$this->assertEquals('TEST_DEFINE', $fqn);
}
}
20 changes: 20 additions & 0 deletions tests/MockPhpDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\Tests;

/**
* A fake document for tests
*/
class MockPhpDocument
{
/**
* Returns fake uri
*
* @return string
*/
public function getUri()
{
return 'file:///whatever';
}
}