diff --git a/src/main/php/PHP/Depend/Code/ASTClosure.php b/src/main/php/PHP/Depend/Code/ASTClosure.php
index f5f09298a..46bad2415 100644
--- a/src/main/php/PHP/Depend/Code/ASTClosure.php
+++ b/src/main/php/PHP/Depend/Code/ASTClosure.php
@@ -90,6 +90,47 @@ public function setReturnsByReference($returnsReference)
$this->setMetadataBoolean(5, (boolean) $returnsReference);
}
+ /**
+ * Returns whether this closure was defined as static or not.
+ *
+ * This method will return TRUE when the closure was declared as
+ * followed:
+ *
+ *
+ * $closure = static function( $e ) {
+ * return pow( $e, 2 );
+ * }
+ *
+ *
+ * And it will return FALSE when we declare the closure as usual:
+ *
+ *
+ * $closure = function( $e ) {
+ * return pow( $e, 2 );
+ * }
+ *
+ *
+ * @return boolean
+ * @since 0.11.0
+ */
+ public function isStatic()
+ {
+ return $this->getMetadataBoolean(6);
+ }
+
+ /**
+ * This method can be used to flag this closure instance as static.
+ *
+ * @param boolean $static Whether this closure is static or not.
+ *
+ * @return void
+ * @since 0.11.0
+ */
+ public function setStatic($static)
+ {
+ $this->setMetadataBoolean(6, (boolean) $static);
+ }
+
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
@@ -114,6 +155,6 @@ public function accept(PHP_Depend_Code_ASTVisitorI $visitor, $data = null)
*/
protected function getMetadataSize()
{
- return 6;
+ return 7;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/php/PHP/Depend/Parser.php b/src/main/php/PHP/Depend/Parser.php
index 5f300fef6..3fa761124 100644
--- a/src/main/php/PHP/Depend/Parser.php
+++ b/src/main/php/PHP/Depend/Parser.php
@@ -5354,17 +5354,21 @@ private function _parseConstantDeclarator()
}
/**
- * This method parses a static variable declaration list or a member primary
- * prefix invoked in the static context of a class.
+ * This method parses a static variable declaration list, a member primary
+ * prefix invoked in the static context of a class or it parses a static
+ * closure declaration.
*
+ * Static variable:
*
* function foo() {
* // ------------------------------
* static $foo, $bar, $baz = null;
* // ------------------------------
* }
+ *
*
- *
+ * Static method invocation:
+ *
* class Foo {
* public function baz() {
* // ----------------
@@ -5379,6 +5383,13 @@ private function _parseConstantDeclarator()
* }
*
*
+ * Static closure declaration:
+ *
+ * $closure = static function($x, $y) {
+ * return ($x * $y);
+ * };
+ *
+ *
* @return PHP_Depend_Code_ASTConstant
* @throws PHP_Depend_Parser_Exception When an error occured during the
* parsing process.
@@ -5404,6 +5415,11 @@ private function _parseStaticVariableDeclarationOrMemberPrimaryPrefix()
$prefix = $this->_parseStaticMemberPrimaryPrefix($static);
return $this->_setNodePositionsAndReturn($prefix);
+ } else if ($tokenType === self::T_FUNCTION) {
+ $closure = $this->_parseClosureDeclaration();
+ $closure->setStatic(true);
+
+ return $this->_setNodePositionsAndReturn($closure);
}
$declaration = $this->_parseStaticVariableDeclaration($token);
diff --git a/src/test/php/PHP/Depend/Code/ASTClosureTest.php b/src/test/php/PHP/Depend/Code/ASTClosureTest.php
index 7f3dac8eb..00b40f68b 100644
--- a/src/test/php/PHP/Depend/Code/ASTClosureTest.php
+++ b/src/test/php/PHP/Depend/Code/ASTClosureTest.php
@@ -77,7 +77,18 @@ class PHP_Depend_Code_ASTClosureTest extends PHP_Depend_Code_ASTNodeTest
public function testReturnsByReferenceReturnsFalseByDefault()
{
$closure = $this->_getFirstClosureInFunction();
- self::assertFalse($closure->returnsByReference());
+ $this->assertFalse($closure->returnsByReference());
+ }
+
+ /**
+ * testReturnsByReferenceReturnsFalseByDefaultForStaticClosure
+ *
+ * @return void
+ */
+ public function testReturnsByReferenceReturnsFalseByDefaultForStaticClosure()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertFalse($closure->returnsByReference());
}
/**
@@ -88,7 +99,18 @@ public function testReturnsByReferenceReturnsFalseByDefault()
public function testReturnsByReferenceReturnsTrueForClosure()
{
$closure = $this->_getFirstClosureInFunction();
- self::assertTrue($closure->returnsByReference());
+ $this->assertTrue($closure->returnsByReference());
+ }
+
+ /**
+ * testReturnsByReferenceReturnsTrueForStaticClosure
+ *
+ * @return void
+ */
+ public function testReturnsByReferenceReturnsTrueForStaticClosure()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertTrue($closure->returnsByReference());
}
/**
@@ -99,7 +121,91 @@ public function testReturnsByReferenceReturnsTrueForClosure()
public function testReturnsByReferenceReturnsTrueForAssignedClosure()
{
$closure = $this->_getFirstClosureInFunction();
- self::assertTrue($closure->returnsByReference());
+ $this->assertTrue($closure->returnsByReference());
+ }
+
+ /**
+ * testIsStaticReturnsFalseByDefault
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsFalseByDefault()
+ {
+ $closure = new PHP_Depend_Code_ASTClosure();
+ $this->assertFalse($closure->isStatic());
+ }
+
+ /**
+ * testIsStaticReturnsTrueWhenSetToTrue
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsTrueWhenSetToTrue()
+ {
+ $closure = new PHP_Depend_Code_ASTClosure();
+ $closure->setStatic(true);
+
+ $this->assertTrue($closure->isStatic());
+ }
+
+ /**
+ * testIsStaticReturnsFalseWhenSetToFalse
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsFalseWhenSetToFalse()
+ {
+ $closure = new PHP_Depend_Code_ASTClosure();
+ $closure->setStatic(false);
+
+ $this->assertFalse($closure->isStatic());
+ }
+
+ /**
+ * testIsStaticReturnsFalseForNonStaticClosure
+ *
+ * Source:
+ *
+ * return function($x, $y) {
+ * return pow($x, $y);
+ * }
+ *
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsFalseForNonStaticClosure()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertFalse($closure->isStatic());
+ }
+
+ /**
+ * testIsStaticReturnsTrueForStaticClosure
+ *
+ * Source:
+ *
+ * return static function($x, $y) {
+ * return pow($x, $y);
+ * }
+ *
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsTrueForStaticClosure()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertTrue($closure->isStatic());
+ }
+
+ /**
+ * testClosureContainsExpectedNumberChildNodes
+ *
+ * @return void
+ */
+ public function testClosureContainsExpectedNumberChildNodes()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertEquals(2, count($closure->getChildren()));
}
/**
@@ -132,7 +238,7 @@ public function testAcceptReturnsReturnValueOfVisitMethod()
->will($this->returnValue(42));
$node = new PHP_Depend_Code_ASTClosure();
- self::assertEquals(42, $node->accept($visitor));
+ $this->assertEquals(42, $node->accept($visitor));
}
/**
@@ -180,14 +286,47 @@ public function testClosureHasExpectedEndColumn()
}
/**
- * testClosureContainsExpectedNumberChildNodes
+ * testStaticClosureHasExpectedStartLine
*
* @return void
*/
- public function testClosureContainsExpectedNumberChildNodes()
+ public function testStaticClosureHasExpectedStartLine()
{
- $closure = $this->_getFirstClosureInFunction();
- $this->assertEquals(2, count($closure->getChildren()));
+ $label = $this->_getFirstClosureInFunction();
+ $this->assertEquals(4, $label->getStartLine());
+ }
+
+ /**
+ * testStaticClosureHasExpectedEndLine
+ *
+ * @return void
+ */
+ public function testStaticClosureHasExpectedEndLine()
+ {
+ $label = $this->_getFirstClosureInFunction();
+ $this->assertEquals(7, $label->getEndLine());
+ }
+
+ /**
+ * testStaticClosureHasExpectedStartColumn
+ *
+ * @return void
+ */
+ public function testStaticClosureHasExpectedStartColumn()
+ {
+ $label = $this->_getFirstClosureInFunction();
+ $this->assertEquals(12, $label->getStartColumn());
+ }
+
+ /**
+ * testStaticClosureHasExpectedEndColumn
+ *
+ * @return void
+ */
+ public function testStaticClosureHasExpectedEndColumn()
+ {
+ $label = $this->_getFirstClosureInFunction();
+ $this->assertEquals(9, $label->getEndColumn());
}
/**
@@ -202,4 +341,4 @@ private function _getFirstClosureInFunction()
PHP_Depend_Code_ASTClosure::CLAZZ
);
}
-}
\ No newline at end of file
+}
diff --git a/src/test/resources/files/Code/ASTClosure/testIsStaticReturnsFalseForNonStaticClosure.php b/src/test/resources/files/Code/ASTClosure/testIsStaticReturnsFalseForNonStaticClosure.php
new file mode 100644
index 000000000..d5a54ec6c
--- /dev/null
+++ b/src/test/resources/files/Code/ASTClosure/testIsStaticReturnsFalseForNonStaticClosure.php
@@ -0,0 +1,7 @@
+