Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refs #202: Support for variable arg list implemented
Still missing support for epsillon token as part of the callee arguments.
  • Loading branch information
Manuel Pichler committed May 20, 2015
1 parent 41d75da commit dff2547
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 114 deletions.
239 changes: 129 additions & 110 deletions composer.lock

Large diffs are not rendered by default.

25 changes: 24 additions & 1 deletion src/main/php/PDepend/Source/AST/ASTFormalParameter.php
Expand Up @@ -58,6 +58,29 @@
*/
class ASTFormalParameter extends ASTNode
{
/**
* This method will return <b>true</b> when the parameter is declared as a
* variable argument list <b>...</b>.
*
* @return boolean
* @since 2.0.7
*/
public function isVariableArgList()
{
return $this->getMetadataBoolean(6);
}

/**
* This method can be used to mark this parameter as passed by reference.
*
* @return void
@since 2.0.7
*/
public function setVariableArgList()
{
return $this->setMetadataBoolean(6, true);
}

/**
* This method will return <b>true</b> when the parameter is passed by
* reference.
Expand Down Expand Up @@ -102,6 +125,6 @@ public function accept(ASTVisitor $visitor, $data = null)
*/
protected function getMetadataSize()
{
return 6;
return 7;
}
}
Expand Up @@ -5418,7 +5418,7 @@ private function parseFormalParameterAndByReference()
* @return \PDepend\Source\AST\ASTFormalParameter
* @since 0.9.6
*/
private function parseFormalParameter()
protected function parseFormalParameter()
{
$parameter = $this->builder->buildAstFormalParameter();
$parameter->addChild($this->parseVariableDeclarator());
Expand Down Expand Up @@ -6204,7 +6204,7 @@ private function parseStaticVariableDeclaration(Token $token)
* @return \PDepend\Source\AST\ASTVariableDeclarator
* @since 0.9.6
*/
private function parseVariableDeclarator()
protected function parseVariableDeclarator()
{
$this->tokenStack->push();

Expand Down
29 changes: 29 additions & 0 deletions src/main/php/PDepend/Source/Language/PHP/PHPParserGeneric.php
Expand Up @@ -376,4 +376,33 @@ protected function parseStaticValueVersionSpecific(ASTValue $value)

return $value;
}

/**
* This method will parse a formal parameter. A formal parameter is at least
* a variable name, but can also contain a default parameter value.
*
* <code>
* // -- -------
* function foo(Bar $x, $y = 42) {}
* // -- -------
* </code>
*
* @return \PDepend\Source\AST\ASTFormalParameter
* @since 2.0.7
*/
protected function parseFormalParameter()
{
$parameter = $this->builder->buildAstFormalParameter();

if (Tokens::T_ELLIPSIS === $this->tokenizer->peek()) {
$this->consumeToken(Tokens::T_ELLIPSIS);
$this->consumeComments();

$parameter->setVariableArgList();
}

$parameter->addChild($this->parseVariableDeclarator());

return $parameter;
}
}
Expand Up @@ -56,6 +56,11 @@
*/
class PHPTokenizerInternal implements Tokenizer
{
/**
* Internally used transition token.
*/
const T_ELLIPSIS = 23006;

/**
* Mapping between php internal tokens and php depend tokens.
*
Expand Down Expand Up @@ -129,6 +134,7 @@ class PHPTokenizerInternal implements Tokenizer
T_OR_EQUAL => Tokens::T_OR_EQUAL,
T_CONTINUE => Tokens::T_CONTINUE,
T_METHOD_C => Tokens::T_METHOD_C,
T_ELLIPSIS => Tokens::T_ELLIPSIS,
T_OPEN_TAG => Tokens::T_OPEN_TAG,
T_SL_EQUAL => Tokens::T_SL_EQUAL,
T_SR_EQUAL => Tokens::T_SR_EQUAL,
Expand Down Expand Up @@ -358,6 +364,19 @@ class PHPTokenizerInternal implements Tokenizer
),
);

protected static $reductionMap = array(
Tokens::T_CONCAT => array(
Tokens::T_CONCAT => array(
'type' => self::T_ELLIPSIS,
'image' => '..'
),
self::T_ELLIPSIS => array(
'type' => Tokens::T_ELLIPSIS,
'image' => '...'
)
),
);

/**
* The source file instance.
*
Expand Down Expand Up @@ -592,12 +611,20 @@ private function tokenize()
if (isset($literalMap[$value])) {
// Fetch literal type
$type = $literalMap[$value];
$image = $token[1];

// Check for a context sensitive alternative
if (isset(self::$alternativeMap[$type][$previousType])) {
$type = self::$alternativeMap[$type][$previousType];
}
$image = $token[1];

if (isset(self::$reductionMap[$type][$previousType])) {
$image = self::$reductionMap[$type][$previousType]['image'];
$type = self::$reductionMap[$type][$previousType]['type'];

array_pop($this->tokens);
}

} elseif (isset($tokenMap[$token[0]])) {
$type = $tokenMap[$token[0]];
// Check for a context sensitive alternative
Expand Down
7 changes: 7 additions & 0 deletions src/main/php/PDepend/Source/Tokenizer/Tokenizer.php
Expand Up @@ -84,6 +84,13 @@
define('T_NAMESPACE', 42005);
}

/**
* Define PHP 5.6 '...' token constant
*/
if (!defined('T_ELLIPSIS')) {
define('T_ELLIPSIS', 42006);
}

/**
* Define PHP 5.3's '__DIR__' token constant.
*/
Expand Down
7 changes: 7 additions & 0 deletions src/main/php/PDepend/Source/Tokenizer/Tokens.php
Expand Up @@ -850,6 +850,13 @@ interface Tokens
*/
const T_FINALLY = 160;

/**
* TOken that represents the '...' token
*
* @since 2.0.7
*/
const T_ELLIPSIS = 161;

/**
* Marks any content not between php tags.
*/
Expand Down
55 changes: 55 additions & 0 deletions src/test/php/PDepend/Source/AST/ASTFormalParameterTest.php
Expand Up @@ -55,6 +55,61 @@
*/
class ASTFormalParameterTest extends \PDepend\Source\AST\ASTNodeTest
{
/**
* testIsVariableArgListReturnsFalseByDefault
*
* @return void
*/
public function testIsVariableArgListReturnsFalseByDefault()
{
$parameter = $this->_getFirstFormalParameterInFunction();
$this->assertFalse($parameter->isVariableArgList());
}

/**
* testIsVariableArgListReturnsTrue
*
* @return void
*/
public function testIsVariableArgListReturnsTrue()
{
$parameter = $this->_getFirstFormalParameterInFunction();
$this->assertTrue($parameter->isVariableArgList());
}

/**
* testIsVariableArgListWithArrayTypeHint
*
* @return void
*/
public function testIsVariableArgListWithArrayTypeHint()
{
$parameter = $this->_getFirstFormalParameterInFunction();
$this->assertTrue($parameter->isVariableArgList());
}

/**
* testIsVariableArgListWithClassTypeHint
*
* @return void
*/
public function testIsVariableArgListWithClassTypeHint()
{
$parameter = $this->_getFirstFormalParameterInFunction();
$this->assertTrue($parameter->isVariableArgList());
}

/**
* testIsVariableArgListPassedByReference
*
* @return void
*/
public function testIsVariableArgListPassedByReference()
{
$parameter = $this->_getFirstFormalParameterInFunction();
$this->assertTrue($parameter->isVariableArgList());
}

/**
* testIsPassedByReferenceReturnsFalseByDefault
*
Expand Down
@@ -0,0 +1,5 @@
<?php
function testIsVariableArgListPassedByReference(&...$argList)
{

}
@@ -0,0 +1,5 @@
<?php
function testIsVariableArgListReturnsFalseByDefault($pdepend)
{

}
@@ -0,0 +1,5 @@
<?php
function testIsVariableArgListReturnsTrue(...$argList)
{

}
@@ -0,0 +1,5 @@
<?php
function testIsVariableArgListWithArrayTypeHint(array ...$argList)
{

}
@@ -0,0 +1,5 @@
<?php
function testIsVariableArgListWithClassTypeHint(Iterator ...$iterator)
{

}

0 comments on commit dff2547

Please sign in to comment.