New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow @var annotations over more statements #1916
Comments
|
if (preg_match('/dummy/', 'dummy', $matches, PREG_OFFSET_CAPTURE)) {
// ...
} No matter where you put Allowing |
That's down to how it's defined in the callmap, I believe. |
It's defined simply as This works, but is less than ideal: if (preg_match('/dummy/', 'dummy', $matches, PREG_OFFSET_CAPTURE)) {
/** @var array<array{string, int}> $matches */
[[$match, $offset]] = $matches;
// ...
} |
I think the idea of parameter-mapped types definition has been discussed elsewhere- @muglug, is there a way around this that doesn't require implementing parameter-mapped types ? |
either static const type inheritance, or inline var on method/function params would be nice: https://psalm.dev/r/f9511a4340 https://3v4l.org/q93Ce <?php
/**
* @template T as array<string, scalar|array|object|null>
*/
abstract class Foo {
/**
* @param array<int, key-of<T>>
*/
const NULLABLES = [];
/**
* @param T $data
*/
public function __construct(array $data) {
foreach ($data as $k => $v) {
$this->$k = $v;
}
}
/**
* @template K as key-of<T>
*
* @param K $k
*
* @return T[K]
*/
public function __get(string $k) {
/**
* @var T[K]
*/
return $this->$k;
}
/**
* @template K as key-of<T>
*
* @param K $k
* @param T[K] $v
*/
public function __set(string $k, $v) : void {
$this->$k = $v;
}
public function __unset(string $k) : void {
if ( ! in_array(
$k,
/**
* @var array<int, key-of<T>>
*/
static::NULLABLES,
true
)) {
throw new InvalidArgumentException(sprintf('%s::$%s is not nullable!', static::class, $k));
}
$this->$k = null;
}
}
/**
* @template-extends Foo<array{baz:string|null}>
*
* @property string|null $baz
*/
class Bar extends Foo {
const NULLABLES = ['baz'];
/**
* @var string|null
*/
protected $baz;
}
/**
* @template-extends Foo<array{baz:string|null}>
*
* @property string $baz
*/
class Bat extends Foo {
const NULLABLES = [];
/**
* @var string
*/
protected $baz;
}
$a = new Bar(['baz' => 'with a string']);
$b = new Bar(['baz' => null]);
$c = new Bar(['baz' => 'this should not be here']);
$d = new Bat(['baz' => 'unsetting this will fail']);
unset($c->baz);
echo var_export($a->baz, true), "\n", var_export($b->baz, true), "\n", var_export($c->baz, true);
unset($d->baz); |
For the few cases where this is needed a possible workaround is to put a semicolon after the doc comment, then it's taken into account: https://psalm.dev/r/29441019f5 PHP seems to ignore empty statements so doing this should be ok (although some CS tools might complain). |
I found these snippets: https://psalm.dev/r/29441019f5<?php
function example(string $s): void
{
if (preg_match('{foo-(\w+)}', $s, $m)) {
/** @var array{string, string} $m */
takesString($m[1]);
}
}
function exampleWithSemicolon(string $s): void
{
if (preg_match('{foo-(\w+)}', $s, $m)) {
/** @var array{string, string} $m */;
takesString($m[1]); // now this works
}
}
function takesString(string $s): void
{
}
|
@muglug Do you have some hint to share on this? Where should I look to begin? I suppose #1111 can be handled at the same time I see some statements that could benefit from this:
|
@orklah the |
In order to properly annotate the $text = '
foobar
foobaz
fooqux
foobop
';
preg_match_all("/(?'word'foob[\w]*)/", $text, $matches);
/**
* @var array{
* word: string[]
* } $params
*/
$params = $matches;
for ($i = 0; $i < count($params['word']); $i++) {
echo $params['word'][$i] . "\n";
} |
I found these snippets: https://psalm.dev/r/d1eac9433a<?php
$text = '
foobar
foobaz
fooqux
foobop
';
preg_match_all("/(?'word'foob[\w]*)/", $text, $matches);
/**
* @var array{
* word: string[]
* } $params
*/
$params = $matches;
for ($i = 0; $i < count($params['word']); $i++) {
echo $params['word'][$i] . "\n";
}
|
Currently only supported above assertions,
foreach
andreturn
statements.The text was updated successfully, but these errors were encountered: