1 | <?php |
||
2 | declare(strict_types=1); |
||
3 | |||
4 | namespace DependencyAnalyzer; |
||
5 | |||
6 | use DependencyAnalyzer\DependencyDumper\CollectDependenciesVisitor; |
||
7 | use DependencyAnalyzer\DependencyDumper\NullObserver; |
||
8 | use DependencyAnalyzer\DependencyDumper\ObserverInterface; |
||
9 | use DependencyAnalyzer\Exceptions\AnalyzedFileException; |
||
10 | use PHPStan\AnalysedCodeException; |
||
11 | use PHPStan\Analyser\ScopeContext; |
||
12 | use PHPStan\Parser\Parser; |
||
13 | use PHPStan\Analyser\NodeScopeResolver; |
||
14 | use PHPStan\Analyser\ScopeFactory; |
||
15 | use PHPStan\DependencyInjection\ContainerFactory; |
||
16 | use PHPStan\File\FileFinder; |
||
17 | use PHPStan\ShouldNotHappenException; |
||
18 | |||
19 | class DependencyDumper |
||
20 | { |
||
21 | /** |
||
22 | * @var CollectDependenciesVisitor |
||
23 | */ |
||
24 | protected $collectNodeVisitor; |
||
25 | |||
26 | /** |
||
27 | * @var NodeScopeResolver |
||
28 | */ |
||
29 | protected $nodeScopeResolver; |
||
30 | |||
31 | /** |
||
32 | * @var Parser |
||
33 | */ |
||
34 | protected $parser; |
||
35 | |||
36 | /** |
||
37 | * @var ScopeFactory |
||
38 | */ |
||
39 | protected $scopeFactory; |
||
40 | |||
41 | /** |
||
42 | * @var FileFinder |
||
43 | */ |
||
44 | protected $fileFinder; |
||
45 | |||
46 | /** |
||
47 | * @var ObserverInterface |
||
48 | */ |
||
49 | protected static $observer = null; |
||
50 | |||
51 | public function __construct( |
||
52 | NodeScopeResolver $nodeScopeResolver, |
||
53 | Parser $parser, |
||
54 | ScopeFactory $scopeFactory, |
||
55 | FileFinder $fileFinder, |
||
56 | CollectDependenciesVisitor $collectNodeVisitor |
||
57 | ) |
||
58 | { |
||
59 | $this->nodeScopeResolver = $nodeScopeResolver; |
||
60 | $this->parser = $parser; |
||
61 | $this->scopeFactory = $scopeFactory; |
||
62 | $this->fileFinder = $fileFinder; |
||
63 | $this->collectNodeVisitor = $collectNodeVisitor; |
||
64 | } |
||
65 | |||
66 | public static function createFromConfig(string $currentDir, string $tmpDir, array $additionalConfigFiles): self |
||
67 | { |
||
68 | $phpStanContainer = (new ContainerFactory($currentDir))->create($tmpDir, $additionalConfigFiles, []); |
||
69 | |||
70 | return new self( |
||
71 | $phpStanContainer->getByType(NodeScopeResolver::class), |
||
72 | $phpStanContainer->getByType(Parser::class), |
||
73 | $phpStanContainer->getByType(ScopeFactory::class), |
||
74 | $phpStanContainer->getByType(FileFinder::class), |
||
75 | $phpStanContainer->getByType(CollectDependenciesVisitor::class) |
||
76 | ); |
||
77 | } |
||
78 | |||
79 | public function dump(array $paths, array $excludePaths = []): DependencyGraph |
||
80 | { |
||
81 | $excludeFiles = $this->getAllFilesRecursive($excludePaths); |
||
82 | $files = $this->getAllFilesRecursive($paths); |
||
83 | |||
84 | $this->notifyDumpStart(array_reduce($files, function (int $max, string $file) use ($excludeFiles) { |
||
85 | if (!in_array($file, $excludeFiles)) { |
||
86 | $max++; |
||
87 | } |
||
88 | |||
89 | return $max; |
||
90 | }, 0)); |
||
91 | foreach ($files as $file) { |
||
92 | if (!in_array($file, $excludeFiles)) { |
||
93 | $this->notifyCurrentFile($file); |
||
94 | |||
95 | try { |
||
96 | $this->dumpFile($file); |
||
97 | } catch (AnalyzedFileException $e) { |
||
98 | $this->notifyAnalyzedFileException($e); |
||
99 | } |
||
100 | } |
||
101 | } |
||
102 | $this->notifyDumpEnd(); |
||
103 | |||
104 | return $this->collectNodeVisitor->getDependencyGraphBuilder()->build(); |
||
105 | } |
||
106 | |||
107 | protected function dumpFile(string $file): void |
||
108 | { |
||
109 | try { |
||
110 | $this->collectNodeVisitor->setFile($file); |
||
111 | |||
112 | // collect dependencies in $this->collectNodeVisitor |
||
113 | $this->nodeScopeResolver->processNodes( |
||
114 | $this->parser->parseFile($file), |
||
115 | $this->scopeFactory->create(ScopeContext::create($file)), |
||
116 | \Closure::fromCallable($this->collectNodeVisitor) // type hint of processNodes() is \Closure... |
||
117 | ); |
||
118 | } catch (ShouldNotHappenException $e) { |
||
119 | throw new AnalyzedFileException($file, 'analyzing file is failed, because unexpected error', 0, $e); |
||
120 | } catch (AnalysedCodeException $e) { |
||
121 | throw new AnalyzedFileException($file, 'analyzing file is failed, because unexpected error', 0, $e); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | protected function getAllFilesRecursive(array $paths): array |
||
126 | { |
||
127 | try { |
||
128 | $fileFinderResult = $this->fileFinder->findFiles($paths); |
||
129 | } catch (\PHPStan\File\PathNotFoundException $e) { |
||
130 | throw new AnalyzedFileException($e->getPath(), 'path was not found.', 0, $e); |
||
131 | } |
||
132 | |||
133 | return $fileFinderResult->getFiles(); |
||
134 | } |
||
135 | |||
136 | public function setObserver(ObserverInterface $observer = null): self |
||
137 | { |
||
138 | self::$observer = $observer; |
||
139 | $this->collectNodeVisitor->getDependencyGraphBuilder()->setObserver($observer); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
140 | |||
141 | return $this; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @return ObserverInterface |
||
146 | * @da-internal \DependencyAnalyzer\DependencyDumper |
||
147 | * @da-internal \DependencyAnalyzer\DependencyDumper\ |
||
148 | */ |
||
149 | public static function getObserver(): ObserverInterface |
||
150 | { |
||
151 | if (!is_null(self::$observer)) { |
||
152 | return self::$observer; |
||
153 | } |
||
154 | |||
155 | return new NullObserver(); |
||
156 | } |
||
157 | |||
158 | protected function notifyDumpStart(int $max): void |
||
159 | { |
||
160 | self::getObserver()->start($max); |
||
161 | } |
||
162 | |||
163 | protected function notifyCurrentFile(string $file): void |
||
164 | { |
||
165 | self::getObserver()->update($file); |
||
166 | } |
||
167 | |||
168 | protected function notifyAnalyzedFileException(AnalyzedFileException $e): void |
||
169 | { |
||
170 | self::getObserver()->notifyAnalyzeFileError($e); |
||
171 | } |
||
172 | |||
173 | protected function notifyDumpEnd(): void |
||
174 | { |
||
175 | self::getObserver()->end(); |
||
176 | } |
||
177 | } |
||
178 |