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

Introduce IgnoreErrorExtension #3783

Draft
wants to merge 1 commit into
base: 2.1.x
Choose a base branch
from
Draft

Conversation

ruudk
Copy link
Contributor

@ruudk ruudk commented Jan 13, 2025

This allows for more flexibility in ignoring errors.

Some use cases:

  • Ignore missingType.iterableValue on controller actions:
    Rule: when the method is public and it has #[Route] attribute or the
    class has #[AsController] attribute.
  • Ignore should return int but returns int|null on getId for entities.
    Rule: class needs to have #[Entity] attribute.
  • Ignore never returns null so it can be removed from the return type
    Rule: method needs to have #[GraphQL\Field] attribute.
  • Enforce missingCheckedExceptionInThrows partially, only for specific classes.

This idea came from phpstan/phpstan#11134

Note

@ondrejmirtes Before I continue with adding tests and improving things, I would first like to know if agree with this functionality.

@LoogleCZ
Copy link

LoogleCZ commented Jan 14, 2025

Hi,

this is exactly what I'm looking for right now as I'm working on Magento 2 projects when I'm bit of forced into following error:

Method Foo\Bar\Plugin\SomeClass::aroundBuildOutputDataArray() has parameter $dataObjectType with no type specified.
         🪪  missingType.parameter

I do not want to ignore all missingType.parameter errors in Method Foo\Bar\Plugin\SomeClass as suggested in comment, but I'd appreciate a way I can determine when the error will be filtered out (In my case, it will be all plugin methods, so class namespace will contain Plugin and method name will start with around/before/after with first argument strongly typed to some existing class).

I'd use this proposed feature or I can use configuration with something like this:

parameters:
	ignoreErrors:
		-
			message: '#^Method [a-zA-Z0-9\\_]+\\Plugin\\[a-zA-Z0-9\\_]+\:\:(before|after|around)[a-zA-Z0-9_-]+\(\) has parameter \$[a-zA-Z0-9_-]* with no type specified#'
			identifier: missingType.parameter
			path: */Plugin/*

And for the requirement to have strongly typed first argument and ignore error based on that - I can then create custom rule to check this condition. Maybe you can do that too in your case.

@ruudk
Copy link
Contributor Author

ruudk commented Jan 15, 2025

@LoogleCZ Yes, with this extension you would be able to filter errors based on their class, namespace, if they use an attribute, if this extend from some base class, etc... Curious what Ondrej thinks about it 😊

@ondrejmirtes
Copy link
Member

Yeah, this would be a nice addition. But there's a lot of details that we need to get right (because ignoring errors is one of the most popular and most widely used PHPStan feature!).

Some notes I have after thinking about this:

  1. I'd avoid "filter" in the name. This should be "IgnoreErrorsExtension".
  2. We have to think about when it makes sense to apply it. There are different shortcomings to different places. For example, does an error first go through ignoreErrors (config) and only after that through the registered extensions?
  3. Do we pass Error or RuleError to the extension? I'm leaning towards Error for many reasons. For example, it'd be great if errors, even when eventually filtered out, would still be part of the result cache. Changing an IgnoreErrorsExtension would mean we don't need to invalidate the result cache. Also, ErrorFormatter works with Error.
  4. Don't forget to also apply IgnoreErrorsExtension to errors produced by CollectedDataNode rules (in AnalyserResultFinalizer).

@ruudk
Copy link
Contributor Author

ruudk commented Jan 23, 2025

  1. I'd avoid "filter" in the name. This should be "IgnoreErrorsExtension".

Sure

  1. We have to think about when it makes sense to apply it. There are different shortcomings to different places. For example, does an error first go through ignoreErrors (config) and only after that through the registered extensions?

If we would first want to process the ignoreErrors, then the current place where I call the extension does not make sense. How would we be able to get the Node at the ignoreErrors stage? I think that information is not part of the Error, right?

Is it even possible to put the Node in the Error, and restore that from the result cache?

  1. Do we pass Error or RuleError to the extension? I'm leaning towards Error for many reasons. For example, it'd be great if errors, even when eventually filtered out, would still be part of the result cache. Changing an IgnoreErrorsExtension would mean we don't need to invalidate the result cache. Also, ErrorFormatter works with Error.

Sure, we can first call the RuleErrorTransformer and then pass the Error to the filter.

  1. Don't forget to also apply IgnoreErrorsExtension to errors produced by CollectedDataNode rules (in AnalyserResultFinalizer).

Will take care of this later once we iron out 2 + 3 😉

@ondrejmirtes
Copy link
Member

Yeah, if you need to access Node and Scope and not just stuff that's available on Error then my whole argument about result cache is moot.

@ondrejmirtes
Copy link
Member

So to summarize:

  1. Rename the extension so that it has "IgnoreError" in the name.
  2. Call it after transforming from RuleError to Error.
  3. Don't forget about calling in on CollectedDataNode rule errors.

Thank you!

This allows for more flexibility in ignoring errors.

Some use cases:

* Ignore `missingType.iterableValue` on controller actions:
  Rule: when the method is public and it has `#[Route]` attribute or the
        class has `#[AsController]` attribute.
* Ignore `should return int but returns int|null` on `getId` for entities.
  Rule: class needs to have `#[Entity]` attribute.
* Ignore `never returns null so it can be removed from the return type`
  Rule: method needs to have `#[GraphQL\Field]` attribute.
* Enforce missingCheckedExceptionInThrows partially, only for specific classes.
@ruudk ruudk force-pushed the rule-error-filter branch from 702d577 to f7021e9 Compare January 24, 2025 08:40
@ruudk ruudk changed the title Introduce RuleErrorFilterExtension Introduce IgnoreErrorExtension Jan 24, 2025
@ruudk
Copy link
Contributor Author

ruudk commented Jan 24, 2025

I pushed the requested changes, please have a look when you have time. When you think it looks OK, I will continue with adding tests and tweaking things.

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