spaze / phpstan-disallowed-calls

PHPStan rules to detect disallowed method & function calls, constant, namespace, attribute & superglobal usages
MIT License
255 stars 17 forks source link

disallowedMethodCalls should also be triggered on inherited classes #208

Closed verfriemelt-dot-org closed 1 year ago

verfriemelt-dot-org commented 1 year ago

i'd like to be strict in my codebase about doctrines magic methods. given this configuration:

  disallowedMethodCalls:
    -
      method: 'Doctrine\ORM\EntityRepository::find*()'
      message: 'to not use magic find*() methods'
      errorTip: 'add method to interface instead!'
      allowIn:
        - src/Repository/*
        - tests/*

i'd like to get all calls to FooRepository::findOneBy() is there a way to disallow all calls to every child of EntityRepository?

also if a repository will implements the actual method, it would be nice to not to trigger the error.

class FooRepository extends EntityRepository {
   public function findBySpecificThing() {
   }
}

$repo = new FooRepository();
// this should not trigger an error upon calling
$repo->findBySpecificThing();
// this should trigger an error
$repo->findBy([ ... ]);
spaze commented 1 year ago

I believe this is exactly how it works but maybe I'd need more info.

Given a code like this that somehow resembles what you have, hopefully:

<?php
class Foo
{
    public function findFoo(): void {}
}

class Bar extends Foo
{
    public function findFood(): void {}
}

$bar = new Bar;
$bar->findFoo();

$bar = new Bar;
$bar->findFood();

and a configuration like

    disallowedMethodCalls:
        -
            method: 'Foo::find*()'
            message: 'to not use magic find*() methods'
            errorTip: 'add method to interface instead!'

Then this is the error I get:

 ------ ---------------------------------------------------------------------------------------------------------------------------------
  Line   Foo.php
 ------ ---------------------------------------------------------------------------------------------------------------------------------
  13     Calling Foo::findFoo() (as Bar::findFoo()) is forbidden, to not use magic find*() methods [Foo::findFoo() matches Foo::find*()]
         💡 add method to interface instead!
 ------ ---------------------------------------------------------------------------------------------------------------------------------

findFoo is declared on Foo but called on Bar and is reported as an error. findFood is not reported because it's declared on Bar.

If you add findFoo to Bar

class Bar extends Foo
{
    public function findFoo(): void {}
    public function findFood(): void {}
}

then no error is reported. Is an error in this case what you'd like to see?

verfriemelt-dot-org commented 1 year ago

argh, sorry.

the @method attributes screwed me over :(

they count towards the method is defined within the child class. and since they are added by default in our project, this caused the confusion :(

sorry for wasting your time and thank you for your effort and for this project :)

spaze commented 1 year ago

Not a problem :-) Thanks for confirming the bug was elsewhere 😜 Let me know if you got more questions or bugs. Or even "bugs" :-)