[TASK] Make MethodCallStaticMatcherTest notice free
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Tests / Unit / ExtensionScanner / Php / Matcher / MethodCallStaticMatcherTest.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\GeneratorClassesResolver;
22 use TYPO3\CMS\Install\ExtensionScanner\Php\Matcher\MethodCallStaticMatcher;
23 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
24
25 /**
26 * Test case
27 */
28 class MethodCallStaticMatcherTest extends UnitTestCase
29 {
30 /**
31 * @test
32 */
33 public function hitsFromFixtureAreFound()
34 {
35 $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
36 $fixtureFile = __DIR__ . '/Fixtures/MethodCallStaticMatcherFixture.php';
37 $statements = $parser->parse(file_get_contents($fixtureFile));
38
39 $traverser = new NodeTraverser();
40 $traverser->addVisitor(new NameResolver());
41 $traverser->addVisitor(new GeneratorClassesResolver());
42
43 $configuration = [
44 'TYPO3\CMS\Backend\Utility\BackendUtility::getAjaxUrl' => [
45 'numberOfMandatoryArguments' => 1,
46 'maximumNumberOfArguments' => 2,
47 'restFiles' => [
48 'Breaking-80700-DeprecatedFunctionalityRemoved.rst',
49 'Deprecation-75340-MethodsRelatedToGeneratingTraditionalBackendAJAXURLs.rst',
50 ],
51 ],
52 ];
53 $subject = new MethodCallStaticMatcher($configuration);
54 $traverser->addVisitor($subject);
55 $traverser->traverse($statements);
56 $expectedHitLineNumbers = [
57 28,
58 30,
59 ];
60 $actualHitLineNumbers = [];
61 foreach ($subject->getMatches() as $hit) {
62 $actualHitLineNumbers[] = $hit['line'];
63 }
64 $this->assertEquals($expectedHitLineNumbers, $actualHitLineNumbers);
65 }
66
67 /**
68 * @return array
69 */
70 public function matchesReturnsExpectedRestFilesDataProvider()
71 {
72 return [
73 'two rest candidates with same number of arguments' => [
74 [
75 'Foo::aMethod' => [
76 'numberOfMandatoryArguments' => 0,
77 'maximumNumberOfArguments' => 2,
78 'restFiles' => [
79 'Foo-1.rst',
80 'Foo-2.rst',
81 ],
82 ],
83 'Bar::aMethod' => [
84 'numberOfMandatoryArguments' => 0,
85 'maximumNumberOfArguments' => 2,
86 'restFiles' => [
87 'Bar-1.rst',
88 'Bar-2.rst',
89 ],
90 ],
91 ],
92 '<?php
93 $someVar::aMethod();',
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, only one hits because second candidate needs one argument' => [
106 [
107 'Foo::aMethod' => [
108 'numberOfMandatoryArguments' => 0,
109 'maximumNumberOfArguments' => 2,
110 'restFiles' => [
111 'Foo-1.rst',
112 ],
113 ],
114 'Bar::aMethod' => [
115 'numberOfMandatoryArguments' => 1,
116 'maximumNumberOfArguments' => 2,
117 'restFiles' => [
118 'Bar-1.rst',
119 ],
120 ],
121 ],
122 '<?php
123 $someVar::aMethod();',
124 [
125 0 => [
126 'restFiles' => [
127 'Foo-1.rst',
128 ],
129 ],
130 ],
131 ],
132 'three candidates, first and second hits' => [
133 [
134 'Foo::aMethod' => [
135 'numberOfMandatoryArguments' => 2,
136 'maximumNumberOfArguments' => 4,
137 'restFiles' => [
138 'Foo-1.rst',
139 ],
140 ],
141 'Bar::aMethod' => [
142 'numberOfMandatoryArguments' => 1,
143 'maximumNumberOfArguments' => 4,
144 'restFiles' => [
145 'Bar-1.rst',
146 ],
147 ],
148 'FooBar::aMethod' => [
149 'numberOfMandatoryArguments' => 3,
150 'maximumNumberOfArguments' => 4,
151 'restFiles' => [
152 'FooBar-1.rst',
153 ],
154 ],
155 ],
156 '<?php
157 $someVar::aMethod(\'arg1\', \'arg2\');',
158 [
159 0 => [
160 'restFiles' => [
161 'Foo-1.rst',
162 'Bar-1.rst',
163 ],
164 ],
165 ],
166 ],
167 'one candidate, does not hit, not enough arguments given' => [
168 [
169 'Foo::aMethod' => [
170 'numberOfMandatoryArguments' => 1,
171 'maximumNumberOfArguments' => 2,
172 'restFiles' => [
173 'Foo-1.rst',
174 ],
175 ],
176 ],
177 '<?php
178 $someVar::aMethod();',
179 [], // no hit
180 ],
181 'too many arguments given' => [
182 [
183 'Foo::aMethod' => [
184 'numberOfMandatoryArguments' => 1,
185 'maximumNumberOfArguments' => 1,
186 'restFiles' => [
187 'Foo-1.rst',
188 ],
189 ],
190 ],
191 '<?php
192 $someVar::aMethod($foo, $bar);',
193 [], // no hit
194 ],
195 'method call using argument unpacking' => [
196 [
197 'Foo::aMethod' => [
198 'numberOfMandatoryArguments' => 2,
199 'maximumNumberOfArguments' => 2,
200 'restFiles' => [
201 'Foo-1.rst',
202 ],
203 ],
204 ],
205 '<?php
206 $args = [\'arg1\', \'arg2\', \'arg3\'];
207 $someVar::aMethod(...$args);',
208 [
209 0 => [
210 'restFiles' => [
211 'Foo-1.rst',
212 ],
213 ],
214 ],
215 ],
216 'method call using argument unpacking with more than max number of args given arguments' => [
217 [
218 'Foo::aMethod' => [
219 'numberOfMandatoryArguments' => 2,
220 'maximumNumberOfArguments' => 2,
221 'restFiles' => [
222 'Foo-1.rst',
223 ],
224 ],
225 ],
226 '<?php
227 $args1 = [\'arg1\', \'arg2\', \'arg3\'];
228 $args2 = [\'arg4\', \'arg5\', \'arg6\'];
229 $args3 = [\'arg7\', \'arg8\', \'arg9\'];
230 $someVar::aMethod(...$args1, ...$args2, ...$args3);',
231 [
232 0 => [
233 'restFiles' => [
234 'Foo-1.rst',
235 ],
236 ],
237 ],
238 ],
239 // something wrong here
240 'double linked .rst file is returned only once' => [
241 [
242 'Foo::aMethod' => [
243 'numberOfMandatoryArguments' => 0,
244 'maximumNumberOfArguments' => 2,
245 'restFiles' => [
246 'aRest.rst',
247 ],
248 ],
249 'Bar::aMethod' => [
250 'numberOfMandatoryArguments' => 0,
251 'maximumNumberOfArguments' => 2,
252 'restFiles' => [
253 'aRest.rst',
254 ],
255 ],
256 ],
257 '<?php
258 $someVar::aMethod(\'foo\');',
259 [
260 0 => [
261 'restFiles' => [
262 'aRest.rst',
263 ],
264 ],
265 ],
266 ],
267 ];
268 }
269
270 /**
271 * @test
272 * @dataProvider matchesReturnsExpectedRestFilesDataProvider
273 */
274 public function matchesReturnsExpectedRestFiles(array $configuration, string $phpCode, array $expected)
275 {
276 $parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
277 $statements = $parser->parse($phpCode);
278
279 $subject = new MethodCallStaticMatcher($configuration);
280
281 $traverser = new NodeTraverser();
282 $traverser->addVisitor($subject);
283 $traverser->traverse($statements);
284
285 $result = $subject->getMatches();
286 if (isset($expected[0], $result[0])) {
287 $this->assertEquals($expected[0]['restFiles'], $result[0]['restFiles']);
288 } else {
289 $this->assertEquals($expected, $result);
290 }
291 }
292 }