Completed
Pull Request — master (#67)
by
unknown
02:21
created

MethodParserVisitor::parseParams()   F

Complexity

Conditions 12
Paths 385

Size

Total Lines 55

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 55
ccs 35
cts 35
cp 1
rs 3.8208
c 0
b 0
f 0
cc 12
nc 385
nop 2
crap 12

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace gossi\codegen\parser\visitor;
5
6
use gossi\codegen\model\PhpMethod;
7
use gossi\codegen\model\PhpParameter;
8
use gossi\codegen\parser\PrettyPrinter;
9
use gossi\codegen\parser\visitor\parts\MemberParserPart;
10
use gossi\codegen\parser\visitor\parts\ValueParserPart;
11
use gossi\codegen\utils\TypeUtils;
12
use gossi\docblock\tags\ParamTag;
13
use PhpParser\Node\Identifier;
14
use PhpParser\Node\Name;
15
use PhpParser\Node\NullableType;
16
use PhpParser\Node\Stmt\ClassMethod;
17
18
class MethodParserVisitor extends StructParserVisitor {
19
20
	use MemberParserPart;
21
	use ValueParserPart;
22
23 9
	public function visitMethod(ClassMethod $node) {
24 9
		$m = new PhpMethod($node->name->name);
25 9
		$m->setAbstract($node->isAbstract());
26 9
		$m->setFinal($node->isFinal());
27 9
		$m->setVisibility($this->getVisibility($node));
28 9
		$m->setStatic($node->isStatic());
29 9
		$m->setReferenceReturned($node->returnsByRef());
30
31 9
		$this->parseMemberDocblock($m, $node->getDocComment());
32 9
		$this->parseParams($m, $node);
0 ignored issues
show
Documentation introduced by
$m is of type object<gossi\codegen\mod...egen\model\PhpConstant>, but the function expects a object<gossi\codegen\model\PhpMethod>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
33 9
		$this->parseType($m, $node);
0 ignored issues
show
Documentation introduced by
$m is of type object<gossi\codegen\mod...egen\model\PhpConstant>, but the function expects a object<gossi\codegen\model\PhpMethod>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
34 9
		$this->parseBody($m, $node);
35
36 9
		$this->struct->addMethod($m);
37 9
	}
38
39 9
	private function parseParams(PhpMethod $m, ClassMethod $node) {
40 9
		$params = $m->getDocblock()->getTags('param');
41 9
		foreach ($node->params as $param) {
42 6
			$name = $param->var ? $param->var->name : $param->name;
43
44 6
			$p = new PhpParameter();
45 6
			$p->setName($name);
46 6
			$p->setPassedByReference($param->byRef);
47
48 6
            $type = null;
49 6
            if ($param->type instanceof NullableType) {
50 1
                $param->type = $param->type->type;
51 1
                $p->setNullable(true);
52
            }
53 6
            if ($param->type instanceof Identifier) {
54 2
                $param->type = $param->type->name;
0 ignored issues
show
Documentation Bug introduced by
It seems like $param->type->name of type string is incompatible with the declared type null|object<PhpParser\No...pParser\Node\UnionType> of property $type.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
55
            }
56 6
            if (is_string($param->type)) {
57 2
				$type = $param->type;
58
			}
59 6
			if ($param->type instanceof Name) {
60 3
                $type = implode('\\', $param->type->parts);
61 3
                $qualifiedType = TypeUtils::guessQualifiedName($this->struct, $type);
62 3
                if ($type !== $qualifiedType) {
63 2
                    $type = $qualifiedType;
64
                } else {
65 1
                    $type = '\\'.$type;
66
                }
67
            }
68
69 6
			if ($type) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
70 3
                $p->addType($type);
71
            }
72
73 6
			$this->parseValue($p, $param);
74
75 6
			if ($p->getExpression() === 'null') {
76 3
                $p->setNullable(true);
77
            }
78
79
			$tag = $params->find($p, static function (ParamTag $t, $p) {
80 3
				return $t->getVariable() === '$' . $p->getName();
81 6
			});
82
83 6
			if ($tag !== null) {
84 3
			    $types = TypeUtils::expressionToTypes($tag->getType());
85 3
			    foreach ($types as $type) {
86 3
                    $p->addType(TypeUtils::guessQualifiedName($this->struct, $type));
87
                }
88 3
			    $p->setTypeDescription($tag->getDescription());
89
			}
90
91 6
			$m->addParameter($p);
92
		}
93 9
	}
94
95 9
	private function parseType(PhpMethod &$m, ClassMethod $node) {
0 ignored issues
show
Unused Code introduced by
The parameter $node is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
96 9
		$returns = $m->getDocblock()->getTags('return');
97 9
		if ($returns->size() > 0) {
98 1
			$return = $returns->get(0);
99 1
			$m->addType($return->getType())->setTypeDescription($return->getDescription());
100
		}
101 9
	}
102
103 9
	private function parseBody(PhpMethod &$m, ClassMethod $node) {
104 9
		$stmts = $node->getStmts();
105 9
		if (is_array($stmts) && count($stmts)) {
106 1
			$prettyPrinter = new PrettyPrinter();
107 1
			$m->setBody($prettyPrinter->prettyPrint($stmts));
108
		}
109 9
	}
110
}
111