Completed
Push — feature/null-coalescing-assign... ( 42d45d...cc67f8 )
by Kyle
43:35 queued 28:18
created

testConstantArrayConcatenation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 34
rs 9.376
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of PDepend.
4
 *
5
 * PHP Version 5
6
 *
7
 * Copyright (c) 2008-2017 Manuel Pichler <[email protected]>.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *   * Redistributions of source code must retain the above copyright
15
 *     notice, this list of conditions and the following disclaimer.
16
 *
17
 *   * Redistributions in binary form must reproduce the above copyright
18
 *     notice, this list of conditions and the following disclaimer in
19
 *     the documentation and/or other materials provided with the
20
 *     distribution.
21
 *
22
 *   * Neither the name of Manuel Pichler nor the names of his
23
 *     contributors may be used to endorse or promote products derived
24
 *     from this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
 * POSSIBILITY OF SUCH DAMAGE.
38
 *
39
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
40
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
41
 * @since 2.3
42
 */
43
44
namespace PDepend\Source\Language\PHP;
45
46
use PDepend\AbstractTest;
47
use PDepend\Source\AST\ASTClass;
48
use PDepend\Source\AST\ASTConstantDeclarator;
49
use PDepend\Source\AST\ASTConstantDefinition;
50
use PDepend\Source\AST\ASTExpression;
51
use PDepend\Source\Builder\Builder;
52
use PDepend\Source\Tokenizer\Tokenizer;
53
use PDepend\Util\Cache\CacheDriver;
54
55
/**
56
 * Test case for the {@link \PDepend\Source\Language\PHP\PHPParserVersion56} class.
57
 *
58
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
59
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
60
 * @since 2.3
61
 *
62
 * @covers \PDepend\Source\Language\PHP\PHPParserVersion56
63
 * @group unittest
64
 */
65
class PHPParserVersion56Test extends AbstractTest
66
{
67
    /**
68
     * testComplexExpressionInParameterInitializer
69
     *
70
     * @return void
71
     */
72
    public function testComplexExpressionInParameterInitializer()
73
    {
74
        $node = $this->getFirstFunctionForTestCase()
75
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTFormalParameter');
76
77
        $this->assertNotNull($node);
78
    }
79
80
    /**
81
     * testComplexExpressionInConstantInitializer
82
     *
83
     * @return void
84
     */
85
    public function testComplexExpressionInConstantDeclarator()
86
    {
87
        $node = $this->getFirstClassForTestCase()
88
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTConstantDeclarator');
89
90
        $this->assertNotNull($node);
91
    }
92
93
    /**
94
     * testComplexExpressionInFieldDeclaration
95
     *
96
     * @return void
97
     */
98
    public function testComplexExpressionInFieldDeclaration()
99
    {
100
        $node = $this->getFirstClassForTestCase()
101
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTFieldDeclaration');
102
103
        $this->assertNotNull($node);
104
    }
105
106
    /**
107
     * testPowExpressionInMethodBody
108
     *
109
     * @return void
110
     */
111
    public function testPowExpressionInMethodBody()
112
    {
113
        $node = $this->getFirstClassForTestCase()
114
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTReturnStatement');
115
116
        $this->assertSame('**', $node->getChild(0)->getChild(1)->getImage());
117
    }
118
119
    /**
120
     * testPowExpressionInFieldDeclaration
121
     *
122
     * @return void
123
     */
124
    public function testPowExpressionInFieldDeclaration()
125
    {
126
        $node = $this->getFirstClassForTestCase()
127
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTFieldDeclaration');
128
129
        $this->assertNotNull($node);
130
    }
131
132
    /**
133
     * @return void
134
     * @expectedException \PDepend\Source\Parser\UnexpectedTokenException
135
     * @expectedExceptionMessageRegExp (Unexpected token: list, line: 4, col: 21, file: )
136
     */
137
    public function testListKeywordAsMethodNameThrowsException()
138
    {
139
        $this->parseCodeResourceForTest();
140
    }
141
142
    /**
143
     * @return void
144
     * @expectedException \PDepend\Source\Parser\UnexpectedTokenException
145
     * @expectedExceptionMessageRegExp (Unexpected token: list, line: 2, col: 10, file: )
146
     */
147
    public function testListKeywordAsFunctionNameThrowsException()
148
    {
149
        $this->parseCodeResourceForTest();
150
    }
151
152
    /**
153
     * @return void
154
     */
155
    public function testUseStatement()
156
    {
157
        $this->assertNotNull($this->parseCodeResourceForTest());
158
    }
159
160
    /**
161
     * @return void
162
     * @expectedException \PDepend\Source\Parser\UnexpectedTokenException
163
     * @expectedExceptionMessageRegExp (^Unexpected token: \{, line: 2, col: 24, file: )
164
     */
165
    public function testGroupUseStatementThrowsException()
166
    {
167
        $this->parseCodeResourceForTest();
168
    }
169
170
    /**
171
     * @return void
172
     * @expectedException \PDepend\Source\Parser\UnexpectedTokenException
173
     * @expectedExceptionMessageRegExp (^Unexpected token: ::, line: 8, col: 24, file: )
174
     */
175
    public function testUniformVariableSyntaxThrowsException()
176
    {
177
        $this->parseCodeResourceForTest();
178
    }
179
180
    /**
181
     * @return void
182
     */
183
    public function testEllipsisOperatorInFunctionCall()
184
    {
185
        $this->assertNotNull($this->parseCodeResourceForTest());
186
    }
187
188
    /**
189
     * Tests that the parser throws an exception when it detects an invalid
190
     * token in a method or property declaration.
191
     *
192
     * @return void
193
     */
194
    public function testParserThrowsUnexpectedTokenExceptionForInvalidTokenInPropertyDeclaration()
195
    {
196
        $this->setExpectedException(
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0; use expectException() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
197
            '\\PDepend\\Source\\Parser\\UnexpectedTokenException',
198
            'Unexpected token: const, line: 4, col: 13, file: '
199
        );
200
201
        $this->parseCodeResourceForTest();
202
    }
203
204
    /**
205
     * Tests issue with constant array concatenation.
206
     * https://github.com/pdepend/pdepend/issues/299
207
     *
208
     * @return void
209
     */
210
    public function testConstantArrayConcatenation()
211
    {
212
        /** @var ASTClass $class */
213
        $class = $this->getFirstClassForTestCase();
214
215
        /** @var ASTConstantDefinition[] $sontants */
216
        $constants = $class->getChildren();
217
218
        $this->assertCount(2, $constants);
219
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTConstantDefinition', $constants[0]);
220
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTConstantDefinition', $constants[1]);
221
222
        /** @var ASTConstantDeclarator[] $declarators */
223
        $declarators = $constants[1]->getChildren();
224
225
        $this->assertCount(1, $declarators);
226
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTConstantDeclarator', $declarators[0]);
227
228
        /** @var ASTExpression $expression */
229
        $expression = $declarators[0]->getValue()->getValue();
230
231
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTExpression', $expression);
232
233
        $nodes = $expression->getChildren();
234
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTMemberPrimaryPrefix', $nodes[0]);
235
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTExpression', $nodes[1]);
236
        $this->assertSame('+', $nodes[1]->getImage());
237
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTArray', $nodes[2]);
238
239
        $nodes = $nodes[0]->getChildren();
240
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTSelfReference', $nodes[0]);
241
        $this->assertInstanceOf('PDepend\\Source\\AST\\ASTConstantPostfix', $nodes[1]);
242
        $this->assertSame('A', $nodes[1]->getImage());
243
    }
244
245
    /**
246
     * @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
247
     * @param \PDepend\Source\Builder\Builder $builder
248
     * @param \PDepend\Util\Cache\CacheDriver $cache
249
     * @return \PDepend\Source\Language\PHP\AbstractPHPParser
250
     */
251
    protected function createPHPParser(Tokenizer $tokenizer, Builder $builder, CacheDriver $cache)
252
    {
253
        return $this->getMockForAbstractClass(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getMockFor...er, $builder, $cache)); (PHPUnit_Framework_MockObject_MockObject) is incompatible with the return type of the parent method PDepend\AbstractTest::createPHPParser of type PDepend\Source\Language\PHP\PHPParserGeneric.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
254
            'PDepend\\Source\\Language\\PHP\\PHPParserVersion56',
255
            array($tokenizer, $builder, $cache)
256
        );
257
    }
258
259
    /**
260
     * Tests that the parser throws an exception when it detects a reserved keyword
261
     * in constant class names.
262
     *
263
     * @return void
264
     */
265
    public function testReservedKeyword()
266
    {
267
        $this->setExpectedException(
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0; use expectException() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
268
            '\\PDepend\\Source\\Parser\\UnexpectedTokenException',
269
            'Unexpected token: NEW, line: 5, col: 11, file: '
270
        );
271
272
        $this->parseCodeResourceForTest();
273
    }
274
}
275