Skip to content
This repository was archived by the owner on Sep 19, 2023. It is now read-only.

Commit c9fd613

Browse files
committed
First working version
1 parent 96f8efc commit c9fd613

15 files changed

+413
-0
lines changed

.editorconfig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
charset = utf-8
7+
trim_trailing_whitespace = true
8+
9+
[*.{php,phpt}]
10+
indent_style = tab
11+
indent_size = 4
12+
13+
[*.xml]
14+
indent_style = tab
15+
indent_size = 4
16+
17+
[*.neon]
18+
indent_style = tab
19+
indent_size = 4
20+
21+
[*.{yaml,yml}]
22+
indent_style = space
23+
indent_size = 2
24+
25+
[composer.json]
26+
indent_style = tab
27+
indent_size = 4

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/tests export-ignore

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/composer.lock
2+
/vendor

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: php
2+
php:
3+
- 7.0
4+
- 7.1
5+
- 7.2
6+
before_script:
7+
- composer self-update
8+
- composer install
9+
script:
10+
- vendor/bin/phing

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,27 @@
11
# PHP-Parser extension for PHPStan
22

3+
[![Build Status](https://travis-ci.org/phpstan/phpstan-php-parser.svg)](https://travis-ci.org/phpstan/phpstan-php-parser)
4+
[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan-php-parser/v/stable)](https://packagist.org/packages/phpstan/phpstan-php-parser)
5+
[![License](https://poser.pugx.org/phpstan/phpstan-php-parser/license)](https://packagist.org/packages/phpstan/phpstan-php-parser)
6+
7+
* [PHPStan](https://github.com/phpstan/phpstan)
8+
* [PHP-Parser](https://github.com/nikic/php-parser)
9+
10+
This extension provides the following feature:
11+
12+
* If you register `PhpParser\NodeVisitor\NameResolver` visitor on `PhpParser\NodeTraverser`, new `$namespacedName` property becomes available on nodes that already have a `$name` property. This extension defines that property.
13+
14+
## Usage
15+
16+
To use this extension, require it in [Composer](https://getcomposer.org/):
17+
18+
```
19+
composer require --dev phpstan/phpstan-php-parser
20+
```
21+
22+
And include extension.neon in your project's PHPStan config:
23+
24+
```
25+
includes:
26+
- vendor/phpstan/phpstan-php-parser/extension.neon
27+
```

build.xml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<project name="PHPStan PHP-Parser extensions" default="check">
3+
4+
<target name="check" depends="
5+
composer,
6+
lint,
7+
cs,
8+
tests,
9+
phpstan
10+
"/>
11+
12+
<target name="composer">
13+
<exec
14+
executable="composer"
15+
logoutput="true"
16+
passthru="true"
17+
checkreturn="true"
18+
>
19+
<arg value="install"/>
20+
</exec>
21+
</target>
22+
23+
<target name="lint">
24+
<exec
25+
executable="vendor/bin/parallel-lint"
26+
logoutput="true"
27+
passthru="true"
28+
checkreturn="true"
29+
>
30+
<arg value="--exclude"/>
31+
<arg path="tests/PHPStan/Analyser/data"/>
32+
<arg path="src" />
33+
<arg path="tests" />
34+
</exec>
35+
</target>
36+
37+
<target name="cs">
38+
<exec
39+
executable="vendor/bin/phpcs"
40+
logoutput="true"
41+
passthru="true"
42+
checkreturn="true"
43+
>
44+
<arg value="--extensions=php"/>
45+
<arg value="--encoding=utf-8"/>
46+
<arg value="--tab-width=4"/>
47+
<arg value="--ignore=tests/*/data"/>
48+
<arg value="-sp"/>
49+
<arg path="src"/>
50+
<arg path="tests"/>
51+
</exec>
52+
</target>
53+
54+
<target name="cs-fix">
55+
<exec
56+
executable="vendor/bin/phpcbf"
57+
logoutput="true"
58+
passthru="true"
59+
checkreturn="true"
60+
>
61+
<arg value="--extensions=php"/>
62+
<arg value="--encoding=utf-8"/>
63+
<arg value="--tab-width=4"/>
64+
<arg value="--ignore=tests/*/data"/>
65+
<arg value="-sp"/>
66+
<arg path="src"/>
67+
<arg path="tests"/>
68+
</exec>
69+
</target>
70+
71+
<target name="tests">
72+
<exec
73+
executable="vendor/bin/phpunit"
74+
logoutput="true"
75+
passthru="true"
76+
checkreturn="true"
77+
>
78+
<arg value="-c"/>
79+
<arg value="tests/phpunit.xml"/>
80+
<arg path="tests"/>
81+
</exec>
82+
</target>
83+
84+
<target name="phpstan">
85+
<exec
86+
executable="vendor/bin/phpstan"
87+
logoutput="true"
88+
passthru="true"
89+
checkreturn="true"
90+
>
91+
<arg value="analyse"/>
92+
<arg value="-l"/>
93+
<arg value="7"/>
94+
<arg value="-c"/>
95+
<arg path="phpstan.neon"/>
96+
<arg path="src"/>
97+
<arg path="tests"/>
98+
</exec>
99+
</target>
100+
101+
</project>

composer.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "phpstan/phpstan-php-parser",
3+
"description": "PHP-Parser extensions for PHPStan",
4+
"license": ["MIT"],
5+
"minimum-stability": "dev",
6+
"prefer-stable": true,
7+
"extra": {
8+
"branch-alias": {
9+
"dev-master": "0.9-dev"
10+
}
11+
},
12+
"require": {
13+
"php": "~7.0",
14+
"phpstan/phpstan": "^0.9",
15+
"nikic/php-parser": "^3.1"
16+
},
17+
"require-dev": {
18+
"consistence/coding-standard": "^2.0.0",
19+
"jakub-onderka/php-parallel-lint": "^0.9.2",
20+
"phing/phing": "^2.16.0",
21+
"phpstan/phpstan-phpunit": "^0.9",
22+
"phpunit/phpunit": "^6.4",
23+
"slevomat/coding-standard": "^3.3.0"
24+
},
25+
"autoload": {
26+
"psr-4": {
27+
"PHPStan\\": "src/"
28+
}
29+
},
30+
"autoload-dev": {
31+
"classmap": ["tests/"]
32+
}
33+
}

extension.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
-
3+
class: PHPStan\Reflection\PHPParser\PhpParserNameClassReflectionExtension
4+
tags:
5+
- phpstan.broker.propertiesClassReflectionExtension

phpcs.xml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0"?>
2+
<ruleset name="PHPStan">
3+
<rule ref="vendor/consistence/coding-standard/Consistence/ruleset.xml">
4+
<exclude name="Squiz.Functions.GlobalFunction.Found"/>
5+
</rule>
6+
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml">
7+
<exclude name="SlevomatCodingStandard.Classes.ClassConstantVisibility.MissingConstantVisibility"/>
8+
<exclude name="SlevomatCodingStandard.Files.TypeNameMatchesFileName"/>
9+
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameAfterKeyword"/>
10+
<exclude name="SlevomatCodingStandard.Namespaces.UseOnlyWhitelistedNamespaces"/>
11+
<exclude name="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly"/>
12+
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableParameterTypeHintSpecification"/>
13+
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableReturnTypeHintSpecification"/>
14+
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation.NonFullyQualifiedClassName"/>
15+
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalConstants"/>
16+
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions"/>
17+
<exclude name="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue"/>
18+
</rule>
19+
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses">
20+
<properties>
21+
<property name="caseSensitive" value="false"/>
22+
</properties>
23+
</rule>
24+
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
25+
<properties>
26+
<property name="newlinesCountBetweenOpenTagAndDeclare" value="0"/>
27+
</properties>
28+
</rule>
29+
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration">
30+
<properties>
31+
<property name="usefulAnnotations" type="array" value="
32+
@dataProvider,
33+
@requires
34+
"/>
35+
<property name="enableNullableTypeHints" type="false" />
36+
<property name="enableVoidTypeHint" type="false" />
37+
</properties>
38+
</rule>
39+
</ruleset>

phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
includes:
2+
- vendor/phpstan/phpstan-phpunit/extension.neon
3+
- vendor/phpstan/phpstan-phpunit/rules.neon
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\PHPParser;
4+
5+
use PhpParser\Node\Name;
6+
use PHPStan\Reflection\ClassReflection;
7+
use PHPStan\Type\ObjectType;
8+
use PHPStan\Type\Type;
9+
10+
class NamespacedNameProperty implements \PHPStan\Reflection\PropertyReflection
11+
{
12+
13+
/** @var \PHPStan\Reflection\ClassReflection */
14+
private $declaringClass;
15+
16+
public function __construct(ClassReflection $declaringClass)
17+
{
18+
$this->declaringClass = $declaringClass;
19+
}
20+
21+
public function getDeclaringClass(): ClassReflection
22+
{
23+
return $this->declaringClass;
24+
}
25+
26+
public function isStatic(): bool
27+
{
28+
return false;
29+
}
30+
31+
public function isPrivate(): bool
32+
{
33+
return false;
34+
}
35+
36+
public function isPublic(): bool
37+
{
38+
return true;
39+
}
40+
41+
public function getType(): Type
42+
{
43+
return new ObjectType(Name::class);
44+
}
45+
46+
public function isReadable(): bool
47+
{
48+
return true;
49+
}
50+
51+
public function isWritable(): bool
52+
{
53+
return true;
54+
}
55+
56+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\PHPParser;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Reflection\ClassReflection;
7+
use PHPStan\Reflection\PropertiesClassReflectionExtension;
8+
use PHPStan\Reflection\PropertyReflection;
9+
10+
class PhpParserNameClassReflectionExtension implements PropertiesClassReflectionExtension
11+
{
12+
13+
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
14+
{
15+
return $classReflection->isSubclassOf(Node::class)
16+
&& ($classReflection->getNativeReflection()->hasProperty('name') || $classReflection->getName() === \PhpParser\Node\FunctionLike::class)
17+
&& $propertyName === 'namespacedName';
18+
}
19+
20+
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
21+
{
22+
return new NamespacedNameProperty($classReflection);
23+
}
24+
25+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\PHPParser;
4+
5+
class PhpParserNameClassReflectionExtensionTest extends \PHPStan\Testing\TestCase
6+
{
7+
8+
public function dataHasProperty(): array
9+
{
10+
return [
11+
[
12+
true,
13+
\PhpParser\Node\Stmt\Class_::class,
14+
'namespacedName',
15+
],
16+
[
17+
true,
18+
\PhpParser\Node\Stmt\Function_::class,
19+
'namespacedName',
20+
],
21+
[
22+
true,
23+
\PhpParser\Node\FunctionLike::class,
24+
'namespacedName',
25+
],
26+
[
27+
false,
28+
\PhpParser\Node\Expr\Closure::class,
29+
'namespacedName',
30+
],
31+
[
32+
false,
33+
\PhpParser\Node\Stmt\Class_::class,
34+
'foo',
35+
],
36+
];
37+
}
38+
39+
/**
40+
* @dataProvider dataHasProperty
41+
* @param bool $expectedHas
42+
* @param string $className
43+
* @param string $propertyName
44+
*/
45+
public function testHasProperty(
46+
bool $expectedHas,
47+
string $className,
48+
string $propertyName
49+
)
50+
{
51+
$broker = $this->createBroker();
52+
$classReflection = $broker->getClass($className);
53+
$extension = new PhpParserNameClassReflectionExtension();
54+
$this->assertSame($expectedHas, $extension->hasProperty($classReflection, $propertyName));
55+
}
56+
57+
}

0 commit comments

Comments
 (0)