Skip to content

Add new method signature rule#1292

Merged
ondrejmirtes merged 2 commits intophpstan:masterfrom
iluuu1994:feature/method-signature-rule
Dec 8, 2018
Merged

Add new method signature rule#1292
ondrejmirtes merged 2 commits intophpstan:masterfrom
iluuu1994:feature/method-signature-rule

Conversation

@iluuu1994
Copy link
Copy Markdown
Contributor

@iluuu1994 iluuu1994 commented Jul 25, 2018

Closes #532
Closes #729

  • Interfaces
  • Traits
  • Should constructors be ignored?

@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch 3 times, most recently from 91943c0 to 201a3cb Compare July 25, 2018 23:34
@ondrejmirtes
Copy link
Copy Markdown
Member

Hi, it's not gonna be that easy because I still want it to work on Rule classes (see the failed build). I know it isn't exactly right but it's a common pattern. Basically I want to specify the type of the parameter in phpDoc because >I know< what's going to be passed there.

@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from 201a3cb to 3162279 Compare July 26, 2018 07:45
@iluuu1994
Copy link
Copy Markdown
Contributor Author

@ondrejmirtes Don't worry, we can ignore all errors from the Rule class with one simple regex. We don't have to change that code. Although I do think it would be cleaner to actually add an assert or throw a ShouldNotHappenException.

I have some issues with traits at the moment (for some reason the phpDoc types are ignored in traits). I'll see if I can fix that right now.

@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from 3162279 to b410394 Compare July 26, 2018 08:22
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from b410394 to cbaeb24 Compare July 26, 2018 09:00
@ondrejmirtes ondrejmirtes modified the milestones: 0.10, 0.11 Jul 26, 2018
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch 2 times, most recently from cb54430 to 5308c8c Compare July 26, 2018 15:37
@iluuu1994
Copy link
Copy Markdown
Contributor Author

Great, now it suddenly works and I've changed absolutely nothing 😬

@JanTvrdik
Copy link
Copy Markdown
Contributor

You cannot solve #532 without introducing generics first. The Rule interface is an example of that, because it should actually be Rule<in T : Node>. See also #729 (comment) for example.

@iluuu1994
Copy link
Copy Markdown
Contributor Author

@JanTvrdik #532 is not about generics but about covariance and contravariance. We don't need generics for the support that. Sure, because of the introduction of this rule I had to ignore this error:

- '#^Declaration of PHPStan\\Rules\\.*::processNode\(.*\): .* should be compatible with PHPStan\\Rules\\Rule::processNode\(.*\): .*$#'

@iluuu1994
Copy link
Copy Markdown
Contributor Author

@JanTvrdik

Also, I don't think people will really use generics until it's a language feature or something their IDE supports. For example, at our company we're not using the array<KType, VType> syntax because PHPStorm doesn't understand it. I'm not arguing about the usefulness of generics themselves. I just feel like that would make for a horrible IDE experience.

@JanTvrdik
Copy link
Copy Markdown
Contributor

@JanTvrdik #532 is not about generics but about covariance and contravariance.

Yes, but without generics you're missing the key information that is required to decide whether the parameter contravariance is valid. You simply do not have enough data.

@iluuu1994
Copy link
Copy Markdown
Contributor Author

@JanTvrdik

Yes, but without generics you're missing the key information that is required to decide whether the parameter contravariance is valid.

Well, this is gonna break some code. Even if we introduce generics people will have to go and annotate their code with generic parameters. Generics aren't gonna change that.

There's other ways to achieve similar results. You could:

class SomeRule implements Rule
{
    public function processNode(Node $node, Scope $scope): array
    {
        if (!$node instanceof Function_) {
            throw new \InvalidArgumentException();
        }

        // ...
    }
}

Obviously this does not protect you from the calling side as the signature is still the same. But that's really not the point here. The method signature rule is all about keeping the promise of the method signature.

Note that PHP itself has simple forms of covariance and contravariance while lacking generic support.

@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from 5308c8c to 5756e52 Compare July 27, 2018 15:53
@iluuu1994
Copy link
Copy Markdown
Contributor Author

@ondrejmirtes

Can you give me feedback on this PR?

One issue I've had is that the Squiz.Commenting.FunctionComment.InvalidNoReturn rule doesn't let me annotate a return type if all the method does is throw an exception. I created an issue over at squizlabs but it doesn't look like that will be fixed. What do we do in cases like this? I can understand if phpcs:ignore is not an option.

Also, how do you feel about the whole generics issue?

@iluuu1994 iluuu1994 changed the title [Method signature] Add new method signature rule (WIP 🚧) [Method signature] Add new method signature rule Jul 27, 2018
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch 2 times, most recently from 6c80055 to 775c46a Compare July 28, 2018 16:22
@iluuu1994
Copy link
Copy Markdown
Contributor Author

@JanTvrdik

I added support for the %reportMaybes% parameter. This allows you to use parameter covariance up until level 6 when reportMaybes is enabled. After that it's prohibited. Unrelated types will always throw an error.

Does this defuse the situation in your opinion?

@ondrejmirtes
Copy link
Copy Markdown
Member

I'm still a little bit torn about this - people sometimes use phpDocs to override badly documented types of parent classes, therefore breaking LSP on purpose.

@iluuu1994
Copy link
Copy Markdown
Contributor Author

people sometimes use phpDocs to override badly documented types of parent classes, therefore breaking LSP on purpose.

That's definitely a valid argument. However, I don't think we should treat the exception as the rule. You can always ignore such cases or ignore the rule completely if that's happens all over your codebase. Also, only invariant types are reported all the way up to level 6.

@ondrejmirtes ondrejmirtes force-pushed the master branch 3 times, most recently from 5904f1c to 99bb3a9 Compare October 30, 2018 10:54
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from 775c46a to 59b191b Compare November 4, 2018 10:55
@iluuu1994 iluuu1994 changed the title [Method signature] Add new method signature rule Add new method signature rule (WIP 🚧) Nov 4, 2018
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch 4 times, most recently from ac6bbca to 6fc59ee Compare November 7, 2018 14:47
@iluuu1994
Copy link
Copy Markdown
Contributor Author

After fixing all phpDoc issues this finally works with no dirty workarounds 🎉

Copy link
Copy Markdown
Member

@ondrejmirtes ondrejmirtes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this a lot! I was rewriting something at my job yesterday and this rule is something I'd really appreciate :)

I have some suggestions:

  1. You probably missed my comment about better error messages: #1292 (comment)
  2. Method checkParameterCompatibility includes checkReturnTypeCompatibility so it should be renamed, probably to checkMethodCompatibility. You might have to refactor it too because of 1).

@iluuu1994
Copy link
Copy Markdown
Contributor Author

Sorry, I had some personal issues these days. Give me a few days or feel free to take over.

@ondrejmirtes
Copy link
Copy Markdown
Member

No problem, I'll wait 👌 Take care.

@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from df2e2f9 to db14605 Compare December 8, 2018 21:08
@iluuu1994 iluuu1994 force-pushed the feature/method-signature-rule branch from db14605 to 83132ab Compare December 8, 2018 21:20
@iluuu1994
Copy link
Copy Markdown
Contributor Author

@ondrejmirtes This is ready. 🙂

@iluuu1994 iluuu1994 changed the title Add new method signature rule (WIP 🚧) Add new method signature rule Dec 8, 2018
@ondrejmirtes ondrejmirtes merged commit 43122b3 into phpstan:master Dec 8, 2018
@ondrejmirtes
Copy link
Copy Markdown
Member

Perfect! :) Thank you very much.

@iluuu1994 iluuu1994 deleted the feature/method-signature-rule branch December 8, 2018 22:26
@iluuu1994
Copy link
Copy Markdown
Contributor Author

@ondrejmirtes Awesome, thank you! Do we wanna turn on %reportMaybesInMethodSignatures% in strict-rules now? If so I'll create a pull request over there too.

@ondrejmirtes
Copy link
Copy Markdown
Member

Yeah, please do :) I also added a commit here so that the build doesn't break (because of Rule interface implementations): 978f829

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants