From bc91de015e5bdc9e22285be3d55bb182cef3e949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sat, 18 Apr 2020 04:08:26 +0200 Subject: [PATCH] Mark throwable methods as pure (#3171) * Write stub as valid PHP This works probably because it is not parsed by PHP but by something more tolerant, but let's make it more valid (the final access type in the signature is not valid) PHP anyway, that will raise fewer eyebrows. * Document actual return type See https://github.com/php/php-src/blob/ca006e54e30bc5ac96f35af1ed7fd73a8c422cf0/Zend/zend_exceptions.stub.php#L8 * Mark all methods from Throwable as mutation free Exception is the only possible class implementation of Throwable, and all of its methods except __toString() are final. See https://github.com/php/php-src/blob/ca006e54e30bc5ac96f35af1ed7fd73a8c422cf0/Zend/zend_exceptions.stub.php#L3-L25 Closes #3170 --- .../Stubs/CoreImmutableClasses.phpstub | 80 ++++++++++++++++--- tests/PureAnnotationTest.php | 66 +++++++++++++++ 2 files changed, 133 insertions(+), 13 deletions(-) diff --git a/src/Psalm/Internal/Stubs/CoreImmutableClasses.phpstub b/src/Psalm/Internal/Stubs/CoreImmutableClasses.phpstub index 6a43f9526..058ff68b7 100644 --- a/src/Psalm/Internal/Stubs/CoreImmutableClasses.phpstub +++ b/src/Psalm/Internal/Stubs/CoreImmutableClasses.phpstub @@ -21,7 +21,37 @@ interface Throwable /** * @psalm-mutation-free */ - public final function getMessage() : string {} + public final function getMessage() : string; + + /** + * @psalm-mutation-free + */ + public final function getCode() : int; + + /** + * @psalm-mutation-free + */ + public final function getFile() : string; + + /** + * @psalm-mutation-free + */ + public final function getLine() : int; + + /** + * @psalm-mutation-free + */ + public final function getTrace() : array; + + /** + * @psalm-mutation-free + */ + public final function getPrevious() : ?Throwable; + + /** + * @psalm-mutation-free + */ + public final function getTraceAsString() : string; } class Exception implements Throwable @@ -61,21 +91,33 @@ class Exception implements Throwable /** * @psalm-mutation-free - * @return int|string */ - public final function getCode(){} + public final function getCode(): int {} /** * @psalm-mutation-free - * @return string */ - public final function getFile(){} + public final function getFile(): string {} /** * @psalm-mutation-free - * @return int */ - public final function getLine(){} + public final function getLine(): int {} + + /** + * @psalm-mutation-free + */ + public final function getTrace() : array {} + + /** + * @psalm-mutation-free + */ + public final function getPrevious() : ?Throwable {} + + /** + * @psalm-mutation-free + */ + public final function getTraceAsString() : string {} } class Error implements Throwable @@ -115,19 +157,31 @@ class Error implements Throwable /** * @psalm-mutation-free - * @return int|string */ - public final function getCode(){} + public final function getCode(): int {} /** * @psalm-mutation-free - * @return string */ - public final function getFile(){} + public final function getFile(): string {} /** * @psalm-mutation-free - * @return int */ - public final function getLine(){} + public final function getLine(): int{} + + /** + * @psalm-mutation-free + */ + public final function getTrace() : array {} + + /** + * @psalm-mutation-free + */ + public final function getPrevious() : ?Throwable {} + + /** + * @psalm-mutation-free + */ + public final function getTraceAsString() : string {} } diff --git a/tests/PureAnnotationTest.php b/tests/PureAnnotationTest.php index 9c9d57887..b6a776bf3 100644 --- a/tests/PureAnnotationTest.php +++ b/tests/PureAnnotationTest.php @@ -210,6 +210,72 @@ class PureAnnotationTest extends TestCase echo getMessage(new Exception("test"));' ], + 'exceptionGetCode' => [ + 'getCode(); + } + + echo getCode(new Exception("test"));' + ], + 'exceptionGetFile' => [ + 'getFile(); + } + + echo getFile(new Exception("test"));' + ], + 'exceptionGetLine' => [ + 'getLine(); + } + + echo getLine(new Exception("test"));' + ], + 'exceptionGetTrace' => [ + 'getTrace(); + } + + echo count(getTrace(new Exception("test")));' + ], + 'exceptionGetPrevious' => [ + 'getPrevious(); + } + + echo gettype(getPrevious(new Exception("test")));' + ], + 'exceptionGetTraceAsString' => [ + 'getTraceAsString(); + } + + echo getTraceAsString(new Exception("test"));' + ], ]; }