ddbcbe2c91663bfc633e1e1c02cf461365970d3e
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Tests / Unit / ExtensionScanner / Php / Matcher / MethodArgumentUnusedMatcherTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Install\Tests\Unit\ExtensionScanner\Php\Matcher;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use PhpParser\NodeTraverser;
19 use PhpParser\NodeVisitor\NameResolver;
20 use PhpParser\ParserFactory;
21 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\MethodArgumentUnusedMatcher;
22 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
23
24 /**
25 * Test case
26 */
27 class MethodArgumentUnusedMatcherTest extends UnitTestCase
28 {
29 /**
30 * Subject is not notice free, disable E_NOTICES
31 */
32 protected static $suppressNotices = true;
33
34 /**
35 * @test
36 */
37 public function hitsFromFixtureAreFound()
38 {
39 $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
40 $fixtureFile = __DIR__ . '/Fixtures/MethodArgumentUnusedMatcherFixture.php';
41 $statements = $parser->parse(file_get_contents($fixtureFile));
42
43 $traverser = new NodeTraverser();
44 $traverser->addVisitor(new NameResolver());
45
46 $configuration = [
47 'TYPO3\CMS\Core\Html\RteHtmlParser->RTE_transform' => [
48 'unusedArgumentNumbers' => [ 2 ],
49 'restFiles' => [
50 'Breaking-80700-DeprecatedFunctionalityRemoved.rst',
51 'Deprecation-79341-MethodsRelatedToRichtextConfiguration.rst',
52 ],
53 ],
54 ];
55 $subject = new MethodArgumentUnusedMatcher($configuration);
56 $traverser->addVisitor($subject);
57 $traverser->traverse($statements);
58 $expectedHitLineNumbers = [
59 26,
60 27,
61 ];
62 $actualHitLineNumbers = [];
63 foreach ($subject->getMatches() as $hit) {
64 $actualHitLineNumbers[] = $hit['line'];
65 }
66 $this->assertEquals($expectedHitLineNumbers, $actualHitLineNumbers);
67 }
68
69 /**
70 * @return array
71 */
72 public function matchesReturnsExpectedRestFilesDataProvider()
73 {
74 return [
75 'two rest candidates with same number of arguments' => [
76 [
77 'Foo->aMethod' => [
78 'unusedArgumentNumbers' => [ 1 ],
79 'restFiles' => [
80 'Foo-1.rst',
81 'Foo-2.rst',
82 ],
83 ],
84 'Bar->aMethod' => [
85 'unusedArgumentNumbers' => [ 1 ],
86 'restFiles' => [
87 'Bar-1.rst',
88 'Bar-2.rst',
89 ],
90 ],
91 ],
92 '<?php
93 $someVar->aMethod(\'foo\');',
94 [
95 0 => [
96 'restFiles' => [
97 'Foo-1.rst',
98 'Foo-2.rst',
99 'Bar-1.rst',
100 'Bar-2.rst',
101 ],
102 ],
103 ],
104 ],
105 'two candidates, multiple matches' => [
106 [
107 'Foo->aMethod' => [
108 'unusedArgumentNumbers' => [ 1, 2 ],
109 'restFiles' => [
110 'Foo-1.rst',
111 ],
112 ],
113 'Bar->aMethod' => [
114 'unusedArgumentNumbers' => [ 3 ],
115 'restFiles' => [
116 'Bar-1.rst',
117 ],
118 ],
119 ],
120 '<?php
121 $someVar->aMethod(\'arg1\', \'arg2\', \'arg3\');',
122 [
123 0 => [
124 'restFiles' => [
125 'Foo-1.rst',
126 'Bar-1.rst',
127 ],
128 ],
129 ],
130 ],
131 'one candidate, no hit, not enough arguments' => [
132 [
133 'Foo->aMethod' => [
134 'unusedArgumentNumbers' => [ 2, 3 ],
135 'restFiles' => [
136 'Foo-1.rst',
137 ],
138 ],
139 ],
140 '<?php
141 $someVar->aMethod(\'arg1\');',
142 [], // no hit
143 ],
144 'one candidate, no hit, given as null is ok' => [
145 [
146 'Foo->aMethod' => [
147 'unusedArgumentNumbers' => [ 2, 3 ],
148 'restFiles' => [
149 'Foo-1.rst',
150 ],
151 ],
152 ],
153 '<?php
154 $someVar->aMethod(\'arg1\', null, null);',
155 [], // no hit
156 ],
157 'one match, third argument still given not null' => [
158 [
159 'Foo->aMethod' => [
160 'unusedArgumentNumbers' => [ 2, 3 ],
161 'restFiles' => [
162 'aRest.rst',
163 ],
164 ],
165 ],
166 '<?php
167 $someVar->aMethod(\'arg1\', null, \'arg3\');',
168 [
169 0 => [
170 'restFiles' => [
171 'aRest.rst',
172 ],
173 ],
174 ],
175 ],
176 'no match, scanning ignored as soon as argument unpacking is used' => [
177 [
178 'Foo->aMethod' => [
179 'unusedArgumentNumbers' => [ 1, 3 ],
180 'restFiles' => [
181 'Foo-1.rst',
182 ],
183 ],
184 ],
185 '<?php
186 $args1 = [\'arg1\', \'arg2\', \'arg3\'];
187 $args2 = [\'arg4\', \'arg5\', \'arg6\'];
188 $args3 = [\'arg7\', \'arg8\', \'arg9\'];
189 $someVar->aMethod(...$args1, ...$args2, ...$args3);',
190 [],
191 ],
192 'double linked .rst file is returned only once' => [
193 [
194 'Foo->aMethod' => [
195 'unusedArgumentNumbers' => [ 1 ],
196 'restFiles' => [
197 'aRest.rst',
198 ],
199 ],
200 'Bar->aMethod' => [
201 'unusedArgumentNumbers' => [ 1 ],
202 'restFiles' => [
203 'aRest.rst',
204 ],
205 ],
206 ],
207 '<?php
208 $someVar->aMethod(\'foo\');',
209 [
210 0 => [
211 'restFiles' => [
212 'aRest.rst',
213 ],
214 ],
215 ],
216 ],
217 ];
218 }
219
220 /**
221 * @test
222 * @dataProvider matchesReturnsExpectedRestFilesDataProvider
223 */
224 public function matchesReturnsExpectedRestFiles(array $configuration, string $phpCode, array $expected)
225 {
226 $parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
227 $statements = $parser->parse($phpCode);
228
229 $subject = new MethodArgumentUnusedMatcher($configuration);
230
231 $traverser = new NodeTraverser();
232 $traverser->addVisitor($subject);
233 $traverser->traverse($statements);
234
235 $result = $subject->getMatches();
236 $this->assertEquals($expected[0]['restFiles'], $result[0]['restFiles']);
237 }
238 }