Skip to content

Commit 9562191

Browse files
committed
Only reflect the classes we need
1 parent f2fb5ec commit 9562191

File tree

5 files changed

+95
-53
lines changed

5 files changed

+95
-53
lines changed

src/Handler/GenerateHandler.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use App\Generator\Generator;
88
use App\SniffFinder\SniffFinder;
99
use App\Value\Folder;
10+
use Iterator;
1011
use Symfony\Component\Filesystem\Filesystem;
1112

1213
class GenerateHandler
@@ -22,7 +23,10 @@ public function __construct(CodeRepository $codeRepository, Generator $generator
2223
$this->sniffFinder = $sniffFinder;
2324
}
2425

25-
public function handle()
26+
/**
27+
* @return Iterator<string>
28+
*/
29+
public function handle(): Iterator
2630
{
2731
$repoName = 'PHPCompatibility/PHPCompatibility';
2832
$repoPath = $this->codeRepository->downloadCode($repoName);
@@ -31,11 +35,13 @@ public function handle()
3135
$standardPath = new Folder($repoPath . 'PHPCompatibility/');
3236

3337
foreach ($this->sniffFinder->getSniffs($standardPath) as $sniff) {
38+
$markdownPath = $this->sniffCodeToMarkdownPath($sniff->getCode());
3439
$filesystem->dumpFile(
3540
// TODO: perhaps we can move this logic to the the sniff class
36-
$this->sniffCodeToMarkdownPath($sniff->getCode()),
41+
$markdownPath,
3742
$this->generator->createSniffDoc($sniff)
3843
);
44+
yield "Created file: {$markdownPath}";
3945
}
4046
}
4147

src/Parser/SniffParser.php

+30-33
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,36 @@
55

66
use App\Parser\Exception\NotASniffPath;
77
use App\Value\Diff;
8-
use App\Value\Folder;
98
use App\Value\Property;
109
use App\Value\Sniff;
1110
use App\Value\Url;
1211
use App\Value\Urls;
13-
use CallbackFilterIterator;
1412
use GlobIterator;
15-
use Iterator;
1613
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
1714
use phpDocumentor\Reflection\DocBlockFactory;
18-
use RecursiveDirectoryIterator;
19-
use RecursiveIteratorIterator;
2015
use ReflectionProperty;
2116
use Roave\BetterReflection\BetterReflection;
2217
use Roave\BetterReflection\Reflection as Roave;
2318
use Roave\BetterReflection\Reflection\ReflectionClass;
2419
use Roave\BetterReflection\Reflector\ClassReflector;
2520
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
26-
use Roave\BetterReflection\SourceLocator\Type\FileIteratorSourceLocator;
2721
use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator;
22+
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;
2823
use SimpleXMLElement;
29-
use SplFileInfo;
3024
use function Stringy\create as s;
3125

3226
class SniffParser
3327
{
34-
public function parse(string $phpFilePath, Folder $repoFolder): Sniff
28+
public function parse(string $phpFilePath, SourceLocator $projectSourceLocator): Sniff
3529
{
3630
$astLocator = (new BetterReflection())->astLocator();
37-
$fileInfoIterator = $this->recursiveSearch($repoFolder);
38-
$sourceLocators = [
39-
new SingleFileSourceLocator($phpFilePath, $astLocator),
40-
new FileIteratorSourceLocator($fileInfoIterator, $astLocator)
41-
];
4231
$reflector = new ClassReflector(
43-
new AggregateSourceLocator($sourceLocators)
32+
new AggregateSourceLocator([
33+
new SingleFileSourceLocator($phpFilePath, $astLocator),
34+
$projectSourceLocator
35+
])
4436
);
45-
$classInfo = $reflector->getAllClasses()[0];
37+
$classInfo = $reflector->reflect($this->getSniffClassName($phpFilePath));
4638

4739
$xmlUrls = [];
4840
$description = '';
@@ -73,18 +65,6 @@ public function parse(string $phpFilePath, Folder $repoFolder): Sniff
7365
);
7466
}
7567

76-
/**
77-
* @return Iterator<SplFileInfo>
78-
*/
79-
private function recursiveSearch(Folder $folder): Iterator
80-
{
81-
$dirs = new RecursiveDirectoryIterator($folder->getPath());
82-
$files = new RecursiveIteratorIterator($dirs);
83-
return new CallbackFilterIterator($files, function (SplFileInfo $fileInfo) {
84-
return preg_match('/\.php$/', $fileInfo->getPathname()) && !preg_match('/\/Tests\//', $fileInfo->getPathname());
85-
});
86-
}
87-
8868
/**
8969
* @return Url[]
9070
*/
@@ -123,13 +103,9 @@ private function getDiffs(SimpleXMLElement $xml): array
123103

124104
private function getCode(string $filePath): string
125105
{
126-
$part = '([^\/]*)';
127-
preg_match("/$part\/Sniffs\/$part\/{$part}Sniff\.php/", $filePath, $matches);
128-
if ($matches === []) {
129-
throw NotASniffPath::fromPath($filePath);
130-
}
106+
$parts = $this->getSniffFileParts($filePath);
131107

132-
return sprintf('%s.%s.%s', $matches[1], $matches[2], $matches[3]);
108+
return sprintf('%s.%s.%s', $parts[0], $parts[1], $parts[2]);
133109
}
134110

135111
private function getDocBlock(string $docComment): string
@@ -216,4 +192,25 @@ private function getLinks(ReflectionClass $classInfo, array $xmlUrls): Urls
216192

217193
return new Urls(array_merge($urls, $xmlUrls));
218194
}
195+
196+
private function getSniffClassName(string $phpFilePath): string
197+
{
198+
$parts = $this->getSniffFileParts($phpFilePath);
199+
200+
return "{$parts[0]}\\Sniffs\\{$parts[1]}\\{$parts[2]}Sniff";
201+
}
202+
203+
/**
204+
* @return string[]
205+
*/
206+
private function getSniffFileParts(string $filePath): array
207+
{
208+
$part = '([^\/]*)';
209+
preg_match("/$part\/Sniffs\/$part\/{$part}Sniff\.php/", $filePath, $matches);
210+
if ($matches === []) {
211+
throw NotASniffPath::fromPath($filePath);
212+
}
213+
214+
return array_slice($matches, 1, 3);
215+
}
219216
}

src/SniffFinder/FilesystemSniffFinder.php

+29-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@
55

66
use App\Parser\SniffParser;
77
use App\Value\Folder;
8+
use CallbackFilterIterator;
89
use GlobIterator;
10+
use Iterator;
11+
use RecursiveDirectoryIterator;
12+
use RecursiveIteratorIterator;
13+
use Roave\BetterReflection\BetterReflection;
14+
use Roave\BetterReflection\SourceLocator\Type\FileIteratorSourceLocator;
15+
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;
16+
use SplFileInfo;
917
use Traversable;
1018

1119
class FilesystemSniffFinder implements SniffFinder
@@ -14,8 +22,28 @@ public function getSniffs(Folder $folder): Traversable
1422
{
1523
$parser = new SniffParser();
1624
$globSniffs = new GlobIterator($folder->getPath() . 'Sniffs/*/*Sniff.php');
25+
$projectSourceLocator = $this->createProjectSourceLocator($folder);
1726
foreach ($globSniffs as $fileInfo) {
18-
yield $parser->parse($fileInfo->getPathname(), $folder);
27+
yield $parser->parse($fileInfo->getPathname(), $projectSourceLocator);
1928
}
2029
}
30+
31+
/**
32+
* @return Iterator<SplFileInfo>
33+
*/
34+
private function recursiveSearch(Folder $folder): Iterator
35+
{
36+
$dirs = new RecursiveDirectoryIterator($folder->getPath());
37+
$files = new RecursiveIteratorIterator($dirs);
38+
return new CallbackFilterIterator($files, function (SplFileInfo $fileInfo) {
39+
return preg_match('/\.php$/', $fileInfo->getPathname()) && !preg_match('/\/Tests\//', $fileInfo->getPathname());
40+
});
41+
}
42+
43+
private function createProjectSourceLocator(Folder $folder): SourceLocator
44+
{
45+
$astLocator = (new BetterReflection())->astLocator();
46+
$fileInfoIterator = $this->recursiveSearch($folder);
47+
return new FileIteratorSourceLocator($fileInfoIterator, $astLocator);
48+
}
2149
}

tests/Parser/SniffParserTest.php

+26-16
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,40 @@
44
namespace App\Tests\Parser;
55

66
use App\Parser\SniffParser;
7-
use App\Value\Folder;
87
use App\Value\Property;
98
use App\Value\Url;
109
use PHPUnit\Framework\TestCase;
10+
use Roave\BetterReflection\BetterReflection;
11+
use Roave\BetterReflection\SourceLocator\Ast\Locator;
12+
use Roave\BetterReflection\SourceLocator\Type\StringSourceLocator;
1113
use Symfony\Component\Filesystem\Filesystem;
1214

1315
/** @covers \App\Parser\SniffParser */
1416
class SniffParserTest extends TestCase
1517
{
1618
private const PHP_FILE_PATH = 'var/tests/src/Standard/Sniffs/Category/MySniff.php';
1719
private const XML_FILE_PATH = 'var/tests/src/Standard/Docs/Category/MyStandard.xml';
18-
private const REPO_FOLDER = 'var/tests/';
1920

2021
private SniffParser $parser;
22+
private Locator $astLocator;
2123

2224
/** @test */
2325
public function parse_WithValidPath_AddCode()
2426
{
2527
$content = '<?php
28+
namespace Standard\Sniffs\Category;
2629
/**
2730
* Summary
2831
*
2932
* Description
3033
*
3134
* @since 1.0.0
3235
*/
33-
class SniffName {}
36+
class MySniff {}
3437
';
3538

3639
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
37-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
40+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
3841
self::assertEquals(
3942
'Standard.Category.My',
4043
$doc->getCode()
@@ -45,18 +48,19 @@ class SniffName {}
4548
public function parse_WithDocblockSummaryAndDescription_AddAllText()
4649
{
4750
$content = '<?php
51+
namespace Standard\Sniffs\Category;
4852
/**
4953
* Summary
5054
*
5155
* Description
5256
*
5357
* @since 1.0.0
5458
*/
55-
class SniffName {}
59+
class MySniff {}
5660
';
5761

5862
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
59-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
63+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
6064
self::assertEquals(
6165
"Summary\n\nDescription",
6266
$doc->getDocblock()
@@ -67,14 +71,15 @@ class SniffName {}
6771
public function parse_WithDocblockSummary_AddSummary()
6872
{
6973
$content = '<?php
74+
namespace Standard\Sniffs\Category;
7075
/**
7176
* Summary
7277
*/
73-
class SniffName {}
78+
class MySniff {}
7479
';
7580

7681
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
77-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
82+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
7883
self::assertEquals(
7984
'Summary',
8085
$doc->getDocblock()
@@ -85,7 +90,8 @@ class SniffName {}
8590
public function parse_WithProperties_AddPublicOnly()
8691
{
8792
$content = '<?php
88-
class SniffName {
93+
namespace Standard\Sniffs\Category;
94+
class MySniff {
8995
/** @var bool */
9096
public $boolProperty = false;
9197
public string $stringProperty = "";
@@ -97,7 +103,7 @@ class SniffName {
97103
';
98104

99105
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
100-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
106+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
101107
self::assertEquals(
102108
[
103109
new Property('boolProperty', 'bool', ''),
@@ -113,15 +119,16 @@ class SniffName {
113119
public function parse_WithMultipleLinks_AddLinks()
114120
{
115121
$content = '<?php
122+
namespace Standard\Sniffs\Category;
116123
/**
117124
* @link http://link1.com
118125
* @link http://link2.com
119126
*/
120-
class SniffName {}
127+
class MySniff {}
121128
';
122129

123130
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
124-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
131+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
125132
self::assertEquals(
126133
[
127134
new Url('http://link1.com'),
@@ -135,18 +142,19 @@ class SniffName {}
135142
public function parse_WithXmlDocs_AddProperties()
136143
{
137144
$content = '<?php
145+
namespace Standard\Sniffs\Category;
138146
/**
139147
* Summary
140148
*
141149
* Description
142150
*
143151
* @since 1.0.0
144152
*/
145-
class SniffName {}
153+
class MySniff {}
146154
';
147155

148156
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
149-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
157+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
150158
self::assertEquals(
151159
'Standard.Category.My',
152160
$doc->getCode()
@@ -157,11 +165,12 @@ class SniffName {}
157165
public function parse_WithXmlLinks_MergeLinks()
158166
{
159167
$content = '<?php
168+
namespace Standard\Sniffs\Category;
160169
/**
161170
* @link http://link1.com
162171
* @link http://link3.com
163172
*/
164-
class SniffName {}
173+
class MySniff {}
165174
';
166175

167176
(new Filesystem())->dumpFile(self::PHP_FILE_PATH, $content);
@@ -175,7 +184,7 @@ class SniffName {}
175184
XML;
176185
(new Filesystem())->dumpFile(self::XML_FILE_PATH, $content);
177186

178-
$doc = $this->parser->parse(self::PHP_FILE_PATH, new Folder(self::REPO_FOLDER));
187+
$doc = $this->parser->parse(self::PHP_FILE_PATH, new StringSourceLocator($content, $this->astLocator));
179188
self::assertEquals(
180189
[
181190
new Url('http://link1.com'),
@@ -189,5 +198,6 @@ class SniffName {}
189198
protected function setUp(): void
190199
{
191200
$this->parser = new SniffParser();
201+
$this->astLocator = (new BetterReflection())->astLocator();
192202
}
193203
}

tests/SniffFinder/FilesystemSniffFinderTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ public function getSniffs()
5757
private function writeSniffPhp(): void
5858
{
5959
$content = '<?php
60-
class SniffName {}
60+
namespace Standard\Sniffs\Category;
61+
class MySniff {}
6162
';
6263
(new Filesystem())->dumpFile(self::PHP_SNIFF_PATH, $content);
6364
}

0 commit comments

Comments
 (0)