Completed
Push — master ( bfa80e...3adc88 )
by Alexander
02:11
created

AbstractAspectLoaderExtension::parseTokenStream()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 26
c 0
b 0
f 0
ccs 0
cts 19
cp 0
rs 8.439
cc 5
eloc 21
nc 2
nop 3
crap 30
1
<?php
2
declare(strict_types = 1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2012, 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\Core;
13
14
use Dissect\Lexer\Exception\RecognitionException;
15
use Dissect\Lexer\Lexer;
16
use Dissect\Lexer\TokenStream\TokenStream;
17
use Dissect\Parser\Exception\UnexpectedTokenException;
18
use Dissect\Parser\Parser;
19
use Go\Aop\Aspect;
20
use Go\Aop\Pointcut;
21
use Go\Aop\PointFilter;
22
use Go\Lang\Annotation;
23
use ReflectionMethod;
24
use ReflectionProperty;
25
26
/**
27
 * Abstract aspect loader
28
 */
29
abstract class AbstractAspectLoaderExtension implements AspectLoaderExtension
30
{
31
32
    /**
33
     * Instance of pointcut lexer
34
     *
35
     * @var Lexer
36
     */
37
    protected $pointcutLexer;
38
39
    /**
40
     * Instance of pointcut parser
41
     *
42
     * @var Parser
43
     */
44
    protected $pointcutParser;
45
46
    /**
47
     * Default initialization of dependencies
48
     *
49
     * @param Lexer $pointcutLexer Instance of pointcut lexer
50
     * @param Parser $pointcutParser Instance of pointcut parser
51
     */
52 2
    public function __construct(Lexer $pointcutLexer, Parser $pointcutParser)
53
    {
54 2
        $this->pointcutLexer  = $pointcutLexer;
55 2
        $this->pointcutParser = $pointcutParser;
56 2
    }
57
58
    /**
59
     * General method for parsing pointcuts
60
     *
61
     * @param Aspect $aspect Instance of current aspect
62
     * @param Annotation\BaseAnnotation|Annotation\BaseInterceptor $metaInformation
63
     * @param mixed|\ReflectionMethod|\ReflectionProperty $reflection Reflection of point
64
     *
65
     * @throws \UnexpectedValueException if there was an error during parsing
66
     * @return Pointcut|PointFilter
67
     */
68
    protected function parsePointcut(Aspect $aspect, $reflection, $metaInformation) : PointFilter
69
    {
70
        $stream = $this->makeLexicalAnalyze($aspect, $reflection, $metaInformation);
71
72
        return $this->parseTokenStream($reflection, $metaInformation, $stream);
73
    }
74
75
    /**
76
     * Performs lexical analyze of pointcut
77
     *
78
     * @param Aspect $aspect Instance of aspect
79
     * @param ReflectionMethod|ReflectionProperty $reflection
80
     * @param Annotation\BaseAnnotation $metaInformation
81
     *
82
     * @return TokenStream
83
     * @throws \UnexpectedValueException
84
     */
85
    protected function makeLexicalAnalyze(Aspect $aspect, $reflection, $metaInformation) : TokenStream
86
    {
87
        try {
88
            $resolvedThisPointcut = str_replace('$this', get_class($aspect), $metaInformation->value);
89
            $stream = $this->pointcutLexer->lex($resolvedThisPointcut);
90
        } catch (RecognitionException $e) {
91
            $message = "Can not recognize the lexical structure `%s` before %s, defined in %s:%d";
92
            $message = sprintf(
93
                $message,
94
                $metaInformation->value,
95
                (isset($reflection->class) ? $reflection->class . '->' : '') . $reflection->name,
96
                method_exists($reflection, 'getFileName')
97
                    ? $reflection->getFileName()
0 ignored issues
show
Bug introduced by
The method getFileName does only exist in ReflectionMethod, but not in ReflectionProperty.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
98
                    : $reflection->getDeclaringClass()->getFileName(),
99
                method_exists($reflection, 'getStartLine')
100
                    ? $reflection->getStartLine()
0 ignored issues
show
Bug introduced by
The method getStartLine does only exist in ReflectionMethod, but not in ReflectionProperty.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
101
                    : 0
102
            );
103
            throw new \UnexpectedValueException($message, 0, $e);
104
        }
105
106
        return $stream;
107
    }
108
109
    /**
110
     * Performs parsing of pointcut
111
     *
112
     * @param ReflectionMethod|ReflectionProperty $reflection
113
     * @param Annotation\BaseAnnotation $metaInformation
114
     * @param TokenStream $stream
115
     * @return Pointcut|PointFilter
116
     *
117
     * @throws \UnexpectedValueException
118
     */
119
    protected function parseTokenStream($reflection, $metaInformation, TokenStream $stream) : PointFilter
120
    {
121
        try {
122
            $pointcut = $this->pointcutParser->parse($stream);
123
        } catch (UnexpectedTokenException $e) {
124
            $token   = $e->getToken();
125
            $message = "Unexpected token %s in the `%s` before %s, defined in %s:%d." . PHP_EOL;
126
            $message .= "Expected one of: %s";
127
            $message = sprintf(
128
                $message,
129
                $token->getValue(),
130
                $metaInformation->value,
131
                (isset($reflection->class) ? $reflection->class . '->' : '') . $reflection->name,
132
                method_exists($reflection, 'getFileName')
133
                    ? $reflection->getFileName()
0 ignored issues
show
Bug introduced by
The method getFileName does only exist in ReflectionMethod, but not in ReflectionProperty.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
134
                    : $reflection->getDeclaringClass()->getFileName(),
135
                method_exists($reflection, 'getStartLine')
136
                    ? $reflection->getStartLine()
0 ignored issues
show
Bug introduced by
The method getStartLine does only exist in ReflectionMethod, but not in ReflectionProperty.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
137
                    : 0,
138
                implode(', ', $e->getExpected())
139
            );
140
            throw new \UnexpectedValueException($message, 0, $e);
141
        }
142
143
        return $pointcut;
144
    }
145
}
146