rule idea: disallow some types from being used as parameter type and/or return types
I have 2 use cases for that in my (Symfony) projects:
- I have a few services for which I definitely want usages to rely on the interface, because the interface autowiring would inject a decorated instance (performing some caching). In an open-source bundle, I would register the concrete implementation using a non-FQCN id so that it is not exposed to the Symfony autowiring. But in private projects, relying on the PSR-4 discovery feature makes DX much better so I'd rather avoid having to do special cases (and ensuring that PSR-4 discovery used for other classes does not re-register those classes). Detecting parameters typed with the concrete implementation for those special cases during the phpstan analysis would still prevent bad usages without the drawbacks on DX.
\Symfony\Component\Translation\TranslatableMessageimplements both\Symfony\Contracts\Translation\TranslatableInterfaceandStringable. The correct usage to get the translated value is$translatableMessage->trans($this->translator)(i.e. using the TranslatableInterface API). However, due to being Stringable, phpstan won't fail on$this->translator->trans($translatableMessage)(and that translation will work if the TranslatableMessage contains a key with no parameters, making it potentially harder to notice that this is broken when the TranslatableMessage object expects to use some parameters or a non-default domain). by forbidding to use a return type ofTranslatableMessage(forcing methods to use the interface as their return type instead), we make sure phpstan will report errors in case of invalid usages ($this->translator->trans($translatableInterface)will report an error saying a string is expected but TranslatableInterface is provided)
I'm not sure I fully understand the idea, but you can allow types in parameters with directives like allowParamsInAllowed and allowParamsAnywhere. They also support "type strings", they are parsed with the PHPStan's parser so you can use anything PHPStan supports, including classes, see the docs (the typeString is described at the bottom of the page). Maybe that would help you?
Checking return type as such is indeed not supported yet, but if you disallow the class or interface, it should be flagged as well when used as return type.
Let me know if any of that would help, or not :-)
But I don't want to forbid using the TranslatableMessage class entirely. I only want to forbid defining a function/method using it as it return type. That same function can perfectly use TranslatableMessage as the class being instantiated to satisfy the TranslatableInterface return type (and this will indeed be the case in 95% of such functions btw).
allowParamsInAllowed seems to be a configuration setting of the disallowedMethodCalls feature. So this does not match my need. What I want to have is a disallowedTypes feature (or separate disallowedParameterTypes and disallowedReturnTypes features) that checks method definitions.
Thanks for further explaining the idea.
So if I understand it hopefully correctly now, given the code like this:
class SomeClass implements SomeInterface {}
function foo(SomeClass $param): void // error because of case 1 below
{
new SomeClass; // no error
}
function bar(): SomeClass // error because of case 2 below
{
return new SomeClass; // no error
}
function barButReturnsInterface(): SomeInterface
{
return new SomeClass; // no error
}
// no errors
new SomeClass;
echo SomeClass:class;
anotherFunction(new SomeClass);
you'd like to mark SomeClass as "disallowed" but have it flagged only when used as
- a parameter type in the signature of the
foofunction (linefunction foo(SomeClass $param): void) and nowhere else for thedisallowedParameterTypesfeature - a return type in the
barfunction signature (linefunction bar(): SomeClass) and nowhere else for thedisallowedReturnTypesfeature - both the cases 1. and 2. for the combined
disallowedTypesfeature
Do I understand it correctly?
yes, exactly.