traverseStringAST()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 3
c 1
b 0
f 1
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace ComposerRequireCheckerTest\NodeVisitor;
4
5
use ComposerRequireChecker\NodeVisitor\UsedSymbolCollector;
6
use PhpParser\NodeTraverser;
7
use PhpParser\NodeTraverserInterface;
8
use PhpParser\NodeVisitor\NameResolver;
9
use PhpParser\Parser;
10
use PhpParser\ParserFactory;
11
use PHPUnit\Framework\TestCase;
12
13
/**
14
 * @coversNothing
15
 *
16
 * @group functional
17
 */
18
final class UsedSymbolCollectorFunctionalTest extends TestCase
19
{
20
    /**
21
     * @var UsedSymbolCollector
22
     */
23
    private $collector;
24
25
    /**
26
     * @var Parser
27
     */
28
    private $parser;
29
30
    /**
31
     * @var NodeTraverserInterface
32
     */
33
    private $traverser;
34
35
    /**
36
     * {@inheritDoc}
37
     */
38
    protected function setUp(): void
39
    {
40
        $this->collector = new UsedSymbolCollector();
41
        $this->parser    = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
42
        $this->traverser = new NodeTraverser();
43
44
        $this->traverser->addVisitor(new NameResolver());
45
        $this->traverser->addVisitor($this->collector);
46
    }
47
48
    public function testWillCollectSymbolsUsedInThisFile(): void
49
    {
50
        $this->traverseClassAST(self::class);
51
52
        self::assertSameCollectedSymbols(
53
            [
54
                'ComposerRequireChecker\NodeVisitor\UsedSymbolCollector',
55
                'PHPUnit\Framework\TestCase',
56
                'PhpParser\NodeTraverser',
57
                'PhpParser\ParserFactory',
58
                'file_get_contents',
59
                'ReflectionClass',
60
                'array_diff',
61
                'self',
62
                'PhpParser\NodeVisitor\NameResolver',
63
                'string',
64
                'array',
65
                'void',
66
            ],
67
            $this->collector->getCollectedSymbols()
68
        );
69
    }
70
71
    public function testWillCollectFunctionDefinitionTypes(): void
72
    {
73
        $this->traverseStringAST('<?php function foo(My\ParameterType $bar, array $fooBar) {}');
74
75
        self::assertSameCollectedSymbols(
76
            [
77
                'My\ParameterType',
78
                'array',
79
            ],
80
            $this->collector->getCollectedSymbols()
81
        );
82
    }
83
84
    public function testWillCollectMethodDefinitionTypes(): void
85
    {
86
        $this->traverseStringAST('<?php class Foo { function foo(My\ParameterType $bar, array $fooBar) {}}');
87
88
        self::assertSameCollectedSymbols(
89
            [
90
                'My\ParameterType',
91
                'array',
92
            ],
93
            $this->collector->getCollectedSymbols()
94
        );
95
    }
96
97
    public function testWillCollectFunctionReturnTypes(): void
98
    {
99
        $this->traverseStringAST('<?php function foo($bar) : My\ReturnType {}');
100
101
        self::assertSameCollectedSymbols(
102
            [
103
                'My\ReturnType',
104
            ],
105
            $this->collector->getCollectedSymbols()
106
        );
107
    }
108
109
    public function testWillCollectMethodReturnTypes(): void
110
    {
111
        $this->traverseStringAST('<?php class Foo { function foo($bar) : My\ReturnType {}}');
112
113
        self::assertSameCollectedSymbols(
114
            [
115
                'My\ReturnType',
116
            ],
117
            $this->collector->getCollectedSymbols()
118
        );
119
    }
120
121
    public function testWillCollectSimpleFunctionReturnTypes(): void
122
    {
123
        $this->traverseStringAST('<?php function foo($bar) : int {}');
124
125
        self::assertSameCollectedSymbols(
126
            [
127
                'int',
128
            ],
129
            $this->collector->getCollectedSymbols()
130
        );
131
    }
132
133
    public function testWontCollectAnyUsageTypes(): void
134
    {
135
        $this->traverseStringAST('<?php function foo($bar) {}');
136
137
        self::assertSameCollectedSymbols(
138
            [],
139
            $this->collector->getCollectedSymbols()
140
        );
141
    }
142
143
    public function testUseTraitAdaptionAlias(): void
144
    {
145
        $this->traverseStringAST('<?php namespace Foo; trait BarTrait { protected function test(){}} class UseTrait { use BarTrait {test as public;} }');
146
147
        self::assertSameCollectedSymbols(
148
            ['Foo\BarTrait'],
149
            $this->collector->getCollectedSymbols()
150
        );
151
    }
152
153
    private function traverseStringAST(string $stringAST)
154
    {
155
        return $this->traverser->traverse(
156
            $this->parser->parse(
0 ignored issues
show
Bug introduced by
It seems like $this->parser->parse($stringAST) can also be of type null; however, parameter $nodes of PhpParser\NodeTraverserInterface::traverse() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

156
            /** @scrutinizer ignore-type */ $this->parser->parse(
Loading history...
157
                $stringAST
158
            )
159
        );
160
    }
161
162
    private function traverseClassAST(string $className): array
163
    {
164
        return $this->traverseStringAST(
165
            file_get_contents((new \ReflectionClass($className))->getFileName())
166
        );
167
    }
168
169
    private static function assertSameCollectedSymbols(array $expected, array $actual): void
170
    {
171
        self::assertSame(array_diff($expected, $actual), array_diff($actual, $expected));
172
    }
173
}
174