ClassParser::parseString()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 1
1
<?php
2
3
namespace PHPRealCoverage\Parser;
4
5
use PHPRealCoverage\Parser\Exception\ParserException;
6
use PHPRealCoverage\Parser\Model\CoveredClass;
7
use PHPRealCoverage\Parser\Model\CoveredLine;
8
use PHPRealCoverage\Parser\Model\DynamicClassnameCoveredClass;
9
10
class ClassParser
11
{
12
    const NAMESPACE_PATTERN = '/namespace ([^\s]+);/Usi';
13
    const CLASSNAME_PATTERN = '/(^|\n)[^*\/\n]*class\s+([^\s{]+?)[\s{\n]*/Usi';
14
    const CLASSLINE_PATTERN = '/^[^*\/]*class\s+([^\s{]+?)[\s{\n]*/Usi';
15
    const METHOD_PATTERN = '/\s*(final)?\s*(public?|private?|protected?)\s*(static)?\s*function\s+(\w+?)/Usi';
16
17
    /**
18
     * @param $filename
19
     * @return CoveredClass
20
     */
21
    public function parse($filename)
22
    {
23
        $content = file_get_contents($filename);
24
25
        $class = $this->parseString($content);
26
        $class->setFilename($filename);
27
        return $class;
28
    }
29
30
    /**
31
     * @param string $content
32
     */
33
    public function parseName($content)
34
    {
35
        if (!preg_match(self::CLASSNAME_PATTERN, $content, $matches)) {
36
            throw new ParserException("Failed to parse name of: " . $content);
37
        }
38
        return $matches[2];
39
    }
40
41
    /**
42
     * @param $input
43
     * @return \PHPRealCoverage\Proxy\Line
44
     */
45
    public function parseLine($input)
46
    {
47
        $line = new CoveredLine($input);
48
        $this->detectMethod($input, $line);
49
        $this->detectClass($input, $line);
50
        return $line;
51
    }
52
53
    public function detectMethod($input, CoveredLine $line)
54
    {
55
        $match = preg_match(self::METHOD_PATTERN, $input, $matches);
56
        if (!$match) {
57
            return;
58
        }
59
60
        $line->setMethod(true);
61
        $line->setFinal($matches[1] === "final");
62
        $line->setMethodName($matches[4]);
63
    }
64
65
    private function detectClass($input, CoveredLine $line)
66
    {
67
68
        $line->setClass((bool)preg_match(self::CLASSLINE_PATTERN, $input, $matches));
69
70
        if ($line->isClass()) {
71
            $line->setClassName($matches[1]);
72
        }
73
    }
74
75
    /**
76
     * @param string $content
77
     */
78
    public function parseNamespace($content)
79
    {
80
        if (!preg_match(self::NAMESPACE_PATTERN, $content, $matches)) {
81
            throw new ParserException("Failed to parse Namespace of : \n" . $content);
82
        }
83
        return $matches[1];
84
    }
85
86
    /**
87
     * @param string $content
88
     * @return DynamicClassnameCoveredClass
89
     */
90
    public function parseString($content)
91
    {
92
        $class = new DynamicClassnameCoveredClass();
93
        $class->setName($this->parseName($content));
94
        $class->setNamespace($this->parseNamespace($content));
95
96
        $lines = explode("\n", $content);
97
        $lineNumber = 1;
98
        foreach ($lines as $lineAsString) {
99
            $line = $this->parseLine($lineAsString);
100
            $class->addLine($lineNumber++, $line);
101
        }
102
103
        return $class;
104
    }
105
}
106