Test Failed
Push — master ( d0ad7f...9ed642 )
by Kirill
02:41
created

NativeStateless::isSkipped()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Lexer\Driver;
11
12
use Railt\Io\Readable;
13
use Railt\Lexer\Driver\Common\PCRECompiler;
14
use Railt\Lexer\Stateless;
15
16
/**
17
 * Class NativeStateless
18
 */
19
class NativeStateless extends NativeStateful implements Stateless
20
{
21
    /**
22
     * @var PCRECompiler
23
     */
24
    private $pcre;
25
26
    /**
27
     * NativeStateless constructor.
28
     */
29
    public function __construct()
30 3
    {
31
        $this->pcre = new PCRECompiler();
32 3
        parent::__construct('');
33 3
    }
34
35
    /**
36
     * @param Readable $input
37
     * @return \Traversable
38
     * @throws \InvalidArgumentException
39
     * @throws \RuntimeException
40
     */
41 11
    public function lex(Readable $input): \Traversable
42
    {
43 11
        foreach (parent::exec($this->pcre->compile(), $input->getContents()) as $token) {
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (exec() instead of lex()). Are you sure this is correct? If so, you might want to change this to $this->exec().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
44
            if (! \in_array($token->name(), $this->skipped, true)) {
45 11
                yield $token;
46 4
            }
47
        }
48
    }
49 11
50
    /**
51
     * @param string $name
52
     * @return Stateless
53
     */
54
    public function skip(string $name): Stateless
55
    {
56 2
        $this->skipped[] = $name;
57
58 2
        return $this;
59
    }
60
61
    /**
62
     * @param string $name
63
     * @param string $pcre
64 2
     * @param bool $skip
65
     * @return Stateless
66 2
     */
67
    public function add(string $name, string $pcre, bool $skip = false): Stateless
68
    {
69
        $this->pcre->addToken($name, $pcre);
0 ignored issues
show
Bug introduced by
The method addToken() does not seem to exist on object<Railt\Lexer\Driver\Common\PCRECompiler>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
70
71
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Railt\Lexer\Driver\NativeStateless) is incompatible with the return type declared by the interface Railt\Lexer\Stateless::add of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
72
    }
73 8
74
    /**
75 8
     * @param string $name
76
     * @return bool
77 8
     */
78
    public function has(string $name): bool
79
    {
80
        return \array_key_exists($name, $this->pcre->getTokens());
81
    }
82
83
    /**
84
     * @return iterable
85
     */
86
    public function getDefinedTokens(): iterable
87
    {
88
        return $this->pcre->getTokens();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->pcre->getTokens(); (array) is incompatible with the return type declared by the interface Railt\Lexer\Stateless::getDefinedTokens of type Railt\Lexer\iterable.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
89
    }
90
91
    /**
92
     * @param string $name
93
     * @return bool
94
     */
95
    public function isSkipped(string $name): bool
96
    {
97
        return \in_array($name, $this->skipped, true);
98
    }
99
}
100