e14ef040cef7cd6ad25b9ce46ad29ee2eb53ea5f
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Tests / Unit / ExtensionScanner / Php / Matcher / MethodArgumentRequiredMatcherTest.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\MethodArgumentRequiredMatcher;
22 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
23
24 /**
25 * Test case
26 */
27 class MethodArgumentRequiredMatcherTest 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/MethodArgumentRequiredMatcherFixture.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\Frontend\ContentObject\ContentObjectRenderer->searchWhere' => [
48 'numberOfMandatoryArguments' => 3,
49 'maximumNumberOfArguments' => 3,
50 'restFiles' => [
51 'Breaking-80700-DeprecatedFunctionalityRemoved.rst',
52 ],
53 ],
54 ];
55 $subject = new MethodArgumentRequiredMatcher($configuration);
56 $traverser->addVisitor($subject);
57 $traverser->traverse($statements);
58 $expectedHitLineNumbers = [
59 28,
60 29,
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 'numberOfMandatoryArguments' => 1,
79 'maximumNumberOfArguments' => 2,
80 'restFiles' => [
81 'Foo-1.rst',
82 'Foo-2.rst',
83 ],
84 ],
85 'Bar->aMethod' => [
86 'numberOfMandatoryArguments' => 2,
87 'maximumNumberOfArguments' => 3,
88 'restFiles' => [
89 'Bar-1.rst',
90 'Bar-2.rst',
91 ],
92 ],
93 ],
94 '<?php
95 $someVar->aMethod();',
96 [
97 0 => [
98 'restFiles' => [
99 'Foo-1.rst',
100 'Foo-2.rst',
101 'Bar-1.rst',
102 'Bar-2.rst',
103 ],
104 ],
105 ],
106 ],
107 'two candidates, only one hits because second candidate needs two arguments' => [
108 [
109 'Foo->aMethod' => [
110 'numberOfMandatoryArguments' => 1,
111 'maximumNumberOfArguments' => 3,
112 'restFiles' => [
113 'Foo-1.rst',
114 ],
115 ],
116 'Bar->aMethod' => [
117 'numberOfMandatoryArguments' => 2,
118 'maximumNumberOfArguments' => 3,
119 'restFiles' => [
120 'Bar-1.rst',
121 ],
122 ],
123 ],
124 '<?php
125 $someVar->aMethod(\'arg1\');',
126 [
127 0 => [
128 'restFiles' => [
129 'Bar-1.rst',
130 ],
131 ],
132 ],
133 ],
134 'one candidate, does not hit' => [
135 [
136 'Foo->aMethod' => [
137 'numberOfMandatoryArguments' => 1,
138 'maximumNumberOfArguments' => 3,
139 'restFiles' => [
140 'Foo-1.rst',
141 ],
142 ],
143 ],
144 '<?php
145 $someVar->aMethod(\'arg1\');',
146 [], // no hit
147 ],
148 'too many arguments given' => [
149 [
150 'Foo->aMethod' => [
151 'numberOfMandatoryArguments' => 1,
152 'maximumNumberOfArguments' => 1,
153 'restFiles' => [
154 'Foo-1.rst',
155 ],
156 ],
157 ],
158 '<?php
159 $someVar->aMethod($foo, $bar);',
160 [], // no hit
161 ],
162 'method call using argument unpacking' => [
163 [
164 'Foo->aMethod' => [
165 'numberOfMandatoryArguments' => 2,
166 'maximumNumberOfArguments' => 3,
167 'restFiles' => [
168 'Foo-1.rst',
169 ],
170 ],
171 ],
172 '<?php
173 $args = [\'arg1\', \'arg2\', \'arg3\'];
174 $someVar->aMethod(...$args);',
175 [], // no match
176 ],
177 'method call using argument unpacking with more than max number of args given arguments' => [
178 [
179 'Foo->aMethod' => [
180 'numberOfMandatoryArguments' => 2,
181 'maximumNumberOfArguments' => 2,
182 'restFiles' => [
183 'Foo-1.rst',
184 ],
185 ],
186 ],
187 '<?php
188 $args1 = [\'arg1\', \'arg2\', \'arg3\'];
189 $args2 = [\'arg4\', \'arg5\', \'arg6\'];
190 $args3 = [\'arg7\', \'arg8\', \'arg9\'];
191 $someVar->aMethod(...$args1, ...$args2, ...$args3);',
192 [], // no match
193 ],
194 'double linked .rst file is returned only once' => [
195 [
196 'Foo->aMethod' => [
197 'numberOfMandatoryArguments' => 1,
198 'maximumNumberOfArguments' => 2,
199 'restFiles' => [
200 'aRest.rst',
201 ],
202 ],
203 'Bar->aMethod' => [
204 'numberOfMandatoryArguments' => 1,
205 'maximumNumberOfArguments' => 2,
206 'restFiles' => [
207 'aRest.rst',
208 ],
209 ],
210 ],
211 '<?php
212 $someVar->aMethod();',
213 [
214 0 => [
215 'restFiles' => [
216 'aRest.rst',
217 ],
218 ],
219 ],
220 ],
221 ];
222 }
223
224 /**
225 * @test
226 * @dataProvider matchesReturnsExpectedRestFilesDataProvider
227 */
228 public function matchesReturnsExpectedRestFiles(array $configuration, string $phpCode, array $expected)
229 {
230 $parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
231 $statements = $parser->parse($phpCode);
232
233 $subject = new MethodArgumentRequiredMatcher($configuration);
234
235 $traverser = new NodeTraverser();
236 $traverser->addVisitor($subject);
237 $traverser->traverse($statements);
238
239 $result = $subject->getMatches();
240 $this->assertEquals($expected[0]['restFiles'], $result[0]['restFiles']);
241 }
242 }