Refactor all exception classes, remove unclear RuntimeException, InvalidArgumentException

This commit is contained in:
crazywhalecc 2025-08-06 20:21:09 +08:00 committed by Jerry Ma
parent 0c9a30256e
commit cc447a089a
13 changed files with 383 additions and 19 deletions

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
/**
* BuildFailureException is thrown when a build process failed with other reasons.
*
* This exception indicates that the build operation did not complete successfully,
* which may be due to various reasons such as missing built-files, incorrect configurations, etc.
*/
class BuildFailureException extends SPCException {}

View File

@ -4,4 +4,10 @@ declare(strict_types=1);
namespace SPC\exception;
class DownloaderException extends \Exception {}
/**
* Exception thrown when an error occurs during the downloading process.
*
* This exception is used to indicate that a download operation has failed,
* typically due to network issues, invalid URLs, or other related problems.
*/
class DownloaderException extends SPCException {}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
/**
* EnvironmentException is thrown when there is an issue with the environment setup,
* such as missing dependencies or incorrect configurations.
*/
class EnvironmentException extends SPCException
{
public function __construct(string $message, private readonly ?string $solution = null)
{
parent::__construct($message);
}
/**
* Returns the solution for the environment issue.
*/
public function getSolution(): ?string
{
return $this->solution;
}
}

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
use SPC\util\shell\UnixShell;
use SPC\util\shell\WindowsCmd;
/**
* Exception thrown when an error occurs during execution of shell command.
*
* This exception is used to indicate that a command executed by the SPC framework
* has failed, typically due to an error in the command itself or an issue with the environment
* in which it was executed.
*/
class ExecutionException extends SPCException
{
public function __construct(
private readonly string|UnixShell|WindowsCmd $cmd,
$message = '',
$code = 0,
private readonly ?string $cd = null,
private readonly array $env = [],
?\Exception $previous = null
) {
parent::__construct($message, $code, $previous);
}
/**
* Returns the command that caused the execution error.
*
* @return string the command that was executed when the error occurred
*/
public function getExecutionCommand(): string
{
if ($this->cmd instanceof UnixShell || $this->cmd instanceof WindowsCmd) {
return $this->cmd->getLastCommand();
}
return $this->cmd;
}
/**
* Returns the directory in which the command was executed.
*/
public function getCd(): ?string
{
return $this->cd;
}
/**
* Returns the environment variables that were set during the command execution.
*/
public function getEnv(): array
{
return $this->env;
}
}

View File

@ -4,4 +4,4 @@ declare(strict_types=1);
namespace SPC\exception;
class FileSystemException extends \Exception {}
class FileSystemException extends SPCException {}

View File

@ -4,4 +4,7 @@ declare(strict_types=1);
namespace SPC\exception;
class InterruptException extends \Exception {}
/**
* Exception caused by manual intervention.
*/
class InterruptException extends SPCException {}

View File

@ -1,7 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
class InvalidArgumentException extends \Exception {}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
/**
* PatchException is thrown when there is an issue applying a patch,
* such as a failure in the patch process or conflicts during patching.
*/
class PatchException extends SPCException
{
public function __construct(private readonly string $patch_module, $message, $code = 0, ?\Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
/**
* Returns the name of the patch module that caused the exception.
*/
public function getPatchModule(): string
{
return $this->patch_module;
}
}

View File

@ -1,7 +0,0 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
class RuntimeException extends \Exception {}

View File

@ -0,0 +1,176 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
use SPC\builder\BuilderBase;
use SPC\builder\freebsd\BSDBuilder;
use SPC\builder\freebsd\library\BSDLibraryBase;
use SPC\builder\LibraryBase;
use SPC\builder\linux\library\LinuxLibraryBase;
use SPC\builder\linux\LinuxBuilder;
use SPC\builder\macos\library\MacOSLibraryBase;
use SPC\builder\macos\MacOSBuilder;
use SPC\builder\windows\library\WindowsLibraryBase;
use SPC\builder\windows\WindowsBuilder;
/**
* Base class for SPC exceptions.
*
* This class serves as the base for all exceptions thrown by the SPC framework.
* It extends the built-in PHP Exception class, allowing for custom exception handling
* and categorization of SPC-related errors.
*/
abstract class SPCException extends \Exception
{
private static ?array $build_php_extra_info = null;
private ?array $library_info = null;
private ?array $extension_info = null;
private ?array $build_php_info = null;
private array $extra_log_files = [];
public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->loadStackTraceInfo();
}
public static function bindBuildPHPExtraInfo(array $indent_texts): void
{
self::$build_php_extra_info = $indent_texts;
}
public function bindExtensionInfo(array $extension_info): void
{
$this->extension_info = $extension_info;
}
public function addExtraLogFile(string $key, string $filename): void
{
$this->extra_log_files[$key] = $filename;
}
public function getBuildPHPExtraInfo(): ?array
{
return self::$build_php_extra_info;
}
/**
* Returns an array containing information about the SPC module.
*
* This method can be overridden by subclasses to provide specific module information.
*
* @return null|array{
* library_name: string,
* library_class: string,
* os: string,
* file: null|string,
* line: null|int,
* } an array containing module information
*/
public function getLibraryInfo(): ?array
{
return $this->library_info;
}
/**
* Returns an array containing information about the PHP build process.
*
* @return null|array{
* builder_class: string,
* os: string,
* file: null|string,
* line: null|int,
* } an array containing PHP build information
*/
public function getBuildPHPInfo(): ?array
{
return $this->build_php_info;
}
/**
* Returns an array containing information about the SPC extension.
*
* This method can be overridden by subclasses to provide specific extension information.
*
* @return null|array{
* extension_name: string,
* extension_class: string,
* file: null|string,
* line: null|int,
* } an array containing extension information
*/
public function getExtensionInfo(): ?array
{
return $this->extension_info;
}
public function getExtraLogFiles(): array
{
return $this->extra_log_files;
}
private function loadStackTraceInfo(): void
{
$trace = $this->getTrace();
foreach ($trace as $frame) {
if (!isset($frame['class'])) {
continue;
}
// Check if the class is a subclass of LibraryBase
if (!$this->library_info && is_subclass_of($frame['class'], LibraryBase::class)) {
try {
$reflection = new \ReflectionClass($frame['class']);
if ($reflection->hasConstant('NAME')) {
$name = $reflection->getConstant('NAME');
if ($name !== 'unknown') {
$this->library_info = [
'library_name' => $name,
'library_class' => $frame['class'],
'os' => match (true) {
is_a($frame['class'], BSDLibraryBase::class, true) => 'BSD',
is_a($frame['class'], LinuxLibraryBase::class, true) => 'Linux',
is_a($frame['class'], MacOSLibraryBase::class, true) => 'macOS',
is_a($frame['class'], WindowsLibraryBase::class, true) => 'Windows',
default => 'Unknown',
},
'file' => $frame['file'] ?? null,
'line' => $frame['line'] ?? null,
];
continue;
}
}
} catch (\ReflectionException) {
continue;
}
}
// Check if the class is a subclass of BuilderBase and the method is buildPHP
if (!$this->build_php_info && is_subclass_of($frame['class'], BuilderBase::class) && $frame['function'] === 'buildPHP') {
$reflection = new \ReflectionClass($frame['class']);
if ($reflection->hasProperty('options')) {
$options = $reflection->getProperty('options')->getValue();
}
$this->build_php_info = [
'builder_class' => $frame['class'],
'builder_options' => $options ?? [],
'os' => match (true) {
is_a($frame['class'], BSDBuilder::class, true) => 'BSD',
is_a($frame['class'], LinuxBuilder::class, true) => 'Linux',
is_a($frame['class'], MacOSBuilder::class, true) => 'macOS',
is_a($frame['class'], WindowsBuilder::class, true) => 'Windows',
default => 'Unknown',
},
'file' => $frame['file'] ?? null,
'line' => $frame['line'] ?? null,
];
}
}
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace SPC\exception;
/**
* Exception for internal errors or vendor wrong usage in SPC.
*
* This exception is thrown when an unexpected internal error or vendor wrong usage occurs within the SPC framework.
*/
class SPCInternalException extends SPCException {}

View File

@ -4,4 +4,58 @@ declare(strict_types=1);
namespace SPC\exception;
class ValidationException extends \Exception {}
use SPC\builder\Extension;
/**
* Exception thrown for validation errors in SPC.
*
* This exception is used to indicate that a validation error has occurred,
* typically when input data does not meet the required criteria.
*/
class ValidationException extends SPCException
{
private null|array|string $validation_module = null;
public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null, null|array|string $validation_module = null)
{
parent::__construct($message, $code, $previous);
// init validation module
if ($validation_module === null) {
foreach ($this->getTrace() as $trace) {
// Extension validate() => "Extension validator"
if (is_a($trace['class'] ?? null, Extension::class, true) && $trace['function'] === 'validate') {
$this->validation_module = 'Extension validator';
break;
}
// Other => "ClassName::functionName"
$this->validation_module = [
'class' => $trace['class'] ?? null,
'function' => $trace['function'],
];
break;
}
} else {
$this->validation_module = $validation_module;
}
}
/**
* Returns the validation module string.
*/
public function getValidationModuleString(): string
{
if ($this->validation_module === null) {
return 'Unknown';
}
if (is_string($this->validation_module)) {
return $this->validation_module;
}
$str = $this->validation_module['class'] ?? null;
if ($str !== null) {
$str .= '::';
}
return ($str ?? '') . $this->validation_module['function'];
}
}

View File

@ -4,4 +4,10 @@ declare(strict_types=1);
namespace SPC\exception;
class WrongUsageException extends \Exception {}
/**
* Exception thrown for incorrect usage of SPC.
*
* This exception is used to indicate that the SPC is being used incorrectly.
* Such as when a command is not supported or an invalid argument is provided.
*/
class WrongUsageException extends SPCException {}