Skip to content

Incorrect return type for Illuminate\Console\Concerns\HasParameters::getOptions() #60723

Description

@wimski

Laravel Version

13.19.0

PHP Version

8.5.8

Database Driver & Version

No response

Description

Illuminate\Console\Concerns\HasParameters::getOptions() has the following return type as defined by a docblock annotation:

    /**
     * Get the console command options.
     *
     * @return (InputOption|array{
     *    0: non-empty-string,
     *    1?: string|non-empty-array<string>,
     *    2?: int-mask-of<InputOption::VALUE_*>,
     *    3?: string,
     *    4?: mixed,
     *    5?: list<string|Suggestion>|\Closure(CompletionInput, CompletionSuggestions): list<string|Suggestion>
     * })[]
     */

https://github.com/laravel/framework/blob/13.x/src/Illuminate/Console/Concerns/HasParameters.php#L56-L67

If the output of this method is an array, then the output will be used to feed the method Symfony\Component\Console\Command\Command::addOption() which has the following signature:

public function addOption(
    string $name,
    string|array|null $shortcut = null,
    ?int $mode = null,
    string $description = '',
    mixed $default = null,
    array|\Closure $suggestedValues = [],
): static

https://github.com/symfony/symfony/blob/8.2/src/Symfony/Component/Console/Command/Command.php#L434

Symfony accepts null for the shortcut argument, but Laravel says it has to be string|non-empty-array<string> without the null option. So a null value is valid and will work at runtime, but static analysis will complain (rightfully so).

Steps To Reproduce

  1. Create a console command class.
  2. Add the getOptions method returning an entry with the shortcut value set to null.
  3. Run static analysis.

Example

Command

class MyCommand extends Command
{
    protected function getOptions(): array
    {
        return [
            ['name', null, InputOption::VALUE_OPTIONAL, 'description'],
        ];
    }
}

Output

 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   app/Console/Commands/MyCommand.php                                                                                                                                  
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    5    Method App\Console\Commands\MyCommand::getOptions() should return array<array{0: non-empty-string, 1?: non-empty-array<string>|string, 2?: int<0, 31>, 3?: string, 4?: mixed, 5?:
         (Closure(Symfony\Component\Console\Completion\CompletionInput, Symfony\Component\Console\Completion\CompletionSuggestions): list<string|Symfony\Component\Console\Completion
         \Suggestion>)|list<string|Symfony\Component\Console\Completion\Suggestion>}|Symfony\Component\Console\Input\InputOption> but returns array{array{'name', null, 4, 'description'}}.                                                                                               
         🪪  return.type                                                                                                                                                                      
         💡  Type #1 from the union: Offset 1 (non-empty-array<int|string, string>|string) does not accept type null: Type #1 from the union: null is empty.                                  
 ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions