Completed
Push — master ( bb7a53...c89193 )
by Kyle
13s queued 11s
created

testParenthesisAroundCallableParsesArguments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
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\ASTExpression;
48
use PDepend\Source\AST\ASTNamespace;
49
use PDepend\Source\Builder\Builder;
50
use PDepend\Source\Tokenizer\Tokenizer;
51
use PDepend\Util\Cache\CacheDriver;
52
53
/**
54
 * Test case for the {@link \PDepend\Source\Language\PHP\PHPParserVersion70} class.
55
 *
56
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
57
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
58
 * @since 2.3
59
 *
60
 * @covers \PDepend\Source\Language\PHP\PHPParserVersion70
61
 * @group unittest
62
 */
63
class PHPParserVersion70Test extends AbstractTest
64
{
65
    /**
66
     * testFormalParameterScalarTypeHintInt
67
     *
68
     * @return void
69
     */
70
    public function testFormalParameterScalarTypeHintInt()
71
    {
72
        $type = $this->getFirstFormalParameterForTestCase()->getType();
73
74
        $this->assertTrue($type->isScalar());
75
        $this->assertEquals('int', $type->getImage());
76
    }
77
78
    /**
79
     * testFormalParameterScalarTypeHintString
80
     *
81
     * @return void
82
     */
83
    public function testFormalParameterScalarTypeHintString()
84
    {
85
        $type = $this->getFirstFormalParameterForTestCase()->getType();
86
87
        $this->assertTrue($type->isScalar());
88
        $this->assertEquals('string', $type->getImage());
89
    }
90
91
    /**
92
     * testFormalParameterScalarTypeHintFloat
93
     *
94
     * @return void
95
     */
96
    public function testFormalParameterScalarTypeHintFloat()
97
    {
98
        $type = $this->getFirstFormalParameterForTestCase()->getType();
99
100
        $this->assertTrue($type->isScalar());
101
        $this->assertEquals('float', $type->getImage());
102
    }
103
104
    /**
105
     * testFormalParameterScalarTypeHintBool
106
     *
107
     * @return void
108
     */
109
    public function testFormalParameterScalarTypeHintBool()
110
    {
111
        $type = $this->getFirstFormalParameterForTestCase()->getType();
112
113
        $this->assertTrue($type->isScalar());
114
        $this->assertEquals('bool', $type->getImage());
115
    }
116
117
    /**
118
     * testFormalParameterStillWorksWithTypeHintArray
119
     *
120
     * @return void
121
     */
122
    public function testFormalParameterStillWorksWithTypeHintArray()
123
    {
124
        $type = $this->getFirstFormalParameterForTestCase()->getChild(0);
125
126
        $this->assertFalse($type->isScalar());
127
    }
128
129
    /**
130
     * testFunctionReturnTypeHintInt
131
     *
132
     * @return void
133
     */
134
    public function testFunctionReturnTypeHintInt()
135
    {
136
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
137
138
        $this->assertTrue($type->isScalar());
139
        $this->assertSame('int', $type->getImage());
140
    }
141
142
    /**
143
     * testFunctionReturnTypeHintFloat
144
     *
145
     * @return void
146
     */
147
    public function testFunctionReturnTypeHintFloat()
148
    {
149
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
150
151
        $this->assertTrue($type->isScalar());
152
        $this->assertSame('float', $type->getImage());
153
    }
154
155
    /**
156
     * testFunctionReturnTypeHintString
157
     *
158
     * @return void
159
     */
160
    public function testFunctionReturnTypeHintString()
161
    {
162
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
163
164
        $this->assertTrue($type->isScalar());
165
        $this->assertSame('string', $type->getImage());
166
    }
167
168
    /**
169
     * testFunctionReturnTypeHintBool
170
     *
171
     * @return void
172
     */
173
    public function testFunctionReturnTypeHintBool()
174
    {
175
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
176
177
        $this->assertTrue($type->isScalar());
178
        $this->assertSame('bool', $type->getImage());
179
    }
180
181
    /**
182
     * testFunctionReturnTypeHintArray
183
     *
184
     * @return void
185
     */
186
    public function testFunctionReturnTypeHintArray()
187
    {
188
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
189
190
        $this->assertTrue($type->isArray());
191
        $this->assertSame('array', $type->getImage());
192
    }
193
194
    /**
195
     * testFunctionReturnTypeHintCallable
196
     *
197
     * @return void
198
     */
199 View Code Duplication
    public function testFunctionReturnTypeHintCallable()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
    {
201
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
202
203
        $this->assertFalse($type->isScalar());
204
        $this->assertFalse($type->isArray());
205
206
        $this->assertSame('callable', $type->getImage());
207
    }
208
209
    /**
210
     * testFunctionReturnTypeHintClass
211
     *
212
     * @return void
213
     */
214 View Code Duplication
    public function testFunctionReturnTypeHintClass()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
215
    {
216
        $type = $this->getFirstFunctionForTestCase()->getReturnType();
217
218
        $this->assertFalse($type->isScalar());
219
        $this->assertFalse($type->isArray());
220
221
        $this->assertSame('\Iterator', $type->getImage());
222
    }
223
224
    /**
225
     * testClosureReturnTypeHintInt
226
     *
227
     * @return void
228
     */
229
    public function testClosureReturnTypeHintInt()
230
    {
231
        $type = $this->getFirstClosureForTestCase()->getReturnType();
232
233
        $this->assertTrue($type->isScalar());
234
        $this->assertSame('int', $type->getImage());
235
    }
236
237
    /**
238
     * testClosureReturnTypeHintFloat
239
     *
240
     * @return void
241
     */
242
    public function testClosureReturnTypeHintFloat()
243
    {
244
        $type = $this->getFirstClosureForTestCase()->getReturnType();
245
246
        $this->assertTrue($type->isScalar());
247
        $this->assertSame('float', $type->getImage());
248
    }
249
250
    /**
251
     * testClosureReturnTypeHintString
252
     *
253
     * @return void
254
     */
255
    public function testClosureReturnTypeHintString()
256
    {
257
        $type = $this->getFirstClosureForTestCase()->getReturnType();
258
259
        $this->assertTrue($type->isScalar());
260
        $this->assertSame('string', $type->getImage());
261
    }
262
263
    /**
264
     * testClosureReturnTypeHintBool
265
     *
266
     * @return void
267
     */
268
    public function testClosureReturnTypeHintBool()
269
    {
270
        $type = $this->getFirstClosureForTestCase()->getReturnType();
271
272
        $this->assertTrue($type->isScalar());
273
        $this->assertSame('bool', $type->getImage());
274
    }
275
276
    /**
277
     * testClosureReturnTypeHintArray
278
     *
279
     * @return void
280
     */
281
    public function testClosureReturnTypeHintArray()
282
    {
283
        $type = $this->getFirstClosureForTestCase()->getReturnType();
284
285
        $this->assertTrue($type->isArray());
286
        $this->assertSame('array', $type->getImage());
287
    }
288
289
    /**
290
     * testClosureReturnTypeHintCallable
291
     *
292
     * @return void
293
     */
294 View Code Duplication
    public function testClosureReturnTypeHintCallable()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
    {
296
        $type = $this->getFirstClosureForTestCase()->getReturnType();
297
298
        $this->assertFalse($type->isScalar());
299
        $this->assertFalse($type->isArray());
300
301
        $this->assertSame('callable', $type->getImage());
302
    }
303
304
    /**
305
     * testClosureReturnTypeHintClass
306
     *
307
     * @return void
308
     */
309 View Code Duplication
    public function testClosureReturnTypeHintClass()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
310
    {
311
        $type = $this->getFirstClosureForTestCase()->getReturnType();
312
313
        $this->assertFalse($type->isScalar());
314
        $this->assertFalse($type->isArray());
315
316
        $this->assertSame('\\Iterator', $type->getImage());
317
    }
318
319
    /**
320
     * testSpaceshipOperatorWithStrings
321
     *
322
     * @return void
323
     */
324
    public function testSpaceshipOperatorWithStrings()
325
    {
326
        $expr = $this->getFirstClassMethodForTestCase()
327
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression')
328
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression');
329
330
        $this->assertSame('<=>', $expr->getImage());
331
    }
332
333
    /**
334
     * testSpaceshipOperatorWithNumbers
335
     *
336
     * @return void
337
     */
338
    public function testSpaceshipOperatorWithNumbers()
339
    {
340
        $expr = $this->getFirstClassMethodForTestCase()
341
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression')
342
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression');
343
344
        $this->assertSame('<=>', $expr->getImage());
345
    }
346
347
    /**
348
     * testSpaceshipOperatorWithArrays
349
     *
350
     * @return \PDepend\Source\AST\ASTExpression
351
     */
352
    public function testSpaceshipOperatorWithArrays()
353
    {
354
        $expr = $this->getFirstClassMethodForTestCase()
355
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression')
356
            ->getChild(1);
357
358
        $this->assertSame('<=>', $expr->getImage());
359
360
        return $expr;
361
    }
362
363
    /**
364
     * @param \PDepend\Source\AST\ASTExpression $expr
365
     * @return void
366
     * @depends testSpaceshipOperatorWithArrays
367
     */
368
    public function testSpaceshipOperatorHasExpectedStartLine(ASTExpression $expr)
369
    {
370
        $this->assertSame(6, $expr->getStartLine());
371
    }
372
373
    /**
374
     * @param \PDepend\Source\AST\ASTExpression $expr
375
     * @return void
376
     * @depends testSpaceshipOperatorWithArrays
377
     */
378
    public function testSpaceshipOperatorHasExpectedEndLine(ASTExpression $expr)
379
    {
380
        $this->assertSame(6, $expr->getEndLine());
381
    }
382
383
    /**
384
     * @param \PDepend\Source\AST\ASTExpression $expr
385
     * @return void
386
     * @depends testSpaceshipOperatorWithArrays
387
     */
388
    public function testSpaceshipOperatorHasExpectedStartColumn(ASTExpression $expr)
389
    {
390
        $this->assertSame(27, $expr->getStartColumn());
391
    }
392
393
    /**
394
     * @param \PDepend\Source\AST\ASTExpression $expr
395
     * @return void
396
     * @depends testSpaceshipOperatorWithArrays
397
     */
398
    public function testSpaceshipOperatorHasExpectedEndColumn(ASTExpression $expr)
399
    {
400
        $this->assertSame(29, $expr->getEndColumn());
401
    }
402
403
    /**
404
     * testNullCoalesceOperator
405
     *
406
     * @return void
407
     */
408
    public function testNullCoalesceOperator()
409
    {
410
        $expr = $this->getFirstClassMethodForTestCase()
411
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression')
412
            ->getFirstChildOfType('PDepend\\Source\\AST\\ASTExpression');
413
414
        $this->assertSame('??', $expr->getImage());
415
    }
416
417
    /**
418
     * @return void
419
     */
420
    public function testListKeywordAsMethodName()
421
    {
422
        $method = $this->getFirstMethodForTestCase();
423
        $this->assertNotNull($method);
424
    }
425
426
    /**
427
     * @return void
428
     * @expectedException \PDepend\Source\Parser\UnexpectedTokenException
429
     */
430
    public function testListKeywordAsFunctionNameThrowsException()
431
    {
432
        $this->parseCodeResourceForTest();
433
    }
434
435
    /**
436
     * @return \PDepend\Source\AST\ASTNamespace
437
     */
438
    public function testGroupUseStatement()
439
    {
440
        $namespaces = $this->parseCodeResourceForTest();
441
        $this->assertNotNull($namespaces);
442
443
        return $namespaces[0];
444
    }
445
446
    /**
447
     * @param \PDepend\Source\AST\ASTNamespace $namespace
448
     * @return void
449
     * @depends testGroupUseStatement
450
     */
451 View Code Duplication
    public function testGroupUseStatementClassNameResolution(ASTNamespace $namespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
    {
453
        $classes = $namespace->getClasses();
454
        $class = $classes[0];
455
456
        $this->assertEquals(
457
            'FooLibrary\Bar\Baz\ClassB',
458
            $class->getParentClass()->getNamespacedName()
459
        );
460
    }
461
462
    /**
463
     * @param \PDepend\Source\AST\ASTNamespace $namespace
464
     * @return void
465
     * @depends testGroupUseStatement
466
     */
467 View Code Duplication
    public function testGroupUseStatementAliasResolution(ASTNamespace $namespace)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
468
    {
469
        $classes = $namespace->getClasses();
470
        $class = $classes[1];
471
472
        $this->assertEquals(
473
            'FooLibrary\Bar\Baz\ClassD',
474
            $class->getParentClass()->getNamespacedName()
475
        );
476
    }
477
478
    /**
479
     * @return void
480
     */
481
    public function testUniformVariableSyntax()
482
    {
483
        $this->assertNotNull($this->parseCodeResourceForTest());
484
    }
485
486
    /**
487
     * @return void
488
     */
489
    public function testConstantNameArray()
490
    {
491
        $this->assertNotNull($this->parseCodeResourceForTest());
492
    }
493
494
    /**
495
     * @return void
496
     */
497
    public function testClassConstantNames()
498
    {
499
        $this->assertNotNull($this->parseCodeResourceForTest());
500
    }
501
502
    /**
503
     * @return void
504
     */
505
    public function testClassConstantNamesAccessed()
506
    {
507
        $this->assertNotNull($this->parseCodeResourceForTest());
508
    }
509
510
    /**
511
     * @return void
512
     */
513
    public function testClassMethodNames()
514
    {
515
        $this->assertNotNull($this->parseCodeResourceForTest());
516
    }
517
518
    /**
519
     * @return void
520
     */
521
    public function testClassMethodNamesInvoked()
522
    {
523
        $this->assertNotNull($this->parseCodeResourceForTest());
524
    }
525
526
    /**
527
     * @return void
528
     */
529
    public function testYieldFrom()
530
    {
531
        $this->assertNotNull($this->parseCodeResourceForTest());
532
    }
533
534
    /**
535
     * Tests that the parser throws an exception when it detects an invalid
536
     * token in a method or property declaration.
537
     *
538
     * @return void
539
     */
540
    public function testParserThrowsUnexpectedTokenExceptionForInvalidTokenInPropertyDeclaration()
541
    {
542
        $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...
543
            '\\PDepend\\Source\\Parser\\UnexpectedTokenException',
544
            'Unexpected token: const, line: 4, col: 13, file: '
545
        );
546
547
        $this->parseCodeResourceForTest();
548
    }
549
550
    /**
551
     * @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
552
     * @param \PDepend\Source\Builder\Builder $builder
553
     * @param \PDepend\Util\Cache\CacheDriver $cache
554
     * @return \PDepend\Source\Language\PHP\AbstractPHPParser
555
     */
556
    protected function createPHPParser(Tokenizer $tokenizer, Builder $builder, CacheDriver $cache)
557
    {
558
        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...
559
            'PDepend\\Source\\Language\\PHP\\PHPParserVersion70',
560
            array($tokenizer, $builder, $cache)
561
        );
562
    }
563
564
    public function testParenthesisAroundCallableParsesArguments()
565
    {
566
        $this->assertNotNull($this->parseCodeResourceForTest());
567
    }
568
}
569