Permalink
Browse files

[fixes #19875155] Implement static closures

  • Loading branch information...
1 parent e4e5d5e commit 1e24a34f6293b175736bf8420fa88b01acd98c81 @manuelpichler manuelpichler committed Oct 19, 2011
@@ -91,6 +91,47 @@ public function setReturnsByReference($returnsReference)
}
/**
+ * Returns whether this closure was defined as static or not.
+ *
+ * This method will return <b>TRUE</b> when the closure was declared as
+ * followed:
+ *
+ * <code>
+ * $closure = static function( $e ) {
+ * return pow( $e, 2 );
+ * }
+ * </code>
+ *
+ * And it will return <b>FALSE</b> when we declare the closure as usual:
+ *
+ * <code>
+ * $closure = function( $e ) {
+ * return pow( $e, 2 );
+ * }
+ * </code>
+ *
+ * @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;
}
-}
+}
@@ -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:
* <code>
* function foo() {
* // ------------------------------
* static $foo, $bar, $baz = null;
* // ------------------------------
* }
+ * </code>
*
- *
+ * Static method invocation:
+ * <code>
* class Foo {
* public function baz() {
* // ----------------
@@ -5379,6 +5383,13 @@ private function _parseConstantDeclarator()
* }
* </code>
*
+ * Static closure declaration:
+ * <code>
+ * $closure = static function($x, $y) {
+ * return ($x * $y);
+ * };
+ * </code>
+ *
* @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);
@@ -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:
+ * <code>
+ * return function($x, $y) {
+ * return pow($x, $y);
+ * }
+ * </code>
+ *
+ * @return void
+ */
+ public function testIsStaticReturnsFalseForNonStaticClosure()
+ {
+ $closure = $this->_getFirstClosureInFunction();
+ $this->assertFalse($closure->isStatic());
+ }
+
+ /**
+ * testIsStaticReturnsTrueForStaticClosure
+ *
+ * Source:
+ * <code>
+ * return static function($x, $y) {
+ * return pow($x, $y);
+ * }
+ * </code>
+ *
+ * @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
);
}
-}
+}
@@ -0,0 +1,7 @@
+<?php
+function testIsStaticReturnsFalseForNonStaticClosure()
+{
+ return function($x, $y) {
+ return pow($x, $y);
+ };
+}
@@ -0,0 +1,9 @@
+<?php
+function testIsStaticReturnsTrueForStaticClosure()
+{
+ $closure = static function($x, $y) {
+ return pow($x, $y);
+ };
+ var_dump($closure(2, 2));
+}
+testIsStaticReturnsTrueForStaticClosure();
@@ -0,0 +1,7 @@
+<?php
+function testReturnsByReferenceReturnsFalseByDefaultForStaticClosure()
+{
+ return static function ($x, $y) {
+ return pow($x, $y);
+ };
+}
@@ -0,0 +1,7 @@
+<?php
+function testReturnsByReferenceReturnsTrueForStaticClosure()
+{
+ return static function &($x, $y) {
+ return pow($x, $y);
+ };
+}
@@ -0,0 +1,8 @@
+<?php
+function testStaticClosureHasExpectedEndColumn()
+{
+ return static
+ function($x, $y) {
+ return ($x * $y);
+ };
+}
@@ -0,0 +1,8 @@
+<?php
+function testStaticClosureHasExpectedEndLine()
+{
+ return static
+ function($x, $y) {
+ return ($x * $y);
+ };
+}
@@ -0,0 +1,8 @@
+<?php
+function testStaticClosureHasExpectedStartColumn()
+{
+ return static
+ function($x, $y) {
+ return ($x * $y);
+ };
+}
@@ -0,0 +1,8 @@
+<?php
+function testStaticClosureHasExpectedStartLine()
+{
+ return static
+ function($x, $y) {
+ return ($x * $y);
+ };
+}

0 comments on commit 1e24a34

Please sign in to comment.