These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of phpDocumentor. |
||
4 | * |
||
5 | * For the full copyright and license information, please view the LICENSE |
||
6 | * file that was distributed with this source code. |
||
7 | * |
||
8 | * @copyright 2010-2018 Mike van Riel<[email protected]> |
||
9 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
10 | * @link http://phpdoc.org |
||
11 | */ |
||
12 | |||
13 | namespace phpDocumentor\Behat\Contexts\Ast; |
||
14 | |||
15 | use Behat\Behat\Context\Context; |
||
16 | use Behat\Behat\Tester\Exception\PendingException; |
||
17 | use Behat\Gherkin\Node\PyStringNode; |
||
18 | use phpDocumentor\Descriptor\ArgumentDescriptor; |
||
19 | use phpDocumentor\Descriptor\ClassDescriptor; |
||
20 | use phpDocumentor\Descriptor\Collection; |
||
21 | use phpDocumentor\Descriptor\ConstantDescriptor; |
||
22 | use phpDocumentor\Descriptor\DescriptorAbstract; |
||
23 | use phpDocumentor\Descriptor\FileDescriptor; |
||
24 | use phpDocumentor\Descriptor\FunctionDescriptor; |
||
25 | use phpDocumentor\Descriptor\MethodDescriptor; |
||
26 | use phpDocumentor\Descriptor\NamespaceDescriptor; |
||
27 | use phpDocumentor\Descriptor\PropertyDescriptor; |
||
28 | use phpDocumentor\Descriptor\Tag\ParamDescriptor; |
||
29 | use phpDocumentor\Descriptor\Tag\ReturnDescriptor; |
||
30 | use phpDocumentor\Descriptor\Tag\VersionDescriptor; |
||
31 | use phpDocumentor\Descriptor\TraitDescriptor; |
||
32 | use phpDocumentor\Reflection\Php\File; |
||
33 | use Webmozart\Assert\Assert; |
||
34 | |||
35 | class ApiContext extends BaseContext implements Context |
||
36 | { |
||
37 | /** |
||
38 | * @Then /^the AST has a class named "([^"]*)" in file "([^"]*)"$/ |
||
39 | * @throws \Exception |
||
40 | */ |
||
41 | public function theASTHasAclassNamedInFile($class, $file) |
||
42 | { |
||
43 | $ast = $this->getAst(); |
||
44 | |||
45 | $file = $this->processFilePath($file); |
||
46 | /** @var FileDescriptor $fileDescriptor */ |
||
47 | $fileDescriptor = $ast->getFiles()->get($file); |
||
48 | |||
49 | /** @var ClassDescriptor $classDescriptor */ |
||
50 | foreach ($fileDescriptor->getClasses() as $classDescriptor) { |
||
51 | if ($classDescriptor->getName() === $class) { |
||
52 | return; |
||
53 | } |
||
54 | } |
||
55 | |||
56 | throw new \Exception(sprintf('Didn\'t find expected class "%s" in "%s"', $class, $file)); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * @Then /^the AST doesn't have a class "([^"]*)"$/ |
||
61 | * @throws \Exception |
||
62 | */ |
||
63 | public function theASTDoesnTHaveAClass($className) |
||
64 | { |
||
65 | $ast = $this->getAst(); |
||
66 | foreach ($ast->getFiles() as $file) { |
||
67 | foreach ($file->getClasses() as $classDescriptor) { |
||
68 | if ($classDescriptor->getName() === $className) { |
||
69 | throw new \Exception('Found unexpected class'); |
||
70 | } |
||
71 | } |
||
72 | } |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * @Then /^the class named "([^"]*)" is in the default package$/ |
||
77 | * @throws \Exception |
||
78 | */ |
||
79 | public function theASTHasAClassInDefaultPackage($class) |
||
80 | { |
||
81 | $class = $this->findClassByName($class); |
||
82 | |||
83 | Assert::eq('Default', $class->getPackage()->getName()); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @Then /^the AST has a trait named "([^"]*)" in file "([^"]*)"$/ |
||
88 | * @throws \Exception |
||
89 | */ |
||
90 | public function theASTHasATraitNamedInFile($trait, $file) |
||
91 | { |
||
92 | $ast = $this->getAst(); |
||
93 | |||
94 | $file = $this->processFilePath($file); |
||
95 | /** @var FileDescriptor $fileDescriptor */ |
||
96 | $fileDescriptor = $ast->getFiles()->get($file); |
||
97 | |||
98 | /** @var TraitDescriptor $classDescriptor */ |
||
99 | foreach ($fileDescriptor->getTraits() as $classDescriptor) { |
||
100 | if ($classDescriptor->getName() === $trait) { |
||
101 | return; |
||
102 | } |
||
103 | } |
||
104 | |||
105 | throw new \Exception(sprintf('Didn\'t find expected trait "%s" in "%s"', $trait, $file)); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * @Then the class named ":class" has docblock with content: |
||
110 | */ |
||
111 | public function classHasDocblockWithContent($class, PyStringNode $expectedContent) |
||
112 | { |
||
113 | $class = $this->findClassByName($class); |
||
114 | |||
115 | Assert::eq($expectedContent->getRaw(), $class->getDescription()); |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * @Then class ":classFqsen" has :docElement: |
||
120 | * @throws Exception |
||
121 | */ |
||
122 | public function classHasDocblockContent($classFqsen, $docElement, PyStringNode $value) |
||
123 | { |
||
124 | $class = $this->findClassByFqsen($classFqsen); |
||
125 | |||
126 | $method = 'get' . $docElement; |
||
127 | |||
128 | Assert::eq($value->getRaw(), $class->{$method}()); |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * @Then class ":classFqsen" has :elementType :elementName with :docElement: |
||
133 | */ |
||
134 | public function classHasElementWithDocblockContent($classFqsen, $elementType, $elementName, $docElement, PyStringNode $value) |
||
135 | { |
||
136 | $class = $this->findClassByFqsen($classFqsen); |
||
137 | |||
138 | switch ($elementType) { |
||
139 | case 'method': |
||
140 | case 'constant': |
||
141 | $method = $method = 'get' . $elementType . 's'; |
||
142 | break; |
||
143 | case 'property': |
||
144 | $method = 'getProperties'; |
||
145 | break; |
||
146 | default: |
||
147 | $method = 'get' . $elementType; |
||
148 | break; |
||
149 | } |
||
150 | |||
151 | $element = $class-> {$method}()->get($elementName); |
||
152 | $method = 'get' . $docElement; |
||
153 | $actual = $element->{$method}(); |
||
154 | |||
155 | Assert::eq($value->getRaw(), $actual, sprintf('"%s" does not match "%s"', $actual, $value->getRaw())); |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * @Then class ":classFqsen" has version :value |
||
160 | */ |
||
161 | public function classHasVersion($classFqsen, $value) |
||
162 | { |
||
163 | $class = $this->findClassByFqsen($classFqsen); |
||
164 | |||
165 | /** @var VersionDescriptor $tag */ |
||
166 | foreach ($class->getVersion() as $tag) { |
||
167 | if ($tag->getVersion() === $value) { |
||
168 | return; |
||
169 | } |
||
170 | } |
||
171 | |||
172 | Assert::false(true, sprintf('Didn\'t find expected version "%s"', $value)); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * @Then class ":classFqsen" without tag :tagName |
||
177 | */ |
||
178 | public function classWithoutTag($classFqsen, $tagName) |
||
179 | { |
||
180 | $this->classHasTag($classFqsen, $tagName, 0); |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * @param string $classFqsen |
||
185 | * @param string $tagName |
||
186 | * @param int $expectedNumber |
||
187 | * @Then class ":classFqsen" has exactly :expectedNumber tag :tagName |
||
188 | */ |
||
189 | public function classHasTag($classFqsen, $tagName, $expectedNumber) |
||
190 | { |
||
191 | $class = $this->findClassByFqsen($classFqsen); |
||
192 | static::AssertTagCount($class, $tagName, $expectedNumber); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * @param string $classFqsen |
||
197 | * @param string $tagName |
||
198 | * @param string $method |
||
199 | * @Then class ":classFqsen" has a method named :method without tag :tagName |
||
200 | */ |
||
201 | public function classHasMethodWithoutTag($classFqsen, $tagName, $method) |
||
202 | { |
||
203 | $this->classHasMethodWithExpectedCountTag($classFqsen, $tagName, $method, 0); |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @param string $classFqsen |
||
208 | * @param string $tagName |
||
209 | * @param string $methodName |
||
210 | * @Then class ":classFqsen" has a method named :method with exactly :expected tag :tagName |
||
211 | */ |
||
212 | public function classHasMethodWithExpectedCountTag($classFqsen, $tagName, $methodName, $expectedCount) |
||
213 | { |
||
214 | $class = $this->findClassByFqsen($classFqsen); |
||
215 | $method = $class->getMethods()->get($methodName); |
||
216 | |||
217 | static::AssertTagCount($method, $tagName, $expectedCount); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * @param string $classFqsen |
||
222 | * @param string $methodName |
||
223 | * @Then class ":classFqsen" has a method :method with argument ":argument is variadic |
||
224 | */ |
||
225 | public function classHasMethodWithArgumentVariadic($classFqsen, $methodName, $argument) |
||
226 | { |
||
227 | $class = $this->findClassByFqsen($classFqsen); |
||
228 | /** @var MethodDescriptor $method */ |
||
229 | $method = $class->getMethods()->get($methodName); |
||
230 | Assert::keyExists($method->getArguments()->getAll(), $argument); |
||
231 | /** @var ArgumentDescriptor $argumentD */ |
||
232 | $argumentD = $method->getArguments()[$argument]; |
||
0 ignored issues
–
show
|
|||
233 | |||
234 | //TODO: enable this check when we support variadic arguments. |
||
235 | //Assert::true($argumentD->isVariadic(), 'Expected argument to be variadic'); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
72% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them.
Loading history...
|
|||
236 | } |
||
237 | |||
238 | /** |
||
239 | * @param string $classFqsen |
||
240 | * @param string $methodName |
||
241 | * @Then class ":classFqsen" has a method :method |
||
242 | */ |
||
243 | public function classHasMethod($classFqsen, $methodName) |
||
244 | { |
||
245 | $class = $this->findClassByFqsen($classFqsen); |
||
246 | /** @var MethodDescriptor $method */ |
||
247 | $method = $class->getMethods()->get($methodName, null); |
||
248 | $methodNames = implode(', ', array_keys($class->getMethods()->getAll())); |
||
249 | |||
250 | Assert::isInstanceOf( |
||
251 | $method, |
||
252 | MethodDescriptor::class, |
||
253 | "Class $classFqsen does not have a method $methodName, it does have the methods: $methodNames" |
||
254 | ); |
||
255 | Assert::eq($methodName, $method->getName()); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * @param string $classFqsen |
||
260 | * @param string $propertyName |
||
261 | * @Then class ":classFqsen" has a property :property |
||
262 | */ |
||
263 | public function classHasProperty($classFqsen, $propertyName) |
||
264 | { |
||
265 | $class = $this->findClassByFqsen($classFqsen); |
||
266 | /** @var PropertyDescriptor $property */ |
||
267 | $property = $class->getProperties()->get($propertyName, null); |
||
268 | Assert::isInstanceOf($property, PropertyDescriptor::class); |
||
269 | Assert::eq($propertyName, $property->getName()); |
||
270 | } |
||
271 | |||
272 | /** |
||
273 | * @param string $classFqsen |
||
274 | * @param string $methodName |
||
275 | * @param string $argument |
||
276 | * @param string $type |
||
277 | * @Then class ":classFqsen" has a method :method with argument :argument of type ":type" |
||
278 | */ |
||
279 | public function classHasMethodWithArgumentOfType($classFqsen, $methodName, $argument, $type) |
||
280 | { |
||
281 | $class = $this->findClassByFqsen($classFqsen); |
||
282 | /** @var MethodDescriptor $method */ |
||
283 | $method = $class->getMethods()->get($methodName); |
||
284 | Assert::keyExists($method->getArguments()->getAll(), $argument); |
||
285 | /** @var ArgumentDescriptor $argumentDescriptor */ |
||
286 | $argumentDescriptor = $method->getArguments()[$argument]; |
||
287 | |||
288 | Assert::eq($type, (string) $argumentDescriptor->getType()); |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * @param string $classFqsen |
||
293 | * @param string $methodName |
||
294 | * @param string $param |
||
295 | * @param string $type |
||
296 | * @Then class ":classFqsen" has a method :method with param :param of type ":type" |
||
297 | */ |
||
298 | public function classHasMethodWithParamOfType($classFqsen, $methodName, $param, $type) |
||
299 | { |
||
300 | $class = $this->findClassByFqsen($classFqsen); |
||
301 | /** @var MethodDescriptor $method */ |
||
302 | $method = $class->getMethods()->get($methodName); |
||
303 | /** @var ParamDescriptor $paramDescriptor */ |
||
304 | foreach ($method->getParam() as $paramDescriptor) { |
||
305 | if ($paramDescriptor->getName() === $param) { |
||
306 | Assert::eq($type, (string) $paramDescriptor->getType()); |
||
307 | } |
||
308 | } |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * @param string $classFqsen |
||
313 | * @param string $constantName |
||
314 | * @Then class ":classFqsen" has a constant :constantName |
||
315 | */ |
||
316 | public function classHasConstant($classFqsen, $constantName) |
||
317 | { |
||
318 | /** @var ClassDescriptor $class */ |
||
319 | $class = $this->findClassByFqsen($classFqsen); |
||
320 | $constant = $class->getConstants()->get($constantName); |
||
321 | Assert::isInstanceOf($constant, ConstantDescriptor::class); |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * @param string $className |
||
326 | * @return ClassDescriptor |
||
327 | * @throws \Exception |
||
328 | */ |
||
329 | private function findClassByName($className) |
||
330 | { |
||
331 | $ast = $this->getAst(); |
||
332 | foreach ($ast->getFiles() as $file) { |
||
333 | foreach ($file->getClasses() as $classDescriptor) { |
||
334 | if ($classDescriptor->getName() === $className) { |
||
335 | return $classDescriptor; |
||
336 | } |
||
337 | } |
||
338 | } |
||
339 | |||
340 | throw new \Exception(sprintf('Didn\'t find expected class "%s"', $className)); |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * @param string $tagName |
||
345 | * @param int $expectedNumber |
||
346 | * @param DescriptorAbstract $element |
||
347 | */ |
||
348 | private static function AssertTagCount($element, $tagName, $expectedNumber) |
||
349 | { |
||
350 | /** @var Collection $tagCollection */ |
||
351 | $tagCollection = $element->getTags()->get($tagName, new Collection()); |
||
352 | |||
353 | Assert::eq((int) $expectedNumber, $tagCollection->count()); |
||
354 | if ($expectedNumber > 0) { |
||
355 | Assert::eq($tagName, $tagCollection[0]->getName()); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | /** |
||
360 | * @Then /^the ast has a file named "([^"]*)" with a summary:$/ |
||
361 | * @throws \Exception |
||
362 | */ |
||
363 | public function theAstHasAFileNamedWithASummary(string $fileName, PyStringNode $string) |
||
364 | { |
||
365 | $ast = $this->getAst(); |
||
366 | /** @var FileDescriptor $file */ |
||
367 | $file = $ast->getFiles()->get($fileName); |
||
368 | |||
369 | Assert::eq($string->getRaw(), $file->getSummary()); |
||
370 | } |
||
371 | |||
372 | /** |
||
373 | * @param string $classFqsen |
||
374 | * @param string $methodName |
||
375 | * @throws Exception |
||
376 | * @Then class ":classFqsen" has a method :method with returntype :returnType |
||
377 | * @Then class ":classFqsen" has a method :method with returntype :returnType without description |
||
378 | */ |
||
379 | public function classHasMethodWithReturnType($classFqsen, $methodName, $returnType) |
||
380 | { |
||
381 | $response = $this->findMethodResponse($classFqsen, $methodName); |
||
382 | |||
383 | Assert::eq((string) $response->getType(), $returnType); |
||
384 | Assert::eq((string) $response->getDescription(), ''); |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * @param string $classFqsen |
||
389 | * @param string $methodName |
||
390 | * @throws Exception |
||
391 | * @Then class ":classFqsen" has a magic method :method with returntype :returnType |
||
392 | * @Then class ":classFqsen" has a magic method :method with returntype :returnType without description |
||
393 | */ |
||
394 | public function classHasMagicMethodWithReturnType($classFqsen, $methodName, $returnType) |
||
395 | { |
||
396 | $response = $this->findMagicMethodResponse($classFqsen, $methodName); |
||
397 | |||
398 | Assert::eq((string) $response->getType(), $returnType); |
||
399 | Assert::eq((string) $response->getDescription(), ''); |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * @param string $classFqsen |
||
404 | * @param string $methodName |
||
405 | * @throws Exception |
||
406 | * @Then class ":classFqsen" has a method :method with returntype :returnType with description: |
||
407 | */ |
||
408 | public function classHasMethodWithReturnTypeAndDescription($classFqsen, $methodName, $returnType, PyStringNode $description) |
||
409 | { |
||
410 | $response = $this->findMethodResponse($classFqsen, $methodName); |
||
411 | |||
412 | Assert::eq($returnType, (string) $response->getType()); |
||
413 | Assert::eq($description, (string) $response->getDescription()); |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * @Then class ":classFqsen" has a method ":method" without returntype |
||
418 | * @throws \Exception |
||
419 | */ |
||
420 | public function classReturnTaggetReturnWithoutAnyWithoutReturntype($classFqsen, $methodName) |
||
421 | { |
||
422 | $response = $this->findMethodResponse($classFqsen, $methodName); |
||
423 | Assert::eq('mixed', (string) $response->getType()); |
||
424 | Assert::eq('', $response->getDescription()); |
||
425 | } |
||
426 | |||
427 | /** |
||
428 | * @throws Exception |
||
429 | * @Then has function :fqsen with returntype :returnType |
||
430 | * @Then has function :fqsen with returntype :returnType without description |
||
431 | */ |
||
432 | public function functionWithReturnType($fqsen, $returnType) |
||
433 | { |
||
434 | $response = $this->findFunctionResponse($fqsen); |
||
435 | |||
436 | Assert::eq($returnType, (string) $response->getType()); |
||
437 | Assert::eq('', (string) $response->getDescription()); |
||
438 | } |
||
439 | |||
440 | /** |
||
441 | * @throws Exception |
||
442 | * @Then has function :fqsen with returntype :returnType with description: |
||
443 | */ |
||
444 | public function functionWithReturnTypeAndDescription($fqsen, $returnType, PyStringNode $description) |
||
445 | { |
||
446 | $response = $this->findFunctionResponse($fqsen); |
||
447 | |||
448 | Assert::eq($returnType, (string) $response->getType()); |
||
449 | Assert::eq($description, (string) $response->getDescription()); |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * @Then has function :fqsen without returntype |
||
454 | * @throws \Exception |
||
455 | */ |
||
456 | public function functionWithoutReturntype($fqsen) |
||
457 | { |
||
458 | $response = $this->findFunctionResponse($fqsen); |
||
459 | Assert::eq('mixed', (string) $response->getType()); |
||
460 | Assert::eq('', $response->getDescription()); |
||
461 | } |
||
462 | |||
463 | /** |
||
464 | * @throws Exception |
||
465 | */ |
||
466 | private function findMethodResponse($classFqsen, $methodName): ReturnDescriptor |
||
467 | { |
||
468 | $class = $this->findClassByFqsen($classFqsen); |
||
469 | /** @var MethodDescriptor $method */ |
||
470 | $method = $class->getMethods()->get($methodName, null); |
||
471 | Assert::isInstanceOf($method, MethodDescriptor::class); |
||
472 | Assert::eq($methodName, $method->getName()); |
||
473 | |||
474 | return $method->getResponse(); |
||
475 | } |
||
476 | |||
477 | /** |
||
478 | * @throws Exception |
||
479 | */ |
||
480 | private function findMagicMethodResponse($classFqsen, $methodName): ReturnDescriptor |
||
481 | { |
||
482 | $class = $this->findClassByFqsen($classFqsen); |
||
483 | $match = null; |
||
484 | |||
485 | /** @var MethodDescriptor $method */ |
||
486 | foreach ($class->getMagicMethods() as $method) { |
||
487 | if ($method->getName() === $methodName) { |
||
488 | $match = $method; |
||
489 | } |
||
490 | } |
||
491 | |||
492 | Assert::isInstanceOf($match, MethodDescriptor::class); |
||
493 | Assert::eq($methodName, $match->getName()); |
||
494 | |||
495 | return $match->getResponse(); |
||
496 | } |
||
497 | |||
498 | /** |
||
499 | * @throws Exception |
||
500 | */ |
||
501 | private function findFunctionResponse(string $fqsen): ReturnDescriptor |
||
502 | { |
||
503 | $function = $this->findFunctionByFqsen($fqsen); |
||
504 | return $function->getResponse(); |
||
505 | } |
||
506 | |||
507 | /** |
||
508 | * @Then class ":classFqsen" has a magic method :method with argument ":argument" of type :type |
||
509 | */ |
||
510 | public function classHasMagicMethodWithArgument($classFqsen, $methodName, $argument, $type) |
||
511 | { |
||
512 | $class = $this->findClassByFqsen($classFqsen); |
||
513 | $match = null; |
||
514 | |||
515 | /** @var MethodDescriptor $method */ |
||
516 | foreach ($class->getMagicMethods() as $method) { |
||
517 | if ($method->getName() === $methodName) { |
||
518 | $match = $method; |
||
519 | } |
||
520 | } |
||
521 | |||
522 | Assert::isInstanceOf($match, MethodDescriptor::class); |
||
523 | Assert::notNull($match->getArguments()->get($argument)); |
||
524 | } |
||
525 | |||
526 | /** |
||
527 | * @Then /^(\d+) files should be parsed$/ |
||
528 | */ |
||
529 | public function filesShouldBeParsed($count) |
||
530 | { |
||
531 | Assert::same((int) $count, $this->getAst()->getFiles()->count()); |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * @Then /^the ast has a function named "([^"]*)"$/ |
||
536 | */ |
||
537 | public function theAstHasAFunctionNamed($functionName) |
||
538 | { |
||
539 | Assert::isInstanceOf( |
||
540 | $this->getAst()->getIndexes()->get('functions')->get($functionName . '()'), |
||
541 | FunctionDescriptor::class |
||
542 | ); |
||
543 | } |
||
544 | |||
545 | /** |
||
546 | * @Then argument :argument of function ":functionName" has no defined type and description is: |
||
547 | */ |
||
548 | public function argumentOfFunctionHasNoTypeAndHasDescripion($argument, $functionName, PyStringNode $description) |
||
549 | { |
||
550 | /** @var FunctionDescriptor $functionDescriptor */ |
||
551 | $functionDescriptor = $this->getAst()->getIndexes()->get('functions')->get($functionName . '()'); |
||
552 | Assert::isInstanceOf( |
||
553 | $functionDescriptor, |
||
554 | FunctionDescriptor::class |
||
555 | ); |
||
556 | |||
557 | /** @var ArgumentDescriptor $argumentDescriptor */ |
||
558 | $argumentDescriptor = $functionDescriptor->getArguments()->get($argument); |
||
559 | |||
560 | Assert::isInstanceOf($argumentDescriptor, ArgumentDescriptor::class); |
||
561 | |||
562 | Assert::same($description->getRaw(), (string) $argumentDescriptor->getDescription()); |
||
563 | } |
||
564 | |||
565 | /** |
||
566 | * @Given the namespace ':namespace' has a function named ':functionName' |
||
567 | */ |
||
568 | public function theNamespaceFoo(string $namespace, string $functionName) |
||
569 | { |
||
570 | /** @var NamespaceDescriptor $namespace */ |
||
571 | $namespace = $this->getAst()->getIndexes()->get('namespaces')->get($namespace); |
||
572 | Assert::isInstanceOf($namespace, NamespaceDescriptor::class); |
||
573 | $function = $this->findFunctionInNamespace($namespace, $functionName); |
||
574 | Assert::isInstanceOf($function, FunctionDescriptor::class); |
||
575 | } |
||
576 | |||
577 | private function findFunctionInNamespace(NamespaceDescriptor $namespace, string $functionName) |
||
578 | { |
||
579 | foreach ($namespace->getFunctions()->getAll() as $key => $function) { |
||
580 | if ($function->getName() === $functionName) { |
||
581 | return $function; |
||
582 | } |
||
583 | } |
||
584 | |||
585 | return null; |
||
586 | } |
||
587 | |||
588 | /** |
||
589 | * @Then /^file "([^"]*)" must contain a marker$/ |
||
590 | */ |
||
591 | public function fileMustContainAMarker($filename) |
||
592 | { |
||
593 | $ast = $this->getAst(); |
||
594 | |||
595 | /** @var FileDescriptor $file */ |
||
596 | $file = $ast->getFiles()->get($filename); |
||
597 | |||
598 | Assert::count($file->getMarkers(), 1); |
||
599 | } |
||
600 | |||
601 | /** |
||
602 | * @Then class ":className" must have magic property ":propertyName" of type :type |
||
603 | */ |
||
604 | public function classMustHaveMagicPropertyOfType($className, $propertyName, $type) |
||
605 | { |
||
606 | $classDescriptor = $this->findClassByFqsen($className); |
||
607 | /** @var PropertyDescriptor $propertyDescriptor */ |
||
608 | $propertyDescriptor = null; |
||
609 | foreach ($classDescriptor->getMagicProperties() as $property) { |
||
610 | if ($property->getName() === $propertyName) { |
||
611 | $propertyDescriptor = $property; |
||
612 | break; |
||
613 | } |
||
614 | } |
||
615 | |||
616 | Assert::isInstanceOf($propertyDescriptor, PropertyDescriptor::class); |
||
617 | Assert::eq($type, (string) $propertyDescriptor->getType()); |
||
618 | } |
||
619 | } |
||
620 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.