Arbit - project tracking

PHP Depend

History

Diff

961 962 /tests/PHP/Depend/Bugs/AllTests.php
68 68 require_once dirname(__FILE__) . '/WrongCouplingAnalyzerForCommentsBug089Test.php';
69 69 require_once dirname(__FILE__) . '/NamespaceChainsNotHandledCorrectByCouplingAnalyzerBug090Test.php';
70 70 require_once dirname(__FILE__) . '/ClassConstantAsArrayDefaultValueResultsInExceptionBug091Test.php';
71 +require_once dirname(__FILE__) . '/ClosureReturnsByReferenceBug094Test.php';
71 72 require_once dirname(__FILE__) . '/NPathComplexityIsBrokenInVersion096Bug095Test.php';
72 73
73 74 /**
117 118 $suite->addTestSuite('PHP_Depend_Bugs_WrongCouplingAnalyzerForCommentsBug089Test');
118 119 $suite->addTestSuite('PHP_Depend_Bugs_NamespaceChainsNotHandledCorrectByCouplingAnalyzerBug090Test');
119 120 $suite->addTestSuite('PHP_Depend_Bugs_ClassConstantAsArrayDefaultValueResultsInExceptionBug091Test');
121 + $suite->addTestSuite('PHP_Depend_Bugs_ClosureReturnsByReferenceBug094Test');
120 122 $suite->addTestSuite('PHP_Depend_Bugs_NPathComplexityIsBrokenInVersion096Bug095Test');
121 123
122 124 return $suite;
961 962 /tests/PHP/Depend/Bugs/ClosureReturnsByReferenceBug094Test.php
2 +<?php
3 +/**
4 + * This file is part of PHP_Depend.
5 + *
6 + * PHP Version 5
7 + *
8 + * Copyright (c) 2008-2009, Manuel Pichler <mapi@pdepend.org>.
9 + * All rights reserved.
10 + *
11 + * Redistribution and use in source and binary forms, with or without
12 + * modification, are permitted provided that the following conditions
13 + * are met:
14 + *
15 + * * Redistributions of source code must retain the above copyright
16 + * notice, this list of conditions and the following disclaimer.
17 + *
18 + * * Redistributions in binary form must reproduce the above copyright
19 + * notice, this list of conditions and the following disclaimer in
20 + * the documentation and/or other materials provided with the
21 + * distribution.
22 + *
23 + * * Neither the name of Manuel Pichler nor the names of his
24 + * contributors may be used to endorse or promote products derived
25 + * from this software without specific prior written permission.
26 + *
27 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 + * POSSIBILITY OF SUCH DAMAGE.
39 + *
40 + * @category PHP
41 + * @package PHP_Depend
42 + * @subpackage Bugs
43 + * @author Manuel Pichler <mapi@pdepend.org>
44 + * @copyright 2008-2009 Manuel Pichler. All rights reserved.
45 + * @license http://www.opensource.org/licenses/bsd-license.php BSD License
46 + * @version SVN: $Id$
47 + * @link http://www.pdepend.org/
48 + */
49 +
50 +require_once dirname(__FILE__) . '/AbstractTest.php';
51 +
52 +/**
53 + * Tests that the parser handles a closure that returns a reference correct.
54 + * This test is related to bug #94.
55 + *
56 + * @category PHP
57 + * @package PHP_Depend
58 + * @subpackage Bugs
59 + * @author Manuel Pichler <mapi@pdepend.org>
60 + * @copyright 2008-2009 Manuel Pichler. All rights reserved.
61 + * @license http://www.opensource.org/licenses/bsd-license.php BSD License
62 + * @version Release: @package_version@
63 + * @link http://www.pdepend.org/
64 + */
65 +class PHP_Depend_Bugs_ClosureReturnsByReferenceBug094Test
66 + extends PHP_Depend_Bugs_AbstractTest
67 +{
68 + /**
69 + * @return void
70 + * @group bugs
71 + */
72 + public function testParserHandlesClosureThatReturnsReference()
73 + {
74 + $packages = self::parseTestCaseSource(__METHOD__);
75 + $function = $packages->current()
76 + ->getFunctions()
77 + ->current();
78 + }
79 +}
961 962 /tests/PHP/Depend/_code/bugs/094/testParserHandlesClosureThatReturnsReference.php
2 +<?php
3 +function foo()
4 +{
5 + $x = function&($y) {
6 + return $y;
7 + };
8 + var_dump($x(42));
9 +}
10 +foo();
961 962 /PHP/Depend/Parser.php
753 753 {
754 754 $this->_tokenStack->push();
755 755
756 - // Read function keyword
757 756 $this->_consumeToken(self::T_FUNCTION);
758 -
759 - // Remove leading comments
760 757 $this->_consumeComments();
758 +
759 + $returnReference = $this->_parseOptionalReturnbyReference();
761 760
762 - // Check for closure or function
763 - if ($this->_tokenizer->peek() === self::T_PARENTHESIS_OPEN) {
761 + if ($this->_isNextTokenFunctionOrMethodIdentifier()) {
762 + $callable = $this->_parseFunctionDeclaration();
763 + } else {
764 764 $callable = $this->_parseClosureDeclaration();
765 - } else {
766 - $callable = $this->_parseFunctionDeclaration();
767 765 }
768 766
769 767 $callable->setSourceFile($this->_sourceFile);
771 769 $callable->setTokens($this->_tokenStack->pop());
772 770 $this->_prepareCallable($callable);
773 771
772 + if ($returnReference) {
773 + $callable->setReturnsReference();
774 + }
775 +
774 776 $this->reset();
775 777
776 778 return $callable;
777 779 }
778 780
779 781 /**
782 + * Parses an optional returns by reference token. The return value will be
783 + * <b>true</b> when a reference token was found, otherwise this method will
784 + * return <b>false</b>.
785 + *
786 + * @return boolean
787 + * @since 0.9.7
788 + */
789 + private function _parseOptionalReturnbyReference()
790 + {
791 + if ($this->_isNextTokenReturnByReference()) {
792 + return $this->_parseReturnByReference();
793 + }
794 + return false;
795 + }
796 +
797 + /**
798 + * Tests that the next available token is the returns by reference token.
799 + *
800 + * @return boolean
801 + * @since 0.9.7
802 + */
803 + private function _isNextTokenReturnByReference()
804 + {
805 + return ($this->_tokenizer->peek() === self::T_BITWISE_AND);
806 + }
807 +
808 +
809 + /**
810 + * This method parses a returns by reference token and returns <b>true</b>.
811 + *
812 + * @return boolean
813 + */
814 + private function _parseReturnByReference()
815 + {
816 + $this->_consumeToken(self::T_BITWISE_AND);
817 + $this->_consumeComments();
818 +
819 + return true;
820 + }
821 +
822 + /**
823 + * Tests that the next available token is a function or method identifier.
824 + *
825 + * @return boolean
826 + * @since 0.9.7
827 + */
828 + private function _isNextTokenFunctionOrMethodIdentifier()
829 + {
830 + return ($this->_tokenizer->peek() === self::T_STRING);
831 + }
832 +
833 + /**
780 834 * This method parses a function declaration.
781 835 *
782 836 * @return PHP_Depend_Code_Function
784 838 */
785 839 private function _parseFunctionDeclaration()
786 840 {
787 - // Remove leading comments
788 841 $this->_consumeComments();
789 842
790 - $returnsReference = false;
791 -
792 - // Check for returns reference token
793 - if ($this->_tokenizer->peek() === self::T_BITWISE_AND) {
794 - $this->_consumeToken(self::T_BITWISE_AND);
795 - $this->_consumeComments();
796 -
797 - $returnsReference = true;
798 - }
799 -
800 843 // Next token must be the function identifier
801 844 $functionName = $this->_consumeToken(self::T_STRING)->image;
802 845
803 846 $function = $this->_builder->buildFunction($functionName);
804 847 $this->_parseCallableDeclaration($function);
805 848
806 - if ($returnsReference === true) {
807 - $function->setReturnsReference();
808 - }
809 -
810 849 // First check for an existing namespace
811 850 if ($this->_namespaceName !== null) {
812 851 $packageName = $this->_namespaceName;
961 962 /PHP/Depend/Code/Closure.php
64 64 class PHP_Depend_Code_Closure extends PHP_Depend_Code_AbstractCallable
65 65 {
66 66 /**
67 - * COnstructs a new closure instance.
67 + * Constructs a new closure instance.
68 68 */
69 69 public function __construct()
70 70 {
83 83 $visitor->visitClosure($this);
84 84 }
85 85 }
86 -?>