Skip to content
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

Feature/deprecations #18

Closed
wants to merge 30 commits into from
Closed

Conversation

iluuu1994
Copy link
Contributor

@iluuu1994 iluuu1994 commented May 6, 2018

No description provided.

@ondrejmirtes
Copy link
Member

FYI you can run the build locally and you don't have to wait for Travis 😊 I'd like if you squashed those "fix" commits into the places where the error got created in the first places, for a nicer Git history. Thanks!

@iluuu1994
Copy link
Contributor Author

Haha yeah I usually do that but the phpcs configuration changed since I've made these commits, I'll squash everything once it's working properly.

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes Any idea why some of the tested files are actually run? I've got some echo statements that are actually being printed out? Should I just avoid using echo or is this some other issue?

To explain why, I'm testing deprecated property accesses in some tests and the easiest way to use them was just an echo. I could also just store them in a variable.

@iluuu1994 iluuu1994 force-pushed the feature/deprecations branch from b88079b to 7bf2992 Compare May 6, 2018 16:37
@iluuu1994
Copy link
Contributor Author

@ondrejmirtes Ok, I think this is ready. Let me know if there's anything I need to adjust. 🙂

As we discussed before, this PR does currently not support warnings when using deprecated classes or interfaces in type hints.

@iluuu1994
Copy link
Contributor Author

Any news?

@ondrejmirtes
Copy link
Member

Don't worry, I'll get to it soon, it will be part of 0.10 😊

@iluuu1994
Copy link
Contributor Author

Nice 👍

Sorry, patience is not one of my virtues 😄

Copy link
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.

Also, please add a one-line bullet point to the README 😊 Thanks!

}

$methodCalledOnType = $scope->getType($node->var);
$referencedClasses = $methodCalledOnType->getReferencedClasses();
Copy link
Member

Choose a reason for hiding this comment

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

This should rather use TypeUtils::getDirectClassNames.

}

$propertyAccessedOnType = $scope->getType($node->var);
$referencedClasses = $propertyAccessedOnType->getReferencedClasses();
Copy link
Member

Choose a reason for hiding this comment

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

This should rather use TypeUtils::getDirectClassNames().

if ($node->class instanceof Name) {
$referredClasses[] = (string) $node->class;
} else {
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
Copy link
Member

Choose a reason for hiding this comment

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

There's a missing:

if ($classTypeResult->getType() instanceof ErrorType) {
    return [];
}

Copy link
Member

Choose a reason for hiding this comment

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

Also, the same method could be used for static methods (not skipping $node->name that is not Name).

$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
$scope,
$node->class,
'%s' // We don't care about the error message
Copy link
Member

Choose a reason for hiding this comment

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

Empty string please.


if ($property instanceof DeprecatableReflection && $property->isDeprecated()) {
return [sprintf(
'Access to deprecated static property %s of class %s.',
Copy link
Member

Choose a reason for hiding this comment

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

property $%s

'%s' // We don't care about the error message
);

$referredClasses = $classTypeResult->getReferencedClasses();
Copy link
Member

Choose a reason for hiding this comment

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

$referencedClasses

*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->class instanceof Name) {
Copy link
Member

Choose a reason for hiding this comment

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

Employ RuleLevelHelper::findTypeToCheck instead of skipping

}

return [sprintf(
'Fetching class constant of deprecated class %s.',
Copy link
Member

Choose a reason for hiding this comment

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

Which class constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's only one class constant 🙂

E.g. stdClass::class

Copy link
Member

Choose a reason for hiding this comment

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

IMHO this rule works for all accessed class constants...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Haha yeah sorry. Apparently I'm confused. But that made me notice that we're totally missing deprecations of constants! I'll fix that too.

public static function isScopeDeprecated(Scope $scope): bool
{
$class = $scope->getClassReflection();
if ($class !== null && $class->isDeprecated()) {
Copy link
Member

Choose a reason for hiding this comment

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

We might also be inside a deprecated trait.

@@ -1,6 +1,6 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Deprecations;
namespace PHPStan\Analyzer;
Copy link
Member

Choose a reason for hiding this comment

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

Noo, leave it in the original place 😊

@ondrejmirtes
Copy link
Member

I found a few things during the review. Hopefully you will be able to go through them this week, I plan to release 0.10 the next week 😊 Thanks!

if ($interface->isDeprecated()) {
if (!$class->getNativeReflection()->isAnonymous()) {
$errors[] = sprintf(
'Implementation of deprecated interface %s in class %s.',
Copy link
Member

@ondrejmirtes ondrejmirtes Jun 20, 2018

Choose a reason for hiding this comment

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

What about Class %s implements deprecated interface %s.?

if ($parentClass->isDeprecated()) {
if (!$class->getNativeReflection()->isAnonymous()) {
$errors[] = sprintf(
'Inheritance of deprecated class %s in class %s.',
Copy link
Member

Choose a reason for hiding this comment

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

What about Class %s extends deprecated class %s.?

Copy link
Member

Choose a reason for hiding this comment

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

Also, what about interfaces extending other deprecated interfaces? 😊

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, what about interfaces extending other deprecated interfaces? 😊

That should be handled in the ImplementationOfDeprecatedInterfaceRule. But tests are missing! Haven't thought about that.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think so, you need a rule that processes Interface_::class for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right 🙂
I'll make sure it works!

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes Sure! I'll fix the issues by this weekend then!

@ondrejmirtes
Copy link
Member

Cool, looking forward to that 😊

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes

Is there a way in PHPStan to resolve a class name in a certain scope? Something that supports self, parent, static and so forth? I've implemented the check to parent myself here but it's lacking static and self. Obviously I could extend the function but if there's a built in way I'd rather use that.

Broker::getClass unfortunately doesn't accept a scope.

@ondrejmirtes
Copy link
Member

@iluuu1994 Try Scope::resolveName 😊

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes Knew it was somewhere 😆

Thanks!

@iluuu1994 iluuu1994 force-pushed the feature/deprecations branch from 920f7f4 to 7a8f54b Compare June 23, 2018 13:57
@iluuu1994
Copy link
Contributor Author

@ondrejmirtes That's it!

I'm still unsure if the implementation of the RuleLevelHelper::findTypeToCheck $unionTypeCriteriaCallback is correct in the InstantiationOfDeprecatedClassRule. Please let me know about that.

Other than that, it's ready for another review.

@Majkl578
Copy link
Contributor

Majkl578 commented Jun 23, 2018

Thinking more and more about this, I feel it doesn't really belong to strict-rules.
Using deprecated methods has nothing to do with strictness, and often there is no way around. As an example, consider ORM 2.x vs. ORM 3.0. You can't often simply abandon deprecated code.

@ondrejmirtes
Copy link
Member

Yeah I'm also thinking that this might be better as a separate package, it's also huge amount of code 😊 I really wouldn't want to all of this to go to waste, @iluuu1994 what would you think if I created something like phpstan/phpstan-detect-deprecated and make you an owner? 😊

@iluuu1994
Copy link
Contributor Author

@Majkl578 I don't know, deprecating code does signalize that you should get rid of the dependency sooner or later. Also, both Phan and Psalm have deprecation warnings out of the box.

@ondrejmirtes It probably wouldn't get used quite as much if it requires you to add it manually.

But hey, it's your project 🤷‍♂️ Whatever you see fit is fine.

@ondrejmirtes
Copy link
Member

On the other hand, you can always ignore it using ignoreErrors 😊 I'll think about it tomorrow and review the new changes 😊

@iluuu1994
Copy link
Contributor Author

I mean, again, whatever you think is best is fine. If someone is consciously looking for the extension they are gonna find it. We could also mention it on the main repo so that it's easier to discover.

@Majkl578
Copy link
Contributor

Majkl578 commented Jun 23, 2018

deprecating code does signalize that you should get rid of the dependency sooner or later.

As said earlier, not all deprecations are fixable or avoidable.

It probably wouldn't get used quite as much if it requires you to add it manually.

This is kinda selfish, heh. It would be used by people who are interested, not forcibly be people who are not. (And trust me, there is a LOT of such consumers, like Symfony bundles that are supporting SF 2.x + 3.x + 4.x simultaneously).

If someone is consciously looking for the extension they are gonna find it. We could also mention it on the main repo so that it's easier to discover.

This is the correct assumption.

@iluuu1994
Copy link
Contributor Author

This is kinda selfish, heh. It would be used by people who are interested, not forcibly be people who are not.

That's hardly what I meant. I was my assuming the new deprecation rules add value to the majority of users of this repository (which might be wrong, we can argue about that). By your logic every new rule has to be opt-in because you didn't specifically enable it.

@Majkl578
Copy link
Contributor

Well, even then, I can only repeat myself:

I feel it doesn't really belong to strict-rules.
Using deprecated methods has nothing to do with strictness


By your logic every new rule has to be opt-in because you didn't specifically enable it.

Absolutely not, and please don't question my logic, I never said anthing like that.

@ondrejmirtes
Copy link
Member

@iluuu1994 This is really awesome body of work! 😊 I'm gonna create an extra package for it and feature it in phpstan/phpstan release notes, README and also in the article, so don't worry, people will know about it 😊

@ondrejmirtes
Copy link
Member

@iluuu1994 BTW one more thing that should be changed but we can do that in the new repo: When returning error messages, you're using the original class/function/method names as mentioned in the code. You should use ->getName() reported by reflection in order to:

  • Have correct character case - foo vs. fOO
  • Account for class aliases (report the original name instead of the use alias)
  • In case of constants, methods and properties, use declaring class name because the element could have been accessed on a child class or something...

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes Sure! Let me know when you created the repository so I can migrate the code.

@ondrejmirtes
Copy link
Member

@iluuu1994 I've sent you an invite to the repo https://github.com/phpstan/phpstan-deprecation-rules 😊 There's a basic skeleton ready. Let me know once the code is there so I can set up Travis CI.

@iluuu1994
Copy link
Contributor Author

@ondrejmirtes The code is ready, you can set up Travis CI 😊

In the meantime I'll adjust the rules to use the reflection name for reporting errors.

@ondrejmirtes
Copy link
Member

I fixed the problem with isAnonymous: phpstan/phpstan-deprecation-rules@2ac49f5 Feel free to fix the tests if you don't want to report anything in the deprecated scope.

@iluuu1994
Copy link
Contributor Author

Awesome! The rule now checks for a deprecated scope as well. Didn't think of anonymous classes when writing that rule.

@ondrejmirtes
Copy link
Member

OK, closing the PR here, we can continue the discussion over at the new repo 😊 BTW I'm gonna tag 0.10 there some time tonight, so don't be surprised 😊

@iluuu1994
Copy link
Contributor Author

Sure, thanks man!

@Majkl578
Copy link
Contributor

Already added this to Doctrine Migrations and it looks great! 🎉

See doctrine/migrations#739.

@iluuu1994
Copy link
Contributor Author

@Majkl578 Nice! Glad to hear!

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