klesun / deep-assoc-completion

A phpstorm plugin for associative array key typing and completion
Other
267 stars 17 forks source link

Possible feature: Enum/Const class values autocompletion #207

Open DominikStyp opened 2 years ago

DominikStyp commented 2 years ago

Hi, First of all thanks for the amazing plugin, I can't stop using it. However lately I found out that I would need to support Enum values like this:

    /**
     *
     * @param array {
     *   id: string|null,
     *   access_level: "low" | "medium" | "high",
     *   privacy_level: \App\Enums\ServiceProvider\DocumentPrivacyLevelEnum::getKeys()
     * } $filter
     */
    public function testMe(array $filter = [])
    {
    }

   ....

   $obj->testMe(['access_level' => '...']); // WORKS PERFECTLY FINE!
   $obj->testMe(['privacy_level' => '...']); // doesn't work

Enums that I use are from known Spatie Enums, which have public static method getKeys() which fetches the constants values, but it does not work in the plugin. Is there a way to make it work somehow?

This could be even better if plugin could autocomplete the class and its constants somehow, to not use the strings there but constant values.

klesun commented 2 years ago

Hi. Mixing PSALM syntax with expression syntax this way is not supported. If you want to use typing from both domains, one possible way would be to define it like this:

/**
 * @param $filter = [
 *     "privacy_level" => \App\Enums\ServiceProvider\DocumentPrivacyLevelEnum::getKeys()[$any]
 * ]
 * @param array {
 *   id: string|null,
 *   access_level: "low" | "medium" | "high",
 *   privacy_level: string
 * } $filter
 */
function testMe(array $filter = [])

image image

Though I suspect the real question is whether or not plugin can understand the reflection logic of spatie Enum class. Some time ago there was some support for get_class_vars type inference in the plugin, but it does not seem to work anymore sadly...

Maybe some good person could try investigate and file a PR

DominikStyp commented 2 years ago

hi @klesun thanks for the quick response.

Though I suspect the real question is whether or not plugin can understand the reflection logic of spatie Enum class. Some time ago there was some support for get_class_vars type inference in the plugin, but it does not seem to work anymore

This has not to be a reflection, I would be very glad actually even if the plugin would allow me to to do this, but in terms of class constants autocomplete instead of just strings like this:

 /**
     *
     * @param array {
     *   id: string|null,
     *   access_level: "low" | "medium" | "high",
     *   privacy_level: DocumentPrivacyLevelEnum::LOW | DocumentPrivacyLevelEnum::MEDIUM | DocumentPrivacyLevelEnum::HIGH
     * } $filter
     */
    public function testMe(array $filter = [])
    {
    }
   $obj->testMe(['privacy_level' => Docu.... ]); // autocompletion where the dots are

Maybe some good person could try investigate and file a PR

I would gladly do that if had the knowledge how to write the PHPStorm plugins, even though I can write Java as well as PHP, I have no idea where to start. Do you happen to have any resources, guides or books of how to start?

klesun commented 2 years ago

privacy_level: DocumentPrivacyLevelEnum::LOW | DocumentPrivacyLevelEnum::MEDIUM | DocumentPrivacyLevelEnum::HIGH

Is this a legit PSALM syntax? If not, I don't think it's a good idea to try adding our own customizations to the specification.

I would be very glad actually even if the plugin would allow me to to do this, but in terms of class constants autocomplete instead of just strings

Since you don't seem to be eager to stick to the PSALM syntax, maybe what you want could be achieved with the expression typing like this?

/**
 * @param $filter = [
 *   "id" => ["some_id_123", null][$any],
 *   "access_level" => ["low", "medium", "high"][$any],
 *   "privacy_level" => [
 *     DocumentPrivacyLevelEnum::LOW,
 *     DocumentPrivacyLevelEnum::MEDIUM,
 *     DocumentPrivacyLevelEnum::HIGH,
 *   ][$any]
 * ]
 */
function testMe(array $filter = [])

image

Do you happen to have any resources, guides or books of how to start?

This documentation is pretty useful:

https://plugins.jetbrains.com/docs/intellij/welcome.html

The entry point of the plugin is:

https://github.com/klesun/deep-assoc-completion/blob/master/resources/META-INF/plugin.xml

The code that is supposed to infer the get_class_vars() type is located at:

https://github.com/klesun/deep-assoc-completion/blob/125a67b7e834b73de92b2ca99112466ce2853a63/src/org/klesun/deep_assoc_completion/resolvers/FuncCallRes.java#L220

DominikStyp commented 2 years ago

@klesun thanks for the info about the plugin, I'll dig into that in the free time.

Regarding this example, unfortunately this doesn't work too...


/**
     * @param $filter = [
     *   "id" => ["some_id_123", null][$any],
     *   "access_level" => ["low", "medium", "high"][$any],
     *   "privacy_level" => [
     *     \App\Enums\ServiceProvider\DocumentPrivacyLevelEnum::LOW,
     *     \App\Enums\ServiceProvider\DocumentPrivacyLevelEnum::MEDIUM,
     *     \App\Enums\ServiceProvider\DocumentPrivacyLevelEnum::HIGH,
     *   ][$any]
     * ]
     */
    public function testMe(array $filter = [])
    {
        $filter['privacy_level'] = ... //here autocomplete doesn't work for the specified enum
    }

  $obj->testMe(['privacy_level' => .... ]); // here also autocompletion for the Enum doesn't work

update: it works inside a string only "", is that possible it would be outside the quotes?

klesun commented 2 years ago

is that possible it would be outside the quotes?

That would be a good improvement to the plugin behaviour. I would gladly accept such PR.

You can probably look at https://github.com/klesun/deep-assoc-completion/blob/master/src/org/klesun/deep_assoc_completion/completion_providers/ArgCstPvdr.java for a reference, it's a code that makes constant completion for built-in functions appear in the arguments.