-
Notifications
You must be signed in to change notification settings - Fork 17
Open
Labels
status: help wantedBacklogBacklogtype: improvementThe issue is about some basic functionality delivered earlier to make it closer to perfectThe issue is about some basic functionality delivered earlier to make it closer to perfect
Description
I don't know whether this is out of scope for this plugin, but it is AFAIK currently the only one detecting the type of untyped closure parameters. I add a little script further below as an example.
To show what I am talking about at first, let me show a little screenshot.
The plugin automatically detects that the argument of the closure must be of type WordBuilder
, provides autocompletion and allows Go To Declaration or Usages.
IMHO, four things are missing to complete this feature.
- Support
Find usage
. As you can see, only the usages ofok()
are found but not forwithLetter()
- Support renaming. Currently, this refactoring is not provided on the autocompleted methods.
- Do not get distracted by outer variables. While autocompletion works in this case
it does not work in this one, because the name of the outer variable is the same as the argument one.
- Detect closure arguments within closure arguments. While
->withWord()
is detected,withLetter()
is not.
Without deeper knowledge, I would guess most of this would be possible with a TypeProvider.
<?php
declare(strict_types=1);
class WordBuilder
{
private string $letters = "";
public function withLetter(string $letter): self
{
$this->letters .= $letter;
return $this;
}
public function ok(): string
{
return $this->letters;
}
}
class SentenceBuilder
{
/** @psalm-var list<string> */
private array $words = [];
/**
* @psalm-param callable(WordBuilder): WordBuilder $mod
*/
public function withWord(callable $mod): self
{
$this->words[] = $mod(new WordBuilder())->ok();
return $this;
}
public function ok(): string
{
return implode(' ', $this->words) . '.';
}
}
class Test
{
public function test_with_and_without_nested_builders(): void
{
echo $this->givenAWord(fn($word) => $word->withLetter("T")->withLetter("e")->withLetter("s")->withLetter("t")) . "\n";
echo $this->givenASentence(
fn($aSentence) => $aSentence
->withWord(fn($word) => $word->withLetter("T")->withLetter("h")->withLetter("i")->withLetter("s"))
->withWord(fn($word) => $word->withLetter("i")->withLetter("s"))
->withWord(fn($word) => $word->withLetter("a"))
->withWord(fn($word) => $word->withLetter("T")->withLetter("e")->withLetter("s")->withLetter("t"))) . "\n";
}
public function test_with_equal_named_variable(): void
{
$word = $this->givenAWord(fn($word) => $word->withLetter("T")->withLetter("e")->withLetter("s")->withLetter("t")) . "\n";
echo $word;
}
/**
* @psalm-param callable(SentenceBuilder): SentenceBuilder $mod
*/
private function givenASentence(callable $mod): string
{
return $mod(new SentenceBuilder())->ok();
}
/**
* @psalm-param callable(WordBuilder): WordBuilder $mod
*/
private function givenAWord(callable $mod): string
{
return $mod(new WordBuilder())->ok();
}
}
(new Test())->test_with_and_without_nested_builders();
(new Test())->test_with_equal_named_variable();
Metadata
Metadata
Assignees
Labels
status: help wantedBacklogBacklogtype: improvementThe issue is about some basic functionality delivered earlier to make it closer to perfectThe issue is about some basic functionality delivered earlier to make it closer to perfect