1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Analyser;
4:
5: use PHPStan\Reflection\ClassReflection;
6: use PHPStan\ShouldNotHappenException;
7: use PHPStan\Turbo\ShadowedByTurboExtension;
8:
9: #[ShadowedByTurboExtension(implementation: __DIR__ . '/../../turbo-ext/src/ScopeContext.cpp')]
10: final class ScopeContext
11: {
12:
13: private function __construct(
14: private string $file,
15: private ?ClassReflection $classReflection,
16: private ?ClassReflection $traitReflection,
17: )
18: {
19: }
20:
21: /** @api */
22: public static function create(string $file): self
23: {
24: return new self($file, classReflection: null, traitReflection: null);
25: }
26:
27: public function beginFile(): self
28: {
29: return new self($this->file, classReflection: null, traitReflection: null);
30: }
31:
32: public function enterClass(ClassReflection $classReflection): self
33: {
34: if ($this->classReflection !== null && !$classReflection->isAnonymous()) {
35: throw new ShouldNotHappenException();
36: }
37: if ($classReflection->isTrait()) {
38: throw new ShouldNotHappenException();
39: }
40: return new self($this->file, $classReflection, traitReflection: null);
41: }
42:
43: public function enterTrait(ClassReflection $traitReflection): self
44: {
45: if ($this->classReflection === null) {
46: throw new ShouldNotHappenException();
47: }
48: if (!$traitReflection->isTrait()) {
49: throw new ShouldNotHappenException();
50: }
51:
52: return new self($this->file, $this->classReflection, $traitReflection);
53: }
54:
55: public function equals(self $otherContext): bool
56: {
57: if ($this->file !== $otherContext->file) {
58: return false;
59: }
60:
61: if ($this->getClassReflection() === null) {
62: return $otherContext->getClassReflection() === null;
63: } elseif ($otherContext->getClassReflection() === null) {
64: return false;
65: }
66:
67: $isSameClass = $this->getClassReflection()->getName() === $otherContext->getClassReflection()->getName();
68:
69: if ($this->getTraitReflection() === null) {
70: return $otherContext->getTraitReflection() === null && $isSameClass;
71: } elseif ($otherContext->getTraitReflection() === null) {
72: return false;
73: }
74:
75: $isSameTrait = $this->getTraitReflection()->getName() === $otherContext->getTraitReflection()->getName();
76:
77: return $isSameClass && $isSameTrait;
78: }
79:
80: public function getFile(): string
81: {
82: return $this->file;
83: }
84:
85: public function getClassReflection(): ?ClassReflection
86: {
87: return $this->classReflection;
88: }
89:
90: public function getTraitReflection(): ?ClassReflection
91: {
92: return $this->traitReflection;
93: }
94:
95: }
96: