Skip to content

Commit 0aa8b4d

Browse files
committed
way to resove types
1 parent 8272032 commit 0aa8b4d

File tree

3 files changed

+224
-0
lines changed

3 files changed

+224
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* (c) Jean-François Lépine <https://twitter.com/Halleck45>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
namespace Hal\Component\OOP\Resolver;
11+
12+
13+
/**
14+
* Type resolver
15+
*
16+
* @author Jean-François Lépine <https://twitter.com/Halleck45>
17+
*/
18+
class TypeResolver
19+
{
20+
21+
const TYPE_VOID = 'void';
22+
const TYPE_STRING = 'string';
23+
const TYPE_INTEGER = 'integer';
24+
const TYPE_FLOAT = 'float';
25+
const TYPE_ARRAY = 'array';
26+
const TYPE_NULL = 'null';
27+
const TYPE_UNKNWON = 'unknown';
28+
const TYPE_FLUENT_INTERFACE = 'fluent';
29+
30+
/**
31+
* Resolves type of given string
32+
*
33+
* @param $string
34+
* @return string
35+
*/
36+
public function resolve($string)
37+
{
38+
$string = $cased = trim($string, ";\t\n\r\0\x0B");
39+
$string = strtolower($string);
40+
41+
if(strlen($string) == 0) {
42+
return self::TYPE_VOID;
43+
}
44+
45+
if(preg_match('!^\d+$!', $string)) {
46+
return self::TYPE_INTEGER;
47+
}
48+
49+
if(preg_match('!^\d+\.\d+$!', $string)) {
50+
return self::TYPE_FLOAT;
51+
}
52+
53+
if('null' == $string) {
54+
return self::TYPE_NULL;
55+
}
56+
57+
if(preg_match('!(^\[|^array\()!', $string)) {
58+
return self::TYPE_ARRAY;
59+
}
60+
61+
if(preg_match('!(^\[|^array\()!', $string)) {
62+
return self::TYPE_ARRAY;
63+
}
64+
65+
if(preg_match('!^new\s*(.*)!', $string, $matches)) {
66+
return trim(preg_replace('!^(new\s+)!', '', $cased));
67+
}
68+
69+
if(preg_match('!^\$this$!', $string, $matches)) {
70+
return self::TYPE_FLUENT_INTERFACE;
71+
}
72+
73+
if(preg_match('!^["\']!', $string, $matches)) {
74+
return self::TYPE_STRING;
75+
}
76+
77+
return self::TYPE_UNKNWON;
78+
}
79+
80+
/**
81+
* Check if type is native (not for PHP, but for this resolver)
82+
*
83+
* @param $type
84+
* @return bool
85+
*/
86+
public function isNative($type) {
87+
return in_array(strtolower(trim($type)), array(
88+
self::TYPE_VOID,
89+
self::TYPE_STRING,
90+
self::TYPE_INTEGER,
91+
self::TYPE_FLOAT,
92+
self::TYPE_ARRAY,
93+
self::TYPE_NULL,
94+
self::TYPE_UNKNWON,
95+
self::TYPE_FLUENT_INTERFACE,
96+
));
97+
}
98+
99+
100+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
namespace Test\Hal\Component\OOP;
3+
4+
use Hal\Component\Token\TokenCollection;
5+
use Hal\Metrics\Design\Component\MaintainabilityIndex\MaintainabilityIndex;
6+
use Hal\Metrics\Design\Component\MaintainabilityIndex\Result;
7+
use Hal\Component\OOP\Extractor\Extractor;
8+
use Hal\Component\OOP\Extractor\MethodExtractor;
9+
use Hal\Component\OOP\Extractor\Searcher;
10+
11+
/**
12+
* @group oop
13+
* @group extractor
14+
* @group php7
15+
*/
16+
class Php7AnonymousClassExtractorTest extends \PHPUnit_Framework_TestCase {
17+
18+
public function testAnonymousClassIsFound() {
19+
20+
$filename = __DIR__.'/../../../resources/oop/php7-1.php';
21+
$extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
22+
$result = $extractor->extract($filename);
23+
24+
$classes = $result->getClasses();
25+
$this->assertEquals(2, sizeof($classes));
26+
27+
$mother = $classes[0];
28+
$anonymous = $classes[1];
29+
$this->assertEquals('\\My\\Mother', $mother->getFullname(), 'mother class is found');
30+
$this->assertEquals('class@anonymous', $anonymous->getName(), 'anonymous class is found');
31+
$this->assertEquals('\\My\\Mother', $anonymous->getParent(), 'mother of anonymous class is found');
32+
$this->assertEquals('\\', $anonymous->getNamespace(), 'anonymous class is in default namespace');
33+
}
34+
35+
public function testInterfacesOfAnonymousClassAreFound() {
36+
37+
$filename = __DIR__.'/../../../resources/oop/php7-2.php';
38+
$extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
39+
$result = $extractor->extract($filename);
40+
41+
$classes = $result->getClasses();
42+
$this->assertEquals(4, sizeof($classes));
43+
44+
$mother = $classes[0];
45+
$interface1 = $classes[1];
46+
$interface2 = $classes[2];
47+
$anonymous = $classes[3];
48+
$this->assertEquals('\\My\\Mother', $mother->getFullname(), 'mother class is found');
49+
$this->assertEquals('\\My\\Contract1', $interface1->getFullname(), 'interface is found');
50+
$this->assertEquals('\\My\\Contract2', $interface2->getFullname(), 'interface is found');
51+
$this->assertEquals('class@anonymous', $anonymous->getName(), 'anonymous class is found');
52+
$this->assertEquals('\\My\\Mother', $anonymous->getParent(), 'mother of anonymous class is found');
53+
$this->assertEquals(array('\\My\\Contract1', '\\My\\Contract2'), $anonymous->getInterfaces(), 'interfaces of anonymous class are found');
54+
}
55+
56+
public function testAnonymousClassDoesNotBreakMainClassExtractor() {
57+
$filename = __DIR__.'/../../../resources/oop/php7-3.php';
58+
$extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
59+
$result = $extractor->extract($filename);
60+
61+
$classes = $result->getClasses();
62+
$this->assertEquals(2, sizeof($classes));
63+
$main = $classes[0];
64+
$anonymous = $classes[1];
65+
$this->assertEquals('\\My\\MainClass', $main->getFullname());
66+
$this->assertEquals('class@anonymous', $anonymous->getName());
67+
68+
$methods = $main->getMethods();
69+
$this->assertEquals(array('foo', 'bar'), array_keys($main->getMethods()), 'Methods of class containing anonymous class are found');
70+
$this->assertEquals(array('sub'), array_keys($anonymous->getMethods()), 'Methods of anonymous class contained in class are found');
71+
}
72+
73+
public function testInnerClassAreAttachedToMainClassExtractor() {
74+
$filename = __DIR__.'/../../../resources/oop/php7-4.php';
75+
$extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
76+
$result = $extractor->extract($filename);
77+
78+
$classes = $result->getClasses();
79+
$this->assertEquals(4, sizeof($classes));
80+
$main = $classes[0];
81+
$this->assertEquals('\\My\\MainClass', $main->getFullname());
82+
83+
$anonymousClasses = $main->getAnonymousClasses();
84+
$this->assertEquals(3, sizeof($anonymousClasses));
85+
}
86+
87+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
namespace Test\Hal\Component\OOP\Resolver;
3+
4+
use Hal\Component\OOP\Resolver\NameResolver;
5+
use Hal\Component\OOP\Resolver\TypeResolver;
6+
use PHPUnit_Framework_TestCase as TestCase;
7+
8+
/**
9+
* @group type
10+
* @group resolver
11+
*/
12+
class TypeResolverTest extends TestCase
13+
{
14+
/**
15+
* @dataProvider providesTypes
16+
*/
17+
public function testTypeResolvesWorks($string, $expected) {
18+
$resolver = new TypeResolver();
19+
$this->assertEquals($expected, $resolver->resolve($string));
20+
}
21+
22+
public function providesTypes()
23+
{
24+
return array(
25+
array('$this;', TypeResolver::TYPE_FLUENT_INTERFACE),
26+
array('1234', TypeResolver::TYPE_INTEGER),
27+
array('123.1', TypeResolver::TYPE_FLOAT),
28+
array('array(4,5)', TypeResolver::TYPE_ARRAY),
29+
array('[4,5]', TypeResolver::TYPE_ARRAY),
30+
array('null', TypeResolver::TYPE_NULL),
31+
array('"abcd"', TypeResolver::TYPE_STRING),
32+
array('', TypeResolver::TYPE_VOID),
33+
array('$this->foo();', TypeResolver::TYPE_UNKNWON),
34+
array('new \StdClass', '\StdClass'),
35+
);
36+
}
37+
}

0 commit comments

Comments
 (0)