0

I want to determine whether a MethodCall node is inside a certain class constructor. More specifically, I want to know if a method is being called within an exception constructor.

This is the background: A third-party translation service uses static analysis to find translatable strings in my code. It does so by analyzing call to a ::translate() method. It only supports string literals, so I can't pass variables or method calls, for example--except when re-throwing exceptions, where there's no way to know the strings ahead of time. Here's an example:

<?php

class ExampleClass
{
    // I know this string ahead of time.
    const BAD = 'BAD';

    function exampleMethod()
    {
        // Should PASS: I control the string, so I pass it directly.
        $this->translate('Good');

        try {
            $this->throwsAnException();
        } catch (Throwable $e) {
            // Should PASS: I don't "own" the string--but it still has to
            // be passed through the translation system for "reasons"--so
            // the only option is to pass the method call.
            throw new Exception($this->translate($e->getMessage()));
        }

        // Should FAIL: I control the string, so I should pass the literal.
        $bad = 'BAD';
        $this->translate($bad);

        // Should FAIL: Same thing. It's my string, so I should pass the literal.
        $this->translate(self::BAD);
    }
}

I have a (basically) working solution to prohibiting non-string values here: How to determine whether a method argument is a literal/scalar string in PHPStan, even if concatenated. What I still need is to ignore the rule when the node is in a new Exception() call. Does anyone have any ideas?

1
  • This is a nicely asked question, it really is, but it’d be much better to ask it in PHPStan’s GitHub Discussions 😊 Commented Oct 5, 2023 at 19:44

1 Answer 1

0

So your rule is registered to process the MethodCall node which is the translate method call.

You essentially want to "look around" the method call to see if it's inside new Exception.

Currently you need a custom node visitor to set the attribute on the node. Here are the details: https://phpstan.org/blog/preprocessing-ast-for-custom-rules

And please ask in GitHub Discussions next time, you'll get a good answer too and quickly :) https://github.com/phpstan/phpstan/discussions

Sign up to request clarification or add additional context in comments.

1 Comment

Oh! I assumed it would be considered more courteous to ask the question here, first. Thanks, @Ondřej Mirtes. I'll ask it on GitHub next time. 🙂

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.