Completed
Pull Request — master (#347)
by Oskar
03:09
created

RoleOfMethodDetector   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 108
rs 10
wmc 9
lcom 1
cbo 2

1 Method

Rating   Name   Duplication   Size   Complexity  
D detects() 0 39 9
1
<?php
2
namespace Hal\Metric\Helper;
3
4
use PhpParser\Node\Expr\Cast;
5
use PhpParser\Node\Expr\Variable;
6
use PhpParser\Node\Identifier;
7
use PhpParser\Node\Stmt\ClassMethod;
8
use PhpParser\Node\Stmt\Return_;
9
10
/**
11
 * Class RoleOfMethodDetector
12
 * @package Hal\Metric\Helper
13
 */
14
class RoleOfMethodDetector
15
{
16
    /**
17
     * @var array
18
     */
19
    private $fingerprints = [
20
        'getter' => [
21
            [
22
                'PhpParser\\Node\\Stmt\\ClassMethod',
23
                'PhpParser\\Node\\Stmt\\Return_',
24
                'PhpParser\\Node\\Expr\\PropertyFetch',
25
                'PhpParser\\Node\\Expr\\Variable',
26
            ],
27
            [
28
                'PhpParser\\Node\\Stmt\\ClassMethod',
29
                'PhpParser\\Node\\Stmt\\Return_',
30
                'PhpParser\\Node\\Expr\\PropertyFetch',
31
                'PhpParser\\Node\\Expr\\Variable',
32
                'PhpParser\\Node\\Name',
33
            ],
34
        ],
35
        'setter' => [
36
            [
37
                'PhpParser\\Node\\Stmt\\ClassMethod',
38
                'PhpParser\\Node\\Expr\\Assign',
39
                'PhpParser\\Node\\Expr\\Variable',
40
                'PhpParser\\Node\\Expr\\PropertyFetch',
41
                'PhpParser\\Node\\Expr\\Variable',
42
                'PhpParser\\Node\\Param',
43
            ],
44
            [
45
                'PhpParser\\Node\\Stmt\\ClassMethod',
46
                'PhpParser\\Node\\Expr\\Assign',
47
                'PhpParser\\Node\\Expr\\Variable',
48
                'PhpParser\\Node\\Expr\\PropertyFetch',
49
                'PhpParser\\Node\\Expr\\Variable',
50
                'PhpParser\\Node\\Param',
51
                'PhpParser\\Node\\Name',
52
            ],
53
            // nicik/php-parser:^4
54
            [
55
                'PhpParser\\Node\\Stmt\\ClassMethod',
56
                'PhpParser\\Node\\Stmt\\Expression',
57
                'PhpParser\\Node\\Expr\\Assign',
58
                'PhpParser\\Node\\Expr\\Variable',
59
                'PhpParser\\Node\\Expr\\PropertyFetch',
60
                'PhpParser\\Node\\Expr\\Variable',
61
                'PhpParser\\Node\\Param',
62
                'PhpParser\\Node\\Expr\\Variable',
63
            ],
64
            [
65
                'PhpParser\\Node\\Stmt\\ClassMethod',
66
                'PhpParser\\Node\\Stmt\\Expression',
67
                'PhpParser\\Node\\Expr\\Assign',
68
                'PhpParser\\Node\\Expr\\Variable',
69
                'PhpParser\\Node\\Expr\\PropertyFetch',
70
                'PhpParser\\Node\\Expr\\Variable',
71
                'PhpParser\\Node\\Param',
72
                'PhpParser\\Node\\Expr\\Variable',
73
                'PhpParser\\Node\\Name',
74
            ],
75
        ]
76
    ];
77
78
    /**
79
     * @param $node
80
     * @return string|null
81
     */
82
    public function detects($node)
83
    {
84
        if (! $node instanceof ClassMethod) {
85
            return null;
86
        }
87
88
        // build a fingerprint of the given method
89
        $fingerprintOfMethod = [];
90
        iterate_over_node($node, function ($node) use (&$fingerprintOfMethod) {
91
92
            // avoid identifier (php-parser:^4)
93
            if ($node instanceof Identifier) {
94
                return;
95
            }
96
97
            // avoid cast
98
            if ($node instanceof Cast) {
99
                return;
100
            }
101
102
            // avoid fluent interface
103
            if ($node instanceof Return_ && $node->expr instanceof Variable && $node->expr->name === 'this') {
104
                unset($fingerprintOfMethod[sizeof($fingerprintOfMethod) - 1]);
105
                return;
106
            }
107
108
            $fingerprintOfMethod[] = get_class($node);
109
        });
110
        $fingerprintOfMethod = array_reverse($fingerprintOfMethod);
111
112
        // compare with database of fingerprints
113
        foreach ($this->fingerprints as $type => $fingerprints) {
114
            if (in_array($fingerprintOfMethod, $fingerprints, true)) {
115
                return $type;
116
            }
117
        }
118
119
        return null;
120
    }
121
}
122