Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Closes #269: Support static access to other expressions
  • Loading branch information
Manuel Pichler committed Jan 6, 2017
1 parent e28dc95 commit e611915
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 5 deletions.
18 changes: 14 additions & 4 deletions src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php
Expand Up @@ -52,6 +52,7 @@
use PDepend\Source\AST\ASTExpression;
use PDepend\Source\AST\ASTIndexExpression;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTNamespace;
use PDepend\Source\AST\ASTNode;
use PDepend\Source\AST\ASTStatement;
use PDepend\Source\AST\ASTSwitchStatement;
Expand Down Expand Up @@ -3708,8 +3709,17 @@ private function parseEchoStatement()
*/
protected function parseParenthesisExpressionOrPrimaryPrefix()
{
$expr = $this->parseParenthesisExpression();
return $this->parseParenthesisExpressionOrPrimaryPrefixForVersion(
$this->parseParenthesisExpression()
);
}

/**
* @param \PDepend\Source\AST\ASTExpression $expr
* @return \PDepend\Source\AST\ASTExpression
*/
protected function parseParenthesisExpressionOrPrimaryPrefixForVersion(ASTExpression $expr)
{
$this->consumeComments();
if (Tokens::T_OBJECT_OPERATOR === $this->tokenizer->peek()) {
return $this->parseMemberPrimaryPrefix($expr->getChild(0));
Expand Down Expand Up @@ -3894,7 +3904,7 @@ protected function parsePostfixIdentifier()
* @throws \PDepend\Source\Parser\ParserException
* @since 0.9.6
*/
private function parseOptionalMemberPrimaryPrefix(ASTNode $node)
protected function parseOptionalMemberPrimaryPrefix(ASTNode $node)
{
$this->consumeComments();

Expand Down Expand Up @@ -3924,7 +3934,7 @@ private function parseOptionalMemberPrimaryPrefix(ASTNode $node)
* @throws \PDepend\Source\Parser\ParserException
* @since 0.9.6
*/
private function parseMemberPrimaryPrefix(ASTNode $node)
protected function parseMemberPrimaryPrefix(ASTNode $node)
{
// Consume double colon and optional comments
$token = $this->consumeToken(Tokens::T_OBJECT_OPERATOR);
Expand Down Expand Up @@ -4022,7 +4032,7 @@ private function parseOptionalStaticMemberPrimaryPrefix(ASTNode $node)
* @throws \PDepend\Source\Parser\ParserException
* @since 0.9.6
*/
private function parseStaticMemberPrimaryPrefix(ASTNode $node)
protected function parseStaticMemberPrimaryPrefix(ASTNode $node)
{
$token = $this->consumeToken(Tokens::T_DOUBLE_COLON);

Expand Down
34 changes: 34 additions & 0 deletions src/main/php/PDepend/Source/Language/PHP/PHPParserVersion70.php
Expand Up @@ -44,6 +44,8 @@
namespace PDepend\Source\Language\PHP;

use PDepend\Source\AST\ASTAllocationExpression;
use PDepend\Source\AST\ASTExpression;
use PDepend\Source\AST\ASTNode;
use PDepend\Source\Tokenizer\Token;
use PDepend\Source\Tokenizer\Tokens;

Expand Down Expand Up @@ -267,6 +269,38 @@ protected function parseAnonymousClassDeclaration(ASTAllocationExpression $alloc
return null;
}

/**
* @param \PDepend\Source\AST\ASTNode $node
* @return \PDepend\Source\AST\ASTNode
*/
protected function parseOptionalMemberPrimaryPrefix(ASTNode $node)
{
$this->consumeComments();
if (Tokens::T_DOUBLE_COLON === $this->tokenizer->peek()) {
return $this->parseStaticMemberPrimaryPrefix($node);
}
if ($this->tokenizer->peek() === Tokens::T_OBJECT_OPERATOR) {
return $this->parseMemberPrimaryPrefix($node);
}
return $node;
}

/**
* @param \PDepend\Source\AST\ASTExpression $expr
* @return \PDepend\Source\AST\ASTExpression
*/
protected function parseParenthesisExpressionOrPrimaryPrefixForVersion(ASTExpression $expr)
{
$this->consumeComments();
if (Tokens::T_DOUBLE_COLON === $this->tokenizer->peek()) {
return $this->parseStaticMemberPrimaryPrefix($expr->getChild(0));
}
if ($this->tokenizer->peek() === Tokens::T_OBJECT_OPERATOR) {
return $this->parseMemberPrimaryPrefix($expr->getChild(0));
}
return $expr;
}

/**
* This method will be called when the base parser cannot handle an expression
* in the base version. In this method you can implement version specific
Expand Down
3 changes: 3 additions & 0 deletions src/site/docx/changes.xml
Expand Up @@ -18,6 +18,9 @@
<action date="fd4aaca" dev="manuelpichler" due-to="PierreLvx" type="fix" system="github" issue="282">
PHP 7 - Group use declarations
</action>
<action date="00a61c6" dev="manuelpichler" due-to="webmailcontatos" type="fix" system="github" issue="281">
Anonymous class - Internal parser state issue fixed.
</action>
</release>
<release version="2.3.2"
date="2016/11/23"
Expand Down
Expand Up @@ -470,4 +470,12 @@ public function testGroupUseStatementAliasResolution(ASTNamespace $namespace)
$class->getParentClass()->getNamespacedName()
);
}

/**
* @return void
*/
public function testUniformVariableSyntax()
{
$this->assertNotNull($this->parseCodeResourceForTest());
}
}
Expand Up @@ -156,13 +156,23 @@ public function testUseStatement()
/**
* @return void
* @expectedException \PDepend\Source\Parser\UnexpectedTokenException
* @expectedExceptionMessageRegExp (^Unexpected token: \{, line: 2, col: 24, file:)
* @expectedExceptionMessageRegExp (^Unexpected token: \{, line: 2, col: 24, file: )
*/
public function testGroupUseStatementThrowsException()
{
$this->parseCodeResourceForTest();
}

/**
* @return void
* @expectedException \PDepend\Source\Parser\UnexpectedTokenException
* @expectedExceptionMessageRegExp (^Unexpected token: ::, line: 8, col: 24, file: )
*/
public function testUniformVariableSyntaxThrowsException()
{
$this->assertNotNull($this->parseCodeResourceForTest());
}

/**
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @param \PDepend\Source\Builder\Builder $builder
Expand Down
Expand Up @@ -475,6 +475,14 @@ public function testGroupUseStatementAliasResolution(ASTNamespace $namespace)
);
}

/**
* @return void
*/
public function testUniformVariableSyntax()
{
$this->assertNotNull($this->parseCodeResourceForTest());
}

/**
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @param \PDepend\Source\Builder\Builder $builder
Expand Down
@@ -0,0 +1,74 @@
<?php
class UniformVariableSyntax
{
static $bar, $baz;

public function foo($foo, $bar, $baz)
{
echo $foo::$bar::$baz, PHP_EOL;
}
}

$foo = new UniformVariableSyntax();
$foo::$bar = $foo;
$foo::$baz = 'foo::bar::baz';
$foo->foo($foo, 'bar', 'baz');

class UniformVariableSyntaxStatic
{
public $bar;

public function __construct() {
$this->bar = new X();
$this->bar::$array = [1, 2];
}

public function validVariableName() {
if ($this->bar::$array[1]) {
var_dump($this->bar::$array);
}
}
}

class X {
public static $array;
}

$o = new UniformVariableSyntaxStatic();
$o->validVariableName();

class UniformVariableSyntaxCallReturn
{
public function create() {
return function () {
echo __METHOD__, PHP_EOL;
};
}
}

$o = new UniformVariableSyntaxCallReturn();
$o->create()();

class UniformVariableSyntaxOperatorOnExpression
{
public function call() {
(function () {
echo __METHOD__, PHP_EOL;
})();
}
}

$o = new UniformVariableSyntaxOperatorOnExpression();
$o->call();

class UniformVariableSyntaxOperatorOnExpression
{
public function call() {
($this)::go("Sindelfingen");
}

public static function go($query) {
echo $query, PHP_EOL;
}
}

@@ -0,0 +1,15 @@
<?php
class UniformVariableSyntax
{
static $bar, $baz;

public function foo($foo, $bar, $baz)
{
echo $foo::$bar::$baz, PHP_EOL;
}
}

$foo = new UniformVariableSyntax();
$foo::$bar = $foo;
$foo::$baz = 'foo::bar::baz';
$foo->foo($foo, 'bar', 'baz');
@@ -0,0 +1,74 @@
<?php
class UniformVariableSyntax
{
static $bar, $baz;

public function foo($foo, $bar, $baz)
{
echo $foo::$bar::$baz, PHP_EOL;
}
}

$foo = new UniformVariableSyntax();
$foo::$bar = $foo;
$foo::$baz = 'foo::bar::baz';
$foo->foo($foo, 'bar', 'baz');

class UniformVariableSyntaxStatic
{
public $bar;

public function __construct() {
$this->bar = new X();
$this->bar::$array = [1, 2];
}

public function validVariableName() {
if ($this->bar::$array[1]) {
var_dump($this->bar::$array);
}
}
}

class X {
public static $array;
}

$o = new UniformVariableSyntaxStatic();
$o->validVariableName();

class UniformVariableSyntaxCallReturn
{
public function create() {
return function () {
echo __METHOD__, PHP_EOL;
};
}
}

$o = new UniformVariableSyntaxCallReturn();
$o->create()();

class UniformVariableSyntaxOperatorOnExpression
{
public function call() {
(function () {
echo __METHOD__, PHP_EOL;
})();
}
}

$o = new UniformVariableSyntaxOperatorOnExpression();
$o->call();

class UniformVariableSyntaxOperatorOnExpression
{
public function call() {
($this)::go("Sindelfingen");
}

public static function go($query) {
echo $query, PHP_EOL;
}
}

0 comments on commit e611915

Please sign in to comment.