1111use Windwalker \Utilities \Str ;
1212
1313/**
14+ * @psalm-type MessageClosure = Closure(string $caller, mixed $value, string $type): string
15+ *
1416 * The Assert class.
1517 */
1618class Assert
@@ -34,16 +36,27 @@ public function __construct(callable $exceptionHandler, ?string $caller = null)
3436 $ this ->exceptionHandler = $ exceptionHandler ;
3537 }
3638
39+ public static function create (
40+ string $ exceptionClass = \RuntimeException::class,
41+ int $ code = 500 ,
42+ ?string $ caller = null ,
43+ ): static {
44+ return new static (
45+ fn ($ message ) => new $ exceptionClass ($ message , $ code ),
46+ $ caller
47+ );
48+ }
49+
3750 /**
38- * @param bool|callable $assertion
39- * @param string $message
40- * @param mixed $value
51+ * @template T of mixed
4152 *
42- * @return void
53+ * @param T $assertion
54+ * @param string|MessageClosure $message
55+ * @param mixed $value
4356 *
44- * @throws Throwable
57+ * @return T
4558 */
46- public function assert (mixed $ assertion , string $ message , mixed $ value = null ): void
59+ public function assert (mixed $ assertion , string | Closure $ message , mixed $ value = null ): mixed
4760 {
4861 if (is_callable ($ assertion )) {
4962 $ result = $ assertion ();
@@ -54,22 +67,46 @@ public function assert(mixed $assertion, string $message, mixed $value = null):
5467 if (!$ result ) {
5568 $ this ->throwException ($ message , $ value );
5669 }
70+
71+ return $ assertion ;
72+ }
73+
74+ /**
75+ * @template T of mixed
76+ *
77+ * @param T $assertion
78+ * @param string|MessageClosure $message
79+ * @param mixed $value
80+ *
81+ * @return T
82+ */
83+ public function __invoke (mixed $ assertion , string |Closure $ message , mixed $ value = null ): mixed
84+ {
85+ return $ this ->assert ($ assertion , $ message , $ value );
5786 }
5887
59- public function throwException (string $ message , $ value = null ): void
88+ public function throwException (string | Closure $ message , $ value = null ): void
6089 {
6190 throw $ this ->exception ($ message , $ value );
6291 }
6392
64- public function exception (string $ message , $ value = null )
93+ public function exception (string | Closure $ message , $ value = null )
6594 {
6695 return ($ this ->exceptionHandler )($ this ->createMessage ($ message , $ value ));
6796 }
6897
69- protected function createMessage (string $ message , $ value ): string
98+ protected function createMessage (string | Closure $ message , $ value ): string
7099 {
71100 $ described = static ::describeValue ($ value );
72101
102+ if ($ message instanceof Closure) {
103+ try {
104+ $ message = $ message ($ this ->caller , $ value , $ described );
105+ } catch (Throwable $ e ) {
106+ $ message = 'Error when generating assert message: ' . $ e ->getMessage ();
107+ }
108+ }
109+
73110 if (str_contains ($ message , '% ' )) {
74111 $ message = sprintf ($ message , $ described );
75112 }
@@ -80,6 +117,7 @@ protected function createMessage(string $message, $value): string
80117 [
81118 'caller ' => $ this ->caller ,
82119 'value ' => $ value ,
120+ 'type ' => $ described ,
83121 ],
84122 '. ' ,
85123 ['{ ' , '} ' ]
0 commit comments