Skip to content

Commit

Permalink
Add support and tests for $this type assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
ekisu committed Sep 7, 2023
1 parent d67f5eb commit 79ae86d
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-empty.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-method.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-property.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-this.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-methods.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-intersected.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-invariant.php');
Expand Down
84 changes: 84 additions & 0 deletions tests/PHPStan/Analyser/data/assert-this.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace AssertThis;

use RuntimeException;

use function PHPStan\Testing\assertType;

/**
* @template TOk
* @template TErr
*/
interface Result {
/**
* @phpstan-assert-if-true Ok<TOk> $this
* @phpstan-assert-if-false Err<TErr> $this
*/
public function isOk(): bool;

/**
* @return TOk|never
*/
public function unwrap();
}

/**
* @template TOk
* @template-implements Result<TOk, never>
*/
class Ok implements Result {
public function __construct(private $value) {
}

/**
* @return true
*/
public function isOk(): bool {
return true;
}

/**
* @return TOk
*/
public function unwrap() {
return $this->value;
}
}

/**
* @template TErr
* @template-implements Result<never, TErr>
*/
class Err implements Result {
public function __construct(private $value) {
}

/**
* @return false
*/
public function isOk(): bool {
return false;
}

/**
* @return never
*/
public function unwrap() {
throw new RuntimeException('Tried to unwrap() an Err value');
}
}

function () {
/** @var Result<int, string> $result */
$result = new Ok(123);
assertType('AssertThis\\Result<int, string>', $result);

if ($result->isOk()) {
assertType('AssertThis\\Ok<int>', $result);
assertType('int', $result->unwrap());
} else {
assertType('AssertThis\\Err<string>', $result);
assertType('never', $result->unwrap());
}
};

0 comments on commit 79ae86d

Please sign in to comment.