Skip to content

Commit dbf5eef

Browse files
committed
DRY in TemplateType implementations
1 parent 46e3ecd commit dbf5eef

File tree

4 files changed

+191
-460
lines changed

4 files changed

+191
-460
lines changed

src/Type/Generic/TemplateMixedType.php

Lines changed: 7 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,13 @@
33
namespace PHPStan\Type\Generic;
44

55
use PHPStan\TrinaryLogic;
6-
use PHPStan\Type\CompoundType;
7-
use PHPStan\Type\IntersectionType;
86
use PHPStan\Type\MixedType;
97
use PHPStan\Type\Type;
10-
use PHPStan\Type\UnionType;
11-
use PHPStan\Type\VerbosityLevel;
128

139
final class TemplateMixedType extends MixedType implements TemplateType
1410
{
1511

16-
private TemplateTypeScope $scope;
17-
18-
private string $name;
19-
20-
private TemplateTypeStrategy $strategy;
21-
22-
private TemplateTypeVariance $variance;
23-
24-
private ?MixedType $bound = null;
12+
use TemplateTypeTrait;
2513

2614
public function __construct(
2715
TemplateTypeScope $scope,
@@ -36,118 +24,21 @@ public function __construct(
3624
$this->strategy = $templateTypeStrategy;
3725
$this->variance = $templateTypeVariance;
3826
$this->name = $name;
39-
}
40-
41-
public function getName(): string
42-
{
43-
return $this->name;
44-
}
45-
46-
public function getScope(): TemplateTypeScope
47-
{
48-
return $this->scope;
49-
}
50-
51-
public function describe(VerbosityLevel $level): string
52-
{
53-
$basicDescription = function (): string {
54-
return $this->name;
55-
};
56-
return $level->handle(
57-
$basicDescription,
58-
$basicDescription,
59-
function () use ($basicDescription): string {
60-
return sprintf('%s (%s, %s)', $basicDescription(), $this->scope->describe(), $this->isArgument() ? 'argument' : 'parameter');
61-
}
62-
);
63-
}
64-
65-
public function equals(Type $type): bool
66-
{
67-
return $type instanceof self
68-
&& $type->scope->equals($this->scope)
69-
&& $type->name === $this->name
70-
&& parent::equals($type);
71-
}
72-
73-
public function getBound(): Type
74-
{
75-
if ($this->bound === null) {
76-
$this->bound = new MixedType(true);
77-
}
78-
return $this->bound;
79-
}
80-
81-
public function accepts(Type $type, bool $strictTypes): TrinaryLogic
82-
{
83-
return $this->strategy->accepts($this, $type, $strictTypes);
84-
}
85-
86-
public function isSuperTypeOf(Type $type): TrinaryLogic
87-
{
88-
if ($type instanceof CompoundType) {
89-
return $type->isSubTypeOf($this);
90-
}
91-
92-
return $this->getBound()->isSuperTypeOf($type)
93-
->and(TrinaryLogic::createMaybe());
27+
$this->bound = new MixedType(true);
9428
}
9529

9630
public function isSuperTypeOfMixed(MixedType $type): TrinaryLogic
9731
{
9832
return $this->isSuperTypeOf($type);
9933
}
10034

101-
public function isSubTypeOf(Type $type): TrinaryLogic
102-
{
103-
if ($type instanceof UnionType || $type instanceof IntersectionType) {
104-
return $type->isSuperTypeOf($this);
105-
}
106-
107-
if (!$type instanceof TemplateType) {
108-
return $type->isSuperTypeOf($this->getBound());
109-
}
110-
111-
if ($this->equals($type)) {
112-
return TrinaryLogic::createYes();
113-
}
114-
115-
return $type->getBound()->isSuperTypeOf($this->getBound())
116-
->and(TrinaryLogic::createMaybe());
117-
}
118-
119-
public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
35+
public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
12036
{
121-
if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) {
122-
return $receivedType->inferTemplateTypesOn($this);
123-
}
124-
125-
if (
126-
$receivedType instanceof TemplateType
127-
&& $this->getBound()->isSuperTypeOf($receivedType->getBound())->yes()
128-
) {
129-
return new TemplateTypeMap([
130-
$this->name => $receivedType,
131-
]);
37+
$isSuperType = $this->isSuperTypeOf($acceptingType);
38+
if ($isSuperType->no()) {
39+
return $isSuperType;
13240
}
133-
134-
if ($this->getBound()->isSuperTypeOf($receivedType)->yes()) {
135-
return new TemplateTypeMap([
136-
$this->name => TemplateTypeHelper::generalizeType($receivedType),
137-
]);
138-
}
139-
140-
return TemplateTypeMap::createEmpty();
141-
}
142-
143-
public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array
144-
{
145-
return [new TemplateTypeReference($this, $positionVariance)];
146-
}
147-
148-
public function isArgument(): bool
149-
{
150-
return $this->strategy->isArgument();
41+
return TrinaryLogic::createYes();
15142
}
15243

15344
public function toArgument(): TemplateType
@@ -160,31 +51,6 @@ public function toArgument(): TemplateType
16051
);
16152
}
16253

163-
public function isValidVariance(Type $a, Type $b): TrinaryLogic
164-
{
165-
return $this->variance->isValidVariance($a, $b);
166-
}
167-
168-
public function subtract(Type $type): Type
169-
{
170-
return $this;
171-
}
172-
173-
public function getTypeWithoutSubtractedType(): Type
174-
{
175-
return $this;
176-
}
177-
178-
public function changeSubtractedType(?Type $subtractedType): Type
179-
{
180-
return $this;
181-
}
182-
183-
public function getVariance(): TemplateTypeVariance
184-
{
185-
return $this->variance;
186-
}
187-
18854
/**
18955
* @param mixed[] $properties
19056
* @return Type

src/Type/Generic/TemplateObjectType.php

Lines changed: 8 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,18 @@
33
namespace PHPStan\Type\Generic;
44

55
use PHPStan\TrinaryLogic;
6-
use PHPStan\Type\CompoundType;
7-
use PHPStan\Type\IntersectionType;
86
use PHPStan\Type\ObjectType;
97
use PHPStan\Type\ObjectWithoutClassType;
108
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
119
use PHPStan\Type\Type;
12-
use PHPStan\Type\UnionType;
13-
use PHPStan\Type\VerbosityLevel;
1410

1511
final class TemplateObjectType extends ObjectType implements TemplateType
1612
{
1713

1814
use UndecidedComparisonCompoundTypeTrait;
19-
20-
private TemplateTypeScope $scope;
21-
22-
private string $name;
23-
24-
private TemplateTypeStrategy $strategy;
25-
26-
private ObjectType $bound;
27-
28-
private TemplateTypeVariance $variance;
15+
use TemplateTypeTrait {
16+
isSubTypeOf as isSubTypeOfTrait;
17+
}
2918

3019
public function __construct(
3120
TemplateTypeScope $scope,
@@ -44,43 +33,13 @@ public function __construct(
4433
$this->bound = new ObjectType($class);
4534
}
4635

47-
public function getName(): string
48-
{
49-
return $this->name;
50-
}
51-
52-
public function getScope(): TemplateTypeScope
53-
{
54-
return $this->scope;
55-
}
56-
57-
public function getBound(): Type
58-
{
59-
return $this->bound;
60-
}
61-
62-
public function describe(VerbosityLevel $level): string
36+
public function isSubTypeOf(Type $type): TrinaryLogic
6337
{
64-
$basicDescription = function () use ($level): string {
65-
return sprintf(
66-
'%s of %s',
67-
$this->name,
68-
parent::describe($level)
69-
);
70-
};
71-
72-
return $level->handle(
73-
$basicDescription,
74-
$basicDescription,
75-
function () use ($basicDescription): string {
76-
return sprintf('%s (%s, %s)', $basicDescription(), $this->scope->describe(), $this->isArgument() ? 'argument' : 'parameter');
77-
}
78-
);
79-
}
38+
if ($type instanceof ObjectWithoutClassType) {
39+
return TrinaryLogic::createYes();
40+
}
8041

81-
public function isArgument(): bool
82-
{
83-
return $this->strategy->isArgument();
42+
return $this->isSubTypeOfTrait($type);
8443
}
8544

8645
public function toArgument(): TemplateType
@@ -94,114 +53,6 @@ public function toArgument(): TemplateType
9453
);
9554
}
9655

97-
public function isValidVariance(Type $a, Type $b): TrinaryLogic
98-
{
99-
return $this->variance->isValidVariance($a, $b);
100-
}
101-
102-
public function subtract(Type $type): Type
103-
{
104-
return $this;
105-
}
106-
107-
public function getTypeWithoutSubtractedType(): Type
108-
{
109-
return $this;
110-
}
111-
112-
public function changeSubtractedType(?Type $subtractedType): Type
113-
{
114-
return $this;
115-
}
116-
117-
public function equals(Type $type): bool
118-
{
119-
return $type instanceof self
120-
&& $type->scope->equals($this->scope)
121-
&& $type->name === $this->name
122-
&& parent::equals($type);
123-
}
124-
125-
public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
126-
{
127-
return $this->isSubTypeOf($acceptingType);
128-
}
129-
130-
public function accepts(Type $type, bool $strictTypes): TrinaryLogic
131-
{
132-
return $this->strategy->accepts($this, $type, $strictTypes);
133-
}
134-
135-
public function isSuperTypeOf(Type $type): TrinaryLogic
136-
{
137-
if ($type instanceof CompoundType) {
138-
return $type->isSubTypeOf($this);
139-
}
140-
141-
return $this->getBound()->isSuperTypeOf($type)
142-
->and(TrinaryLogic::createMaybe());
143-
}
144-
145-
public function isSubTypeOf(Type $type): TrinaryLogic
146-
{
147-
if ($type instanceof UnionType || $type instanceof IntersectionType) {
148-
return $type->isSuperTypeOf($this);
149-
}
150-
151-
if ($type instanceof ObjectWithoutClassType) {
152-
return TrinaryLogic::createYes();
153-
}
154-
155-
if (!$type instanceof TemplateType) {
156-
return $type->isSuperTypeOf($this->getBound());
157-
}
158-
159-
if ($this->equals($type)) {
160-
return TrinaryLogic::createYes();
161-
}
162-
163-
if ($type->getBound()->isSuperTypeOf($this->getBound())->no() &&
164-
$this->getBound()->isSuperTypeOf($type->getBound())->no()) {
165-
return TrinaryLogic::createNo();
166-
}
167-
168-
return TrinaryLogic::createMaybe();
169-
}
170-
171-
public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
172-
{
173-
if ($receivedType instanceof UnionType || $receivedType instanceof IntersectionType) {
174-
return $receivedType->inferTemplateTypesOn($this);
175-
}
176-
177-
if (
178-
$receivedType instanceof TemplateType
179-
&& $this->getBound()->isSuperTypeOf($receivedType->getBound())->yes()
180-
) {
181-
return new TemplateTypeMap([
182-
$this->name => $receivedType,
183-
]);
184-
}
185-
186-
if ($this->getBound()->isSuperTypeOf($receivedType)->yes()) {
187-
return new TemplateTypeMap([
188-
$this->name => TemplateTypeHelper::generalizeType($receivedType),
189-
]);
190-
}
191-
192-
return TemplateTypeMap::createEmpty();
193-
}
194-
195-
public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array
196-
{
197-
return [new TemplateTypeReference($this, $positionVariance)];
198-
}
199-
200-
public function getVariance(): TemplateTypeVariance
201-
{
202-
return $this->variance;
203-
}
204-
20556
/**
20657
* @param mixed[] $properties
20758
* @return Type

0 commit comments

Comments
 (0)