1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Command;
4:
5: use PHPStan\Analyser\Error;
6: use PHPStan\Analyser\InternalError;
7: use PHPStan\Collectors\CollectedData;
8: use function count;
9: use function usort;
10:
11: /**
12: * @api
13: */
14: final class AnalysisResult
15: {
16:
17: /** @var list<Error> sorted by their file name, line number and message */
18: private array $fileSpecificErrors;
19:
20: /**
21: * @param list<Error> $fileSpecificErrors
22: * @param list<string> $notFileSpecificErrors
23: * @param list<InternalError> $internalErrors
24: * @param list<string> $warnings
25: * @param list<CollectedData> $collectedData
26: * @param array<string, string> $changedProjectExtensionFilesOutsideOfAnalysedPaths
27: * @param list<string> $processedFiles
28: */
29: public function __construct(
30: array $fileSpecificErrors,
31: private array $notFileSpecificErrors,
32: private array $internalErrors,
33: private array $warnings,
34: private array $collectedData,
35: private bool $defaultLevelUsed,
36: private ?string $projectConfigFile,
37: private bool $savedResultCache,
38: private int $peakMemoryUsageBytes,
39: private bool $isResultCacheUsed,
40: private array $changedProjectExtensionFilesOutsideOfAnalysedPaths,
41: private array $processedFiles = [],
42: private bool $resultCacheExisted = true,
43: )
44: {
45: usort(
46: $fileSpecificErrors,
47: static fn (Error $a, Error $b): int => [
48: $a->getFile(),
49: $a->getLine(),
50: $a->getMessage(),
51: ] <=> [
52: $b->getFile(),
53: $b->getLine(),
54: $b->getMessage(),
55: ],
56: );
57:
58: $this->fileSpecificErrors = $fileSpecificErrors;
59: }
60:
61: public function hasErrors(): bool
62: {
63: return $this->getTotalErrorsCount() > 0;
64: }
65:
66: public function getTotalErrorsCount(): int
67: {
68: return count($this->fileSpecificErrors) + count($this->notFileSpecificErrors);
69: }
70:
71: /**
72: * @return list<Error> sorted by their file name, line number and message
73: */
74: public function getFileSpecificErrors(): array
75: {
76: return $this->fileSpecificErrors;
77: }
78:
79: /**
80: * @return list<string>
81: */
82: public function getNotFileSpecificErrors(): array
83: {
84: return $this->notFileSpecificErrors;
85: }
86:
87: /**
88: * @return list<InternalError>
89: */
90: public function getInternalErrorObjects(): array
91: {
92: return $this->internalErrors;
93: }
94:
95: /**
96: * @return list<string>
97: */
98: public function getWarnings(): array
99: {
100: return $this->warnings;
101: }
102:
103: public function hasWarnings(): bool
104: {
105: return count($this->warnings) > 0;
106: }
107:
108: /**
109: * @return list<CollectedData>
110: */
111: public function getCollectedData(): array
112: {
113: return $this->collectedData;
114: }
115:
116: public function isDefaultLevelUsed(): bool
117: {
118: return $this->defaultLevelUsed;
119: }
120:
121: public function getProjectConfigFile(): ?string
122: {
123: return $this->projectConfigFile;
124: }
125:
126: public function hasInternalErrors(): bool
127: {
128: return count($this->internalErrors) > 0;
129: }
130:
131: public function isResultCacheSaved(): bool
132: {
133: return $this->savedResultCache;
134: }
135:
136: public function getPeakMemoryUsageBytes(): int
137: {
138: return $this->peakMemoryUsageBytes;
139: }
140:
141: public function isResultCacheUsed(): bool
142: {
143: return $this->isResultCacheUsed;
144: }
145:
146: /**
147: * Whether the result cache file existed when PHPStan started.
148: * False means the cache was never created; a stale/invalid cache that
149: * triggered a full re-analysis still counts as existing.
150: */
151: public function resultCacheExisted(): bool
152: {
153: return $this->resultCacheExisted;
154: }
155:
156: /**
157: * @return array<string, string>
158: */
159: public function getChangedProjectExtensionFilesOutsideOfAnalysedPaths(): array
160: {
161: return $this->changedProjectExtensionFilesOutsideOfAnalysedPaths;
162: }
163:
164: /**
165: * @return list<string>
166: */
167: public function getProcessedFiles(): array
168: {
169: return $this->processedFiles;
170: }
171:
172: /**
173: * @api
174: * @param list<Error> $fileSpecificErrors
175: */
176: public function withFileSpecificErrors(array $fileSpecificErrors): self
177: {
178: return new self(
179: $fileSpecificErrors,
180: $this->notFileSpecificErrors,
181: $this->internalErrors,
182: $this->warnings,
183: $this->collectedData,
184: $this->defaultLevelUsed,
185: $this->projectConfigFile,
186: $this->savedResultCache,
187: $this->peakMemoryUsageBytes,
188: $this->isResultCacheUsed,
189: $this->changedProjectExtensionFilesOutsideOfAnalysedPaths,
190: $this->processedFiles,
191: $this->resultCacheExisted,
192: );
193: }
194:
195: }
196: