Skip to content

Allow togging discoveringSymbols tip #3929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ rules:
- PHPStan\Rules\Classes\ClassConstantRule
- PHPStan\Rules\Classes\DuplicateDeclarationRule
- PHPStan\Rules\Classes\EnumSanityRule
- PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule
- PHPStan\Rules\Classes\ExistingClassesInEnumImplementsRule
- PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule
- PHPStan\Rules\Classes\ExistingClassInTraitUseRule
- PHPStan\Rules\Classes\InstantiationRule
- PHPStan\Rules\Classes\InstantiationCallableRule
- PHPStan\Rules\Classes\InvalidPromotedPropertiesRule
- PHPStan\Rules\Classes\LocalTypeAliasesRule
Expand Down Expand Up @@ -113,27 +108,67 @@ services:
class: PHPStan\Rules\Classes\ExistingClassInClassExtendsRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\ExistingClassesInEnumImplementsRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\ExistingClassInInstanceOfRule
tags:
- phpstan.rules.rule
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\ExistingClassInTraitUseRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\InstantiationRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule
tags:
- phpstan.rules.rule
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Functions\CallToNonExistentFunctionRule
tags:
- phpstan.rules.rule
arguments:
checkFunctionNameCase: %checkFunctionNameCase%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Constants\OverridingConstantRule
Expand Down Expand Up @@ -165,13 +200,15 @@ services:
- phpstan.rules.rule
arguments:
checkFunctionNameCase: %checkFunctionNameCase%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Namespaces\ExistingNamesInUseRule
tags:
- phpstan.rules.rule
arguments:
checkFunctionNameCase: %checkFunctionNameCase%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Properties\AccessPropertiesRule
Expand All @@ -182,6 +219,8 @@ services:
class: PHPStan\Rules\Properties\AccessStaticPropertiesRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Properties\ExistingClassesInPropertiesRule
Expand All @@ -190,6 +229,7 @@ services:
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
checkThisOnly: %checkThisOnly%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Functions\FunctionCallableRule
Expand Down
9 changes: 8 additions & 1 deletion conf/config.level1.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ parameters:

rules:
- PHPStan\Rules\Classes\UnusedConstructorParametersRule
- PHPStan\Rules\Constants\ConstantRule
- PHPStan\Rules\Functions\UnusedClosureUsesRule
- PHPStan\Rules\Variables\EmptyRule
- PHPStan\Rules\Variables\IssetRule
- PHPStan\Rules\Variables\NullCoalesceRule

services:
-
class: PHPStan\Rules\Constants\ConstantRule
tags:
- phpstan.rules.rule
arguments:
discoveringSymbolsTip: %tips.discoveringSymbols%
3 changes: 3 additions & 0 deletions conf/config.level2.neon
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ services:
class: PHPStan\Rules\PhpDoc\RequireExtendsCheck
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\PhpDoc\RequireImplementsDefinitionTraitRule
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
discoveringSymbolsTip: %tips.discoveringSymbols%
tags:
- phpstan.rules.rule

Expand All @@ -101,6 +103,7 @@ services:
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
checkMissingVarTagTypehint: %checkMissingVarTagTypehint%
discoveringSymbolsTip: %tips.discoveringSymbols%
tags:
- phpstan.rules.rule
-
Expand Down
7 changes: 7 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ parameters:
usePathConstantsAsConstantString: false
rememberPossiblyImpureFunctionValues: true
tips:
discoveringSymbols: true
treatPhpDocTypesAsCertain: true
tipsOfTheDay: true
reportMagicMethods: false
Expand Down Expand Up @@ -888,24 +889,28 @@ services:
globalTypeAliases: %typeAliases%
checkMissingTypehints: %checkMissingTypehints%
checkClassCaseSensitivity: %checkClassCaseSensitivity%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\MethodTagCheck
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
checkMissingTypehints: %checkMissingTypehints%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\MixinCheck
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
checkMissingTypehints: %checkMissingTypehints%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Classes\PropertyTagCheck
arguments:
checkClassCaseSensitivity: %checkClassCaseSensitivity%
checkMissingTypehints: %checkMissingTypehints%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\Comparison\ConstantConditionRuleHelper
Expand Down Expand Up @@ -1005,6 +1010,7 @@ services:
class: PHPStan\Rules\Methods\StaticMethodCallCheck
arguments:
checkFunctionNameCase: %checkFunctionNameCase%
discoveringSymbolsTip: %tips.discoveringSymbols%
reportMagicMethods: %reportMagicMethods%

-
Expand Down Expand Up @@ -1096,6 +1102,7 @@ services:
checkExplicitMixed: %checkExplicitMixed%
checkImplicitMixed: %checkImplicitMixed%
checkBenevolentUnionTypes: %checkBenevolentUnionTypes%
discoveringSymbolsTip: %tips.discoveringSymbols%

-
class: PHPStan\Rules\UnusedFunctionParametersCheck
Expand Down
1 change: 1 addition & 0 deletions conf/parametersSchema.neon
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ parametersSchema:
inferPrivatePropertyTypeFromConstructor: bool()

tips: structure([
discoveringSymbols: bool()
treatPhpDocTypesAsCertain: bool()
])
tipsOfTheDay: bool()
Expand Down
15 changes: 8 additions & 7 deletions src/PhpDoc/StubValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,23 @@ private function getRuleRegistry(Container $container): RuleRegistry
$genericCallableRuleHelper = $container->getByType(GenericCallableRuleHelper::class);
$methodTagTemplateTypeCheck = $container->getByType(MethodTagTemplateTypeCheck::class);
$mixinCheck = $container->getByType(MixinCheck::class);
$methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true);
$propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true);
$discoveringSymbolsTip = $container->getParameter('tips')['discoveringSymbols'];
$methodTagCheck = new MethodTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true, $discoveringSymbolsTip);
$propertyTagCheck = new PropertyTagCheck($reflectionProvider, $classNameCheck, $genericObjectTypeCheck, $missingTypehintCheck, $unresolvableTypeHelper, true, true, $discoveringSymbolsTip);
$reflector = $container->getService('stubReflector');
$relativePathHelper = $container->getService('simpleRelativePathHelper');
$assertRuleHelper = $container->getByType(AssertRuleHelper::class);
$conditionalReturnTypeRuleHelper = $container->getByType(ConditionalReturnTypeRuleHelper::class);

$rules = [
// level 0
new ExistingClassesInClassImplementsRule($classNameCheck, $reflectionProvider),
new ExistingClassesInInterfaceExtendsRule($classNameCheck, $reflectionProvider),
new ExistingClassInClassExtendsRule($classNameCheck, $reflectionProvider),
new ExistingClassInTraitUseRule($classNameCheck, $reflectionProvider),
new ExistingClassesInClassImplementsRule($classNameCheck, $reflectionProvider, $discoveringSymbolsTip),
new ExistingClassesInInterfaceExtendsRule($classNameCheck, $reflectionProvider, $discoveringSymbolsTip),
new ExistingClassInClassExtendsRule($classNameCheck, $reflectionProvider, $discoveringSymbolsTip),
new ExistingClassInTraitUseRule($classNameCheck, $reflectionProvider, $discoveringSymbolsTip),
new ExistingClassesInTypehintsRule($functionDefinitionCheck),
new \PHPStan\Rules\Functions\ExistingClassesInTypehintsRule($functionDefinitionCheck),
new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, true, false),
new ExistingClassesInPropertiesRule($reflectionProvider, $classNameCheck, $unresolvableTypeHelper, $phpVersion, true, false, $discoveringSymbolsTip),
new OverridingMethodRule(
$phpVersion,
new MethodSignatureRule($phpClassReflectionExtension, true, true),
Expand Down
13 changes: 9 additions & 4 deletions src/Rules/Classes/ExistingClassInClassExtendsRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ final class ExistingClassInClassExtendsRule implements Rule
public function __construct(
private ClassNameCheck $classCheck,
private ReflectionProvider $reflectionProvider,
private bool $discoveringSymbolsTip,
)
{
}
Expand All @@ -42,15 +43,19 @@ public function processNode(Node $node, Scope $scope): array
}
if (!$this->reflectionProvider->hasClass($extendedClassName)) {
if (!$scope->isInClassExists($extendedClassName)) {
$messages[] = RuleErrorBuilder::message(sprintf(
$errorBuilder = RuleErrorBuilder::message(sprintf(
'%s extends unknown class %s.',
$currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class',
$extendedClassName,
))
->identifier('class.notFound')
->nonIgnorable()
->discoveringSymbolsTip()
->build();
->nonIgnorable();

if ($this->discoveringSymbolsTip) {
$errorBuilder->discoveringSymbolsTip();
}

$messages[] = $errorBuilder->build();
}
} else {
$reflection = $this->reflectionProvider->getClass($extendedClassName);
Expand Down
15 changes: 10 additions & 5 deletions src/Rules/Classes/ExistingClassInInstanceOfRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function __construct(
private ReflectionProvider $reflectionProvider,
private ClassNameCheck $classCheck,
private bool $checkClassCaseSensitivity,
private bool $discoveringSymbolsTip,
)
{
}
Expand Down Expand Up @@ -69,12 +70,16 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$errorBuilder = RuleErrorBuilder::message(sprintf('Class %s not found.', $name))
->identifier('class.notFound')
->line($class->getStartLine());

if ($this->discoveringSymbolsTip) {
$errorBuilder->discoveringSymbolsTip();
}

return [
RuleErrorBuilder::message(sprintf('Class %s not found.', $name))
->identifier('class.notFound')
->line($class->getStartLine())
->discoveringSymbolsTip()
->build(),
$errorBuilder->build(),
];
}

Expand Down
13 changes: 9 additions & 4 deletions src/Rules/Classes/ExistingClassInTraitUseRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ final class ExistingClassInTraitUseRule implements Rule
public function __construct(
private ClassNameCheck $classCheck,
private ReflectionProvider $reflectionProvider,
private bool $discoveringSymbolsTip,
)
{
}
Expand Down Expand Up @@ -64,11 +65,15 @@ public function processNode(Node $node, Scope $scope): array
foreach ($node->traits as $trait) {
$traitName = (string) $trait;
if (!$this->reflectionProvider->hasClass($traitName)) {
$messages[] = RuleErrorBuilder::message(sprintf('%s uses unknown trait %s.', $currentName, $traitName))
$errorBuilder = RuleErrorBuilder::message(sprintf('%s uses unknown trait %s.', $currentName, $traitName))
->identifier('trait.notFound')
->nonIgnorable()
->discoveringSymbolsTip()
->build();
->nonIgnorable();

if ($this->discoveringSymbolsTip) {
$errorBuilder->discoveringSymbolsTip();
}

$messages[] = $errorBuilder->build();
} else {
$reflection = $this->reflectionProvider->getClass($traitName);
if ($reflection->isClass()) {
Expand Down
13 changes: 9 additions & 4 deletions src/Rules/Classes/ExistingClassesInClassImplementsRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class ExistingClassesInClassImplementsRule implements Rule
public function __construct(
private ClassNameCheck $classCheck,
private ReflectionProvider $reflectionProvider,
private bool $discoveringSymbolsTip,
)
{
}
Expand All @@ -45,15 +46,19 @@ public function processNode(Node $node, Scope $scope): array
$implementedClassName = (string) $implements;
if (!$this->reflectionProvider->hasClass($implementedClassName)) {
if (!$scope->isInClassExists($implementedClassName)) {
$messages[] = RuleErrorBuilder::message(sprintf(
$errorBuilder = RuleErrorBuilder::message(sprintf(
'%s implements unknown interface %s.',
$currentClassName !== null ? sprintf('Class %s', $currentClassName) : 'Anonymous class',
$implementedClassName,
))
->identifier('interface.notFound')
->nonIgnorable()
->discoveringSymbolsTip()
->build();
->nonIgnorable();

if ($this->discoveringSymbolsTip) {
$errorBuilder->discoveringSymbolsTip();
}

$messages[] = $errorBuilder->build();
}
} else {
$reflection = $this->reflectionProvider->getClass($implementedClassName);
Expand Down
13 changes: 9 additions & 4 deletions src/Rules/Classes/ExistingClassesInEnumImplementsRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class ExistingClassesInEnumImplementsRule implements Rule
public function __construct(
private ClassNameCheck $classCheck,
private ReflectionProvider $reflectionProvider,
private bool $discoveringSymbolsTip,
)
{
}
Expand All @@ -42,15 +43,19 @@ public function processNode(Node $node, Scope $scope): array
$implementedClassName = (string) $implements;
if (!$this->reflectionProvider->hasClass($implementedClassName)) {
if (!$scope->isInClassExists($implementedClassName)) {
$messages[] = RuleErrorBuilder::message(sprintf(
$errorBuilder = RuleErrorBuilder::message(sprintf(
'Enum %s implements unknown interface %s.',
$currentEnumName,
$implementedClassName,
))
->identifier('interface.notFound')
->nonIgnorable()
->discoveringSymbolsTip()
->build();
->nonIgnorable();

if ($this->discoveringSymbolsTip) {
$errorBuilder->discoveringSymbolsTip();
}

$messages[] = $errorBuilder->build();
}
} else {
$reflection = $this->reflectionProvider->getClass($implementedClassName);
Expand Down
Loading
Loading