Completed
Push — master ( b6d688...cba8ad )
by Alexander
11s
created

PointcutGrammar::__construct()   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 277
Code Lines 200

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 224
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 277
ccs 224
cts 225
cp 0.9956
rs 8.2857
c 0
b 0
f 0
cc 2
eloc 200
nc 1
nop 2
crap 2

How to fix   Long Method   

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
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2013, Lisachenko Alexander <[email protected]>
7
 *
8
 * This source file is subject to the license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Go\Aop\Pointcut;
13
14
use Closure;
15
use Dissect\Lexer\Token;
16
use Dissect\Parser\Grammar;
17
use Doctrine\Common\Annotations\Reader;
18
use Go\Aop\PointFilter;
19
use Go\Aop\Support\InheritanceClassFilter;
20
use Go\Aop\Support\ModifierMatcherFilter;
21
use Go\Aop\Support\SimpleNamespaceFilter;
22
use Go\Aop\Support\TruePointFilter;
23
use Go\Core\AspectContainer;
24
25
/**
26
 * Pointcut grammar defines general structure of pointcuts and rules of parsing
27
 */
28
class PointcutGrammar extends Grammar
29
{
30
    /**
31
     * Constructs a pointcut grammar with AST
32
     *
33
     * @param AspectContainer $container Instance of the container
34
     * @param Reader $annotationReader
35
     */
36 29
    public function __construct(AspectContainer $container, Reader $annotationReader)
37
    {
38 29
        $this('empty')
39 29
            ->is(/* empty */);
40
41 29
        $stringConverter = $this->getNodeToStringConverter();
42
43 29
        $this('pointcutExpression')
44 29
            ->is('pointcutExpression', '||', 'conjugatedExpression')
45 29
            ->call(function($first, $_0, $second) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
46 2
                return new OrPointcut($first, $second);
47 29
            })
48 29
            ->is('conjugatedExpression');
49
50 29
        $this('conjugatedExpression')
51 29
            ->is('conjugatedExpression', '&&', 'negatedExpression')
52 29
            ->call(function($first, $_0, $second) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
53 3
                return new AndPointcut($first, $second);
54 29
            })
55 29
            ->is('negatedExpression');
56
57 29
        $this('negatedExpression')
58 29
            ->is('!', 'brakedExpression')
59 29
            ->call(function($_0, $item) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
60 2
                return new NotPointcut($item);
61 29
            })
62 29
            ->is('brakedExpression');
63
64 29
        $this('brakedExpression')
65 29
            ->is('(', 'pointcutExpression', ')')
66 29
            ->call(function($_0, $e, $_1) {
0 ignored issues
show
Unused Code introduced by
The parameter $_1 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...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
67 1
                return $e;
68 29
            })
69 29
            ->is('singlePointcut');
70
71 29
        $this('singlePointcut')
72 29
            ->is('accessPointcut')
73 29
            ->is('annotatedAccessPointcut')
74 29
            ->is('executionPointcut')
75 29
            ->is('annotatedExecutionPointcut')
76 29
            ->is('withinPointcut')
77 29
            ->is('annotatedWithinPointcut')
78 29
            ->is('initializationPointcut')
79 29
            ->is('staticInitializationPointcut')
80 29
            ->is('cflowbelowPointcut')
81 29
            ->is('dynamicExecutionPointcut')
82 29
            ->is('matchInheritedPointcut')
83 29
            ->is('pointcutReference');
84
85 29
        $this('accessPointcut')
86 29
            ->is('access', '(', 'propertyAccessReference', ')')
87 29
            ->call(function($_0, $_1, $propertyReference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
88 2
                return $propertyReference;
89 29
            });
90
91 29
        $this('executionPointcut')
92 29
            ->is('execution', '(', 'methodExecutionReference', ')')
93 29
            ->call(function($_0, $_1, $methodReference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
94 6
                return $methodReference;
95 29
            })
96 29
            ->is('execution', '(', 'functionExecutionReference', ')')
97 29
            ->call(function($_0, $_1, $functionReference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
98 3
                return $functionReference;
99 29
            });
100
101 29
        $this('withinPointcut')
102 29
            ->is('within', '(', 'classFilter', ')')
103 29
            ->call(function($_0, $_1, $classFilter) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
104 8
                $pointcut = new TruePointcut(PointFilter::KIND_ALL);
105 8
                $pointcut->setClassFilter($classFilter);
106
107 8
                return $pointcut;
108 29
            });
109
110 29
        $this('annotatedAccessPointcut')
111 29
            ->is('annotation', 'access', '(', 'namespaceName', ')')
112 29
            ->call(function($_0, $_1, $_2, $annotationClassName) use ($annotationReader) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
113 1
                $kindProperty = PointFilter::KIND_PROPERTY;
114 1
                return new AnnotationPointcut($kindProperty, $annotationReader, $annotationClassName);
115 29
            });
116
117 29
        $this('annotatedExecutionPointcut')
118 29
            ->is('annotation', 'execution', '(', 'namespaceName', ')')
119 29
            ->call(function($_0, $_1, $_2, $annotationClassName) use ($annotationReader) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
120 1
                $kindMethod = PointFilter::KIND_METHOD;
121 1
                return new AnnotationPointcut($kindMethod, $annotationReader, $annotationClassName);
122 29
            });
123
124 29
        $this('annotatedWithinPointcut')
125 29
            ->is('annotation', 'within', '(', 'namespaceName', ')')
126 29
            ->call(function($_0, $_1, $_2, $annotationClassName) use ($annotationReader) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
127 1
                $pointcut    = new TruePointcut(PointFilter::KIND_ALL);
128 1
                $kindClass   = PointFilter::KIND_CLASS;
129 1
                $classFilter = new AnnotationPointcut($kindClass, $annotationReader, $annotationClassName);
130 1
                $pointcut->setClassFilter($classFilter);
131
132 1
                return $pointcut;
133 29
            });
134
135 29
        $this('initializationPointcut')
136 29
            ->is('initialization', '(', 'classFilter', ')')
137 29
            ->call(function($_0, $_1, $classFilter) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
138 1
                $pointcut = new TruePointcut(PointFilter::KIND_INIT + PointFilter::KIND_CLASS);
139 1
                $pointcut->setClassFilter($classFilter);
140
141 1
                return $pointcut;
142 29
            });
143
144 29
        $this('staticInitializationPointcut')
145 29
            ->is('staticinitialization', '(', 'classFilter', ')')
146 29
            ->call(function($_0, $_1, $classFilter) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
147 1
                $pointcut = new TruePointcut(PointFilter::KIND_STATIC_INIT + PointFilter::KIND_CLASS);
148 1
                $pointcut->setClassFilter($classFilter);
149
150 1
                return $pointcut;
151 29
            });
152
153 29
        $this('cflowbelowPointcut')
154 29
            ->is('cflowbelow', '(', 'executionPointcut', ')')
155 29
            ->call(function($_0, $_1, $pointcut) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
156 1
                return new CFlowBelowMethodPointcut($pointcut);
157 29
            });
158
159 29
        $this('matchInheritedPointcut')
160 29
            ->is('matchInherited', '(', ')')
161 29
            ->call(function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
162 1
                return new MatchInheritedPointcut();
163 29
            });
164
165 29
        $this('dynamicExecutionPointcut')
166
            // ideally, this should be 'dynamic', 'methodExecutionReference'
167 29
            ->is('dynamic', '(', 'memberReference', '(', 'argumentList', ')', ')')
168 29
            ->call(function($_0, $_1, ClassMemberReference $reference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
169 2
                $memberFilter = $reference->getVisibilityFilter();
170 2
                $memberFilter = $memberFilter->merge($reference->getAccessTypeFilter());
171 2
                $pointcut     = new MagicMethodPointcut(
172 2
                    $reference->getMemberNamePattern(),
173 2
                    $memberFilter);
174 2
                $pointcut->setClassFilter($reference->getClassFilter());
175
176 2
                return $pointcut;
177 29
            });
178
179 29
        $this('pointcutReference')
180 29
            ->is('namespaceName', '->', 'namePatternPart')
181 29
            ->call(function($className, $_0, $name) use ($container) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
182
                return new PointcutReference($container, "{$className}->{$name}");
183 29
            });
184
185 29
        $this('propertyAccessReference')
186 29
            ->is('memberReference')
187 29
            ->call(function(ClassMemberReference $reference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
188 2
                $memberFilter = $reference->getVisibilityFilter();
189 2
                $memberFilter = $memberFilter->merge($reference->getAccessTypeFilter());
190 2
                $pointcut     = new SignaturePointcut(
191 2
                    PointFilter::KIND_PROPERTY,
192 2
                    $reference->getMemberNamePattern(),
193 2
                    $memberFilter);
194
195 2
                $pointcut->setClassFilter($reference->getClassFilter());
196
197 2
                return $pointcut;
198 29
            });
199
200 29
        $this('methodExecutionReference')
201 29
            ->is('memberReference', '(', 'argumentList', ')')
202 29
            ->call(function(ClassMemberReference $reference) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
203
204 6
                $memberFilter = $reference->getVisibilityFilter();
205 6
                $memberFilter = $memberFilter->merge($reference->getAccessTypeFilter());
206 6
                $pointcut     = new SignaturePointcut(
207 6
                    PointFilter::KIND_METHOD,
208 6
                    $reference->getMemberNamePattern(),
209 6
                    $memberFilter);
210
211 6
                $pointcut->setClassFilter($reference->getClassFilter());
212
213 6
                return $pointcut;
214 29
            });
215
216 29
        $this('functionExecutionReference')
217 29
            ->is('namespacePattern', 'nsSeparator', 'namePatternPart', '(', 'argumentList', ')')
218 29
            ->call(function($namespacePattern, $_0, $namePattern) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
219 3
                $nsFilter = new SimpleNamespaceFilter($namespacePattern);
220 3
                $pointcut = new FunctionPointcut($namePattern);
221 3
                $pointcut->setNamespaceFilter($nsFilter);
222
223 3
                return $pointcut;
224 29
            });
225
226 29
        $this('memberReference')
227 29
            ->is('memberModifiers', 'classFilter', 'memberAccessType', 'namePatternPart')
228 29
            ->call(function(
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
229
                ModifierMatcherFilter $memberModifiers,
230
                PointFilter $classFilter,
231
                ModifierMatcherFilter $memberAccessType,
232
                $namePattern
233
            ) {
234 10
                $reference = new ClassMemberReference(
235 10
                    $classFilter,
236 10
                    $memberModifiers,
237 10
                    $memberAccessType,
238 10
                    $namePattern);
239
240 10
                return $reference;
241 29
            });
242
243 29
        $this('classFilter')
244 29
            ->is('namespacePattern')
245 29
            ->call(function($pattern) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
246 18
                $truePointFilter = TruePointFilter::getInstance();
247
248 18
                return $pattern === '**'
249 3
                    ? $truePointFilter
250 18
                    : new SignaturePointcut(PointFilter::KIND_CLASS, $pattern, $truePointFilter);
251 29
            })
252 29
            ->is('namespacePattern', '+')
253 29
            ->call(function($parentClassName) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
254 5
                return new InheritanceClassFilter($parentClassName);
255 29
            });
256
257 29
        $this('argumentList')
258 29
            ->is('*');
259
260 29
        $this('memberAccessType')
261 29
            ->is('::')
262 29
            ->call(function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
263 2
                return new ModifierMatcherFilter(\ReflectionMethod::IS_STATIC);
264 29
            })
265 29
            ->is('->')
266 29
            ->call(function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
267 8
                $modifierMatcherFilter = new ModifierMatcherFilter();
268 8
                $modifierMatcherFilter->notMatch(\ReflectionMethod::IS_STATIC);
269
270 8
                return $modifierMatcherFilter;
271 29
            });
272
273 29
        $this('namespacePattern')
274 29
            ->is('**')->call($stringConverter)
275 29
            ->is('namePatternPart')
276 29
            ->is('namespacePattern', 'nsSeparator', 'namePatternPart')->call($stringConverter)
277 29
            ->is('namespacePattern', 'nsSeparator', '**')->call($stringConverter);
278
279 29
        $this('namePatternPart')
280 29
            ->is('*')->call($stringConverter)
281 29
            ->is('namePart')->call($stringConverter)
282 29
            ->is('namePatternPart', '*')->call($stringConverter)
283 29
            ->is('namePatternPart', 'namePart')->call($stringConverter)
284 29
            ->is('namePatternPart', '|', 'namePart')->call($stringConverter);
285
286 29
        $this('namespaceName')
287 29
            ->is('namePart')->call($stringConverter)
288 29
            ->is('namespaceName', 'nsSeparator', 'namePart')->call($stringConverter);
289
290 29
        $this('memberModifiers')
291 29
            ->is('memberModifier', '|', 'memberModifiers')
292 29
            ->call(function($modifier, $_0, ModifierMatcherFilter $matcher) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
293 2
                return $matcher->orMatch($modifier);
294 29
            })
295 29
            ->is('memberModifier', 'memberModifiers')
296 29
            ->call(function($modifier, ModifierMatcherFilter $matcher) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
297 1
                return $matcher->andMatch($modifier);
298 29
            })
299 29
            ->is('memberModifier')
300 29
            ->call(function($modifier) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
301 10
                return new ModifierMatcherFilter($modifier);
302 29
            });
303
304 29
        $converter = $this->getModifierConverter();
305 29
        $this('memberModifier')
306 29
            ->is('public')->call($converter)
307 29
            ->is('protected')->call($converter)
308 29
            ->is('private')->call($converter)
309 29
            ->is('final')->call($converter);
310
311 29
        $this->start('pointcutExpression');
312 29
    }
313
314
    /**
315
     * Returns callable for converting node(s) to the string
316
     */
317
    private function getNodeToStringConverter() : Closure
318
    {
319 29
        return function(...$arguments) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
320 26
            $value = '';
321 26
            foreach ($arguments as $node) {
322 26
                if (is_scalar($node)) {
323 20
                    $value .= $node;
324
                } else {
325 26
                    $value .= $node->getValue();
326
                }
327
            }
328
329 26
            return $value;
330 29
        };
331
    }
332
333
    /**
334
     * Returns callable for converting node value for modifiers to the constant value
335
     */
336
    private function getModifierConverter() : Closure
337
    {
338 29
        return function(Token $token) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
339 10
            $name = strtoupper($token->getValue());
340
341 10
            return constant("ReflectionMethod::IS_{$name}");
342 29
        };
343
    }
344
}
345