Skip to content

Commit

Permalink
An option for checking explicit mixed
Browse files Browse the repository at this point in the history
Eventually this will become level 9
  • Loading branch information
ondrejmirtes committed May 25, 2020
1 parent 6a38951 commit da0b2eb
Show file tree
Hide file tree
Showing 41 changed files with 372 additions and 38 deletions.
3 changes: 3 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ parameters:
checkAlwaysTrueInstanceof: false
checkAlwaysTrueStrictComparison: false
checkClassCaseSensitivity: false
checkExplicitMixed: false
checkFunctionArgumentTypes: false
checkFunctionNameCase: false
checkGenericClassInNonGenericObjectType: false
Expand Down Expand Up @@ -145,6 +146,7 @@ parametersSchema:
checkAlwaysTrueInstanceof: bool()
checkAlwaysTrueStrictComparison: bool()
checkClassCaseSensitivity: bool()
checkExplicitMixed: bool()
checkFunctionArgumentTypes: bool()
checkFunctionNameCase: bool()
checkGenericClassInNonGenericObjectType: bool()
Expand Down Expand Up @@ -596,6 +598,7 @@ services:
checkNullables: %checkNullables%
checkThisOnly: %checkThisOnly%
checkUnionTypes: %checkUnionTypes%
checkExplicitMixed: %checkExplicitMixed%

-
class: PHPStan\Rules\UnusedFunctionParametersCheck
Expand Down
25 changes: 24 additions & 1 deletion src/Rules/RuleLevelHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
use PHPStan\Type\BenevolentUnionType;
use PHPStan\Type\CompoundType;
use PHPStan\Type\ErrorType;
use PHPStan\Type\Generic\TemplateMixedType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\StaticType;
use PHPStan\Type\StrictMixedType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeUtils;
Expand All @@ -29,17 +31,21 @@ class RuleLevelHelper

private bool $checkUnionTypes;

private bool $checkExplicitMixed;

public function __construct(
ReflectionProvider $reflectionProvider,
bool $checkNullables,
bool $checkThisOnly,
bool $checkUnionTypes
bool $checkUnionTypes,
bool $checkExplicitMixed
)
{
$this->reflectionProvider = $reflectionProvider;
$this->checkNullables = $checkNullables;
$this->checkThisOnly = $checkThisOnly;
$this->checkUnionTypes = $checkUnionTypes;
$this->checkExplicitMixed = $checkExplicitMixed;
}

public function isThis(Expr $expression): bool
Expand All @@ -49,6 +55,14 @@ public function isThis(Expr $expression): bool

public function accepts(Type $acceptingType, Type $acceptedType, bool $strictTypes): bool
{
if (
$this->checkExplicitMixed
&& $acceptedType instanceof MixedType
&& $acceptedType->isExplicitMixed()
) {
$acceptedType = new StrictMixedType();
}

if (
!$this->checkNullables
&& !$acceptingType instanceof NullType
Expand Down Expand Up @@ -111,6 +125,15 @@ public function findTypeToCheck(
if (!$this->checkNullables && !$type instanceof NullType) {
$type = \PHPStan\Type\TypeCombinator::removeNull($type);
}
if (
$this->checkExplicitMixed
&& $type instanceof MixedType
&& !$type instanceof TemplateMixedType
&& $type->isExplicitMixed()
) {
return new FoundTypeResult(new StrictMixedType(), [], []);
}

if ($type instanceof MixedType || $type instanceof NeverType) {
return new FoundTypeResult(new ErrorType(), [], []);
}
Expand Down
213 changes: 213 additions & 0 deletions src/Type/StrictMixedType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type;

use PHPStan\Reflection\ClassMemberAccessAnswerer;
use PHPStan\Reflection\ConstantReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Generic\TemplateMixedType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;

class StrictMixedType implements CompoundType
{

public function getReferencedClasses(): array
{
return [];
}

public function accepts(Type $type, bool $strictTypes): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
{
return TrinaryLogic::createFromBoolean(
$acceptingType instanceof MixedType && !$acceptingType instanceof TemplateMixedType
);
}

public function isSuperTypeOf(Type $type): TrinaryLogic
{
return TrinaryLogic::createFromBoolean($type instanceof self);
}

public function isSubTypeOf(Type $otherType): TrinaryLogic
{
return TrinaryLogic::createFromBoolean($otherType instanceof self);
}

public function equals(Type $type): bool
{
return $type instanceof self;
}

public function describe(VerbosityLevel $level): string
{
return 'mixed';
}

public function canAccessProperties(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasProperty(string $propertyName): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): PropertyReflection
{
throw new \PHPStan\ShouldNotHappenException();
}

public function canCallMethods(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasMethod(string $methodName): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getMethod(string $methodName, ClassMemberAccessAnswerer $scope): MethodReflection
{
throw new \PHPStan\ShouldNotHappenException();
}

public function canAccessConstants(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasConstant(string $constantName): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getConstant(string $constantName): ConstantReflection
{
throw new \PHPStan\ShouldNotHappenException();
}

public function isIterable(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isIterableAtLeastOnce(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getIterableKeyType(): Type
{
return $this;
}

public function getIterableValueType(): Type
{
return $this;
}

public function isArray(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isOffsetAccessible(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getOffsetValueType(Type $offsetType): Type
{
return new ErrorType();
}

public function setOffsetValueType(?Type $offsetType, Type $valueType): Type
{
return new ErrorType();
}

public function isCallable(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array
{
return [];
}

public function isCloneable(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function toBoolean(): BooleanType
{
return new BooleanType();
}

public function toNumber(): Type
{
return new ErrorType();
}

public function toInteger(): Type
{
return new ErrorType();
}

public function toFloat(): Type
{
return new ErrorType();
}

public function toString(): Type
{
return new ErrorType();
}

public function toArray(): Type
{
return new ErrorType();
}

public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
{
return TemplateTypeMap::createEmpty();
}

public function getReferencedTemplateTypes(TemplateTypeVariance $positionVariance): array
{
return [];
}

public function traverse(callable $cb): Type
{
return $this;
}

/**
* @param mixed[] $properties
* @return Type
*/
public static function __set_state(array $properties): Type
{
return new self();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protected function getRule(): \PHPStan\Rules\Rule
{
return new AppendedArrayItemTypeRule(
new PropertyReflectionFinder(),
new RuleLevelHelper($this->createReflectionProvider(), true, false, true)
new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false)
);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Arrays/IterableInForeachRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class IterableInForeachRuleTest extends \PHPStan\Testing\RuleTestCase

protected function getRule(): \PHPStan\Rules\Rule
{
return new IterableInForeachRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true));
return new IterableInForeachRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false));
}

public function testCheckWithMaybes(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class NonexistentOffsetInArrayDimFetchRuleTest extends \PHPStan\Testing\RuleTest
protected function getRule(): \PHPStan\Rules\Rule
{
return new NonexistentOffsetInArrayDimFetchRule(
new RuleLevelHelper($this->createReflectionProvider(), true, false, true),
new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false),
true
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class OffsetAccessAssignOpRuleTest extends \PHPStan\Testing\RuleTestCase

protected function getRule(): Rule
{
$ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions);
$ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnions, false);
return new OffsetAccessAssignOpRule($ruleLevelHelper);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class OffsetAccessAssignmentRuleTest extends \PHPStan\Testing\RuleTestCase

protected function getRule(): \PHPStan\Rules\Rule
{
$ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes);
$ruleLevelHelper = new RuleLevelHelper($this->createReflectionProvider(), true, false, $this->checkUnionTypes, false);
return new OffsetAccessAssignmentRule($ruleLevelHelper);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class OffsetAccessValueAssignmentRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new OffsetAccessValueAssignmentRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true));
return new OffsetAccessValueAssignmentRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false));
}

public function testRule(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class UnpackIterableInArrayRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new UnpackIterableInArrayRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true));
return new UnpackIterableInArrayRule(new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false));
}

public function testRule(): void
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Cast/EchoRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class EchoRuleTest extends RuleTestCase
protected function getRule(): Rule
{
return new EchoRule(
new RuleLevelHelper($this->createReflectionProvider(), true, false, true)
new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false)
);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Cast/InvalidCastRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class InvalidCastRuleTest extends \PHPStan\Testing\RuleTestCase
protected function getRule(): \PHPStan\Rules\Rule
{
$broker = $this->createReflectionProvider();
return new InvalidCastRule($broker, new RuleLevelHelper($broker, true, false, true));
return new InvalidCastRule($broker, new RuleLevelHelper($broker, true, false, true, false));
}

public function testRule(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ protected function getRule(): \PHPStan\Rules\Rule
{
return new InvalidPartOfEncapsedStringRule(
new \PhpParser\PrettyPrinter\Standard(),
new RuleLevelHelper($this->createReflectionProvider(), true, false, true)
new RuleLevelHelper($this->createReflectionProvider(), true, false, true, false)
);
}

Expand Down
Loading

0 comments on commit da0b2eb

Please sign in to comment.