Home > Software design >  What is the "Add #[Pure] attribute" inspection in PhpStorm checking for?
What is the "Add #[Pure] attribute" inspection in PhpStorm checking for?

Time:10-07

I've got a very simple FormRequest class in a Laravel project. Two methods, both of which return a simple array that's partially populated by a method, but the IDE treats them differently.

<?php

namespace App\Http\Requests;

class VerifyPhoneNumber extends FormRequest {
    use Support\ValidatesPhoneNumbers;

    public function authorize(): bool {
        return true;
    }

    public function rules(): array {
        return [
            "phone_number" => $this->getPhoneNumberRules(),
            "verify_code" => ["required", "numeric", "max:999999"],
        ];
    }

    public function messages(): array {
        return [
            "phone_number.regex" => $this->getPhoneNumberMessage(),
        ];
    }
}

And the very basic trait methods:

<?php

namespace App\Http\Requests\Support;

trait ValidatesPhoneNumbers {
    protected function getPhoneNumberMessage(): string {
        return __("Some localized error message");
    }

    protected function getPhoneNumberRules(): array {
        return ["regex:/^\ ?1?[2-9][0-9]{5,14}$/", "max:16"];
    }
}

The thing I'm puzzled about is that the IDE inspection complains that I should add the JetBrains\PhpStorm\Pure attribute to the rules() method, but not the messages() method.

The comments in the class definition say:

The attribute marks the function that has no impact on the program state or passed parameters used after the function execution. This means that a function call that resolves to such a function can be safely removed if the execution result is not used in code afterwards.

That doesn't really give me any clues why it treats these two methods differently. If I'm understanding the second sentence correctly, when the result of a "pure" method is unused the IDE will flag usage of the method as unused and recommend its removal.

What is the logic used to determine when this attribute is needed?

CodePudding user response:

If a function only depends on other pure functions, then it is also pure. Since getPhoneNumberRules() just returns a fixed array, it's pure, so rules() is also pure.

But messages() calls getPhoneNumberMessage(), which calls the __() function that can return a different localized message if the location state changes, so it's not pure.

CodePudding user response:

The rules() method has fixed (better say "side effects free") result -- it uses fixed values only. Sure, it calls getPhoneNumberRules() from a trait but it also returns fixed array (always the same). It does not make changes anywhere else (internal state or external storage).

The messages() method calls a method from a trait that calls __() to get translated message... that can come from a different source (a DB, a file) and therefore potentially can throw exceptions if a storage (file/DB) is not readable. The IDE does not know for sure if __() makes changes to a file/DB -- it's not annotated as pure and PhpStorm cannot make such decision from the methods that it uses.


P.S. If this inspection annoys you (which I can understand) then I suggest you just ignore such inspection and lower its severity in PhpStorm Settings to "No highlighting, only fix" (Settings (Preferences on macOS) | Editor | Inspections | PHP | Attributes | '#[Pure]' attribute can be added)

CodePudding user response:

Use this attribute for functions that do not produce any side effects. All such PHP internal functions are already marked in PhpStorm.

#[Pure]
function compare(Foo $a, Foo $b): int
{
    return $a->a <=> $b->b;
}

Source: https://github.com/JetBrains/phpstorm-attributes#pure

As this function only does something within its own it can be called a #[Pure] function and so you know that via PhpStorm.

  • Related