Completed
Pull Request — master (#328)
by Nikola
03:49
created

PointcutGrammar::__construct()   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 277
Code Lines 200

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 196
CRAP Score 2

Importance

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