From 43b7b046fa73cc3ca5bbd30f74564750d8b8b3a2 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 28 Dec 2023 12:33:06 +0400 Subject: [PATCH] modifs.mineures sans commentaires --- php/src_base/ExceptionShadow.php | 101 +++++++++++++++++++++++++++++++ php/src_base/ExitException.php | 22 +++++++ php/src_base/StopException.php | 12 ++++ php/src_base/UserException.php | 89 +++++++++++++++++++++++++++ php/src_base/ValueException.php | 20 ++++-- php/src_base/cv.php | 4 +- php/src_base/str.php | 2 +- php/tests/ValueExceptionTest.php | 6 +- 8 files changed, 245 insertions(+), 11 deletions(-) create mode 100644 php/src_base/ExceptionShadow.php create mode 100644 php/src_base/ExitException.php create mode 100644 php/src_base/StopException.php create mode 100644 php/src_base/UserException.php diff --git a/php/src_base/ExceptionShadow.php b/php/src_base/ExceptionShadow.php new file mode 100644 index 0000000..6e5ca3e --- /dev/null +++ b/php/src_base/ExceptionShadow.php @@ -0,0 +1,101 @@ + $file, + "line" => $line, + "class" => $class, + "object" => null, + "type" => $type, + "function" => $function, + "args" => [], + ]; + } + return $frames; + } + + function __construct(Throwable $exception) { + $this->class = get_class($exception); + $this->message = $exception->getMessage(); + $this->code = $exception->getCode(); + $this->file = $exception->getFile(); + $this->line = $exception->getLine(); + $this->trace = self::extract_trace($exception->getTrace()); + $previous = $exception->getPrevious(); + if ($previous !== null) $this->previous = new static($previous); + } + + /** @var string */ + protected $class; + + function getClass(): string { + return $this->class; + } + + /** @var string */ + protected $message; + + function getMessage(): string { + return $this->message; + } + + /** @var mixed */ + protected $code; + + function getCode() { + return $this->code; + } + + /** @var string */ + protected $file; + + function getFile(): string { + return $this->file; + } + + /** @var int */ + protected $line; + + function getLine(): int { + return $this->line; + } + + /** @var array */ + protected $trace; + + function getTrace(): array { + return $this->trace; + } + + function getTraceAsString(): string { + $lines = []; + foreach ($this->trace as $index => $frame) { + $lines[] = "#$index $frame[file]($frame[line]): $frame[class]$frame[type]$frame[function]()"; + } + $index++; + $lines[] = "#$index {main}"; + return implode("\n", $lines); + } + + /** @var ExceptionShadow */ + protected $previous; + + function getPrevious(): ?ExceptionShadow { + return $this->previous; + } +} diff --git a/php/src_base/ExitException.php b/php/src_base/ExitException.php new file mode 100644 index 0000000..008a186 --- /dev/null +++ b/php/src_base/ExitException.php @@ -0,0 +1,22 @@ +getCode() !== 0; + } + + function haveMessage(): bool { + return $this->getUserMessage() !== null; + } +} diff --git a/php/src_base/StopException.php b/php/src_base/StopException.php new file mode 100644 index 0000000..de1b4dd --- /dev/null +++ b/php/src_base/StopException.php @@ -0,0 +1,12 @@ +getUserMessage(); + else return null; + } + + /** @param Throwable|ExceptionShadow $e */ + static final function get_user_summary($e): string { + $parts = []; + $first = true; + while ($e !== null) { + $message = self::get_user_message($e); + if (!$message) $message = "(no message)"; + if ($first) $first = false; + else $parts[] = "caused by "; + $parts[] = get_class($e) . ": " . $message; + $e = $e->getPrevious(); + } + return implode(", ", $parts); + } + + /** @param Throwable|ExceptionShadow $e */ + static function get_message($e): ?string { + $message = $e->getMessage(); + if (!$message && $e instanceof self) $message = $e->getUserMessage(); + return $message; + } + + /** @param Throwable|ExceptionShadow $e */ + static final function get_summary($e): string { + $parts = []; + $first = true; + while ($e !== null) { + $message = self::get_message($e); + if (!$message) $message = "(no message)"; + if ($first) $first = false; + else $parts[] = "caused by "; + if ($e instanceof ExceptionShadow) $class = $e->getClass(); + else $class = get_class($e); + $parts[] = "$class: $message"; + $e = $e->getPrevious(); + } + return implode(", ", $parts); + } + + /** @param Throwable|ExceptionShadow $e */ + static final function get_traceback($e): string { + $tbs = []; + $previous = false; + while ($e !== null) { + if (!$previous) { + $efile = $e->getFile(); + $eline = $e->getLine(); + $tbs[] = "at $efile($eline)"; + } else { + $tbs[] = "~~ caused by: " . self::get_summary($e); + } + $tbs[] = $e->getTraceAsString(); + $e = $e->getPrevious(); + $previous = true; + #XXX il faudrait ne pas réinclure les lignes communes aux exceptions qui + # ont déjà été affichées + } + return implode("\n", $tbs); + } + + function __construct($user_message, $tech_message=null, $code=0, ?Throwable $previous=null) { + $this->userMessage = $user_message; + if ($tech_message === null) $tech_message = $user_message; + parent::__construct($tech_message, $code, $previous); + } + + protected $userMessage; + + function getUserMessage(): ?string { + return $this->userMessage; + } +} diff --git a/php/src_base/ValueException.php b/php/src_base/ValueException.php index 51e35c8..10498ee 100644 --- a/php/src_base/ValueException.php +++ b/php/src_base/ValueException.php @@ -1,12 +1,10 @@ "; @@ -40,11 +38,23 @@ class ValueException extends Exception { return new static(self::message(null, $message, $kind, $prefix, " is null")); } - static final function invalid($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self { + static final function invalid_kind($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self { return new static(self::message($value, $message, $kind, $prefix, " is invalid")); } - static final function unexpected_class($class, string $expected_class) { + static final function invalid_key($value, ?string $prefix=null, ?string $message=null): self { + return self::invalid_kind($value, "key", $prefix, $message); + } + + static final function invalid_value($value, ?string $prefix=null, ?string $message=null): self { + return self::invalid_kind($value, "value", $prefix, $message); + } + + static final function invalid_type($value, string $expected_type): self { + return new static(self::message($value, null, "type", null, " is invalid, expected $expected_type")); + } + + static final function invalid_class($class, string $expected_class): self { if (is_object($class)) $class = get_class($class); return new static(self::message($class, null, "class", null, " is invalid, expected $expected_class")); } diff --git a/php/src_base/cv.php b/php/src_base/cv.php index 42b5eb5..796a6da 100644 --- a/php/src_base/cv.php +++ b/php/src_base/cv.php @@ -181,7 +181,7 @@ class cv { $index = is_int($value)? $value : null; $key = is_string($value)? $value : null; if ($index === null && $key === null && $throw_exception) { - throw ValueException::invalid($value, "key", $prefix); + throw ValueException::invalid_kind($value, "key", $prefix); } else { return [$index, $key]; } @@ -198,7 +198,7 @@ class cv { $string = is_string($value)? $value : null; $array = is_array($value)? $value : null; if ($bool === null && $string === null && $array === null && $throw_exception) { - throw ValueException::invalid($value, "value", $prefix); + throw ValueException::invalid_kind($value, "value", $prefix); } else { return [$bool, $string, $array]; } diff --git a/php/src_base/str.php b/php/src_base/str.php index d2b5471..3ef054a 100644 --- a/php/src_base/str.php +++ b/php/src_base/str.php @@ -348,7 +348,7 @@ class str { } elseif (preg_match(self::CAMEL_PATTERN2, $camel, $vs, PREG_OFFSET_CAPTURE)) { # préfixe en minuscule } else { - throw ValueException::invalid($camel, "camel string"); + throw ValueException::invalid_kind($camel, "camel string"); } $parts[] = strtolower($vs[1][0]); $index = intval($vs[1][1]) + strlen($vs[1][0]); diff --git a/php/tests/ValueExceptionTest.php b/php/tests/ValueExceptionTest.php index d325159..a41a937 100644 --- a/php/tests/ValueExceptionTest.php +++ b/php/tests/ValueExceptionTest.php @@ -4,11 +4,11 @@ namespace nulib; use nulib\tests\TestCase; class ValueExceptionTest extends TestCase { - function testUnexpectedClass() { - $e = ValueException::unexpected_class(null, self::class); + function testInvalidClass() { + $e = ValueException::invalid_class(null, self::class); self::assertSame("class is invalid, expected ".self::class, $e->getMessage()); - $e = ValueException::unexpected_class(ValueException::class, self::class); + $e = ValueException::invalid_class(ValueException::class, self::class); self::assertSame(ValueException::class.": class is invalid, expected ".self::class, $e->getMessage()); } }