Skip to content

Commit

Permalink
Merge pull request #598 from PHPCSStandards/feature/introduce-better-…
Browse files Browse the repository at this point in the history
…exceptions

✨ Introduce 7 new exceptions
  • Loading branch information
jrfnl authored May 20, 2024
2 parents 4a18f11 + 8b08c1e commit f2d8282
Show file tree
Hide file tree
Showing 14 changed files with 612 additions and 1 deletion.
2 changes: 1 addition & 1 deletion PHPCSUtils/Exceptions/InvalidTokenArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace PHPCSUtils\Exceptions;

use PHP_CodeSniffer\Exceptions\RuntimeException;
use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception thrown when an non-existent token array is requested.
Expand Down
47 changes: 47 additions & 0 deletions PHPCSUtils/Exceptions/LogicException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for reporting a logic error.
*
* {@internal This exception should probably extend the PHP native `LogicException`, but
* that would inhibit the use of this exception, as replacing existing exceptions with this
* (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class LogicException extends RuntimeException
{

/**
* Create a new LogicException with a standardized start of the text.
*
* @param string $message Arbitrary message text.
*
* @return \PHPCSUtils\Exceptions\LogicException
*/
public static function create($message)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): %s',
$stack[1]['class'],
$stack[1]['function'],
$message
)
);
}
}
52 changes: 52 additions & 0 deletions PHPCSUtils/Exceptions/MissingArgumentError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for when a (conditionally) required parameter is not passed.
*
* {@internal This exception should probably extend the PHP native `ArgumentCountError`, but
* that would inhibit the use of this exception, as replacing existing exceptions with this
* (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class MissingArgumentError extends RuntimeException
{

/**
* Create a new MissingArgumentError exception with a standardized start of the text.
*
* @param int $position The argument position in the function signature. 1-based.
* @param string $name The argument name in the function signature.
* @param string $message Arbitrary message text, which should indicate under what
* conditions the parameter is required.
*
* @return \PHPCSUtils\Exceptions\MissingArgumentError
*/
public static function create($position, $name, $message)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): Argument #%d (%s) is required %s.',
$stack[1]['class'],
$stack[1]['function'],
$position,
$name,
$message
)
);
}
}
51 changes: 51 additions & 0 deletions PHPCSUtils/Exceptions/OutOfBoundsStackPtr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for when a stack pointer which doesn't exist in the current file is passed.
*
* {@internal This exception should probably extend the PHP native `OutOfBoundsException`, but
* that would inhibit the use of this exception, as replacing existing exceptions with this
* (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class OutOfBoundsStackPtr extends RuntimeException
{

/**
* Create a new OutOfBoundsStackPtr exception with a standardized text.
*
* @param int $position The argument position in the function signature. 1-based.
* @param string $name The argument name in the function signature.
* @param mixed $received The received stack pointer position.
*
* @return \PHPCSUtils\Exceptions\OutOfBoundsStackPtr
*/
public static function create($position, $name, $received)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): Argument #%d (%s) must be a stack pointer which exists in the $phpcsFile object, %s given.',
$stack[1]['class'],
$stack[1]['function'],
$position,
$name,
\is_scalar($received) ? \var_export($received, true) : \gettype($received)
)
);
}
}
24 changes: 24 additions & 0 deletions PHPCSUtils/Exceptions/RuntimeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHP_CodeSniffer\Exceptions\RuntimeException as PHPCSRuntimeException;

/**
* Exception for reporting a runtime error.
*
* @phpcs:disable Universal.Classes.RequireFinalClass -- Deliberately not final.
*
* @since 1.1.0
*/
class RuntimeException extends PHPCSRuntimeException
{
}
53 changes: 53 additions & 0 deletions PHPCSUtils/Exceptions/TypeError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for an invalid argument type passed.
*
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, or
* the PHP 7.0+ `TypeError`, but that would inhibit the use of this exception, as replacing existing
* exceptions with this (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class TypeError extends RuntimeException
{

/**
* Create a new TypeError exception with a standardized text.
*
* @param int $position The argument position in the function signature. 1-based.
* @param string $name The argument name in the function signature.
* @param string $expected The argument type expected as a string.
* @param mixed $received The actual argument received.
*
* @return \PHPCSUtils\Exceptions\TypeError
*/
public static function create($position, $name, $expected, $received)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): Argument #%d (%s) must be of type %s, %s given.',
$stack[1]['class'],
$stack[1]['function'],
$position,
$name,
$expected,
\gettype($received)
)
);
}
}
53 changes: 53 additions & 0 deletions PHPCSUtils/Exceptions/UnexpectedTokenType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for when a stack pointer is passed which is not of the expected token type.
*
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, but
* that would inhibit the use of this exception, as replacing existing exceptions with this
* (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class UnexpectedTokenType extends RuntimeException
{

/**
* Create a new UnexpectedTokenType exception with a standardized text.
*
* @param int $position The argument position in the function signature. 1-based.
* @param string $name The argument name in the function signature.
* @param string $acceptedTypes Phrase listing the accepted token type(s).
* @param string $receivedType The received token type.
*
* @return \PHPCSUtils\Exceptions\UnexpectedTokenType
*/
public static function create($position, $name, $acceptedTypes, $receivedType)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): Argument #%d (%s) must be of type %s; %s given.',
$stack[1]['class'],
$stack[1]['function'],
$position,
$name,
$acceptedTypes,
$receivedType
)
);
}
}
55 changes: 55 additions & 0 deletions PHPCSUtils/Exceptions/ValueError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Exceptions;

use PHPCSUtils\Exceptions\RuntimeException;

/**
* Exception for an invalid argument value passed.
*
* This exception should be used when the argument uses the correct type, but doesn't comply with
* predefined restrictions, like an empty string being passed, when only a non-empty string is accepted
* or a negative integer being passed when a positive integer is expected.
*
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, or the
* PHP 8.0+ `ValueError`, but that would inhibit the use of this exception, as replacing existing
* exceptions with this (better) one would then be a breaking change.}
*
* @since 1.1.0
*/
final class ValueError extends RuntimeException
{

/**
* Create a new ValueError exception with a standardized start of the text.
*
* @param int $position The argument position in the function signature. 1-based.
* @param string $name The argument name in the function signature.
* @param string $message Arbitrary message text.
*
* @return \PHPCSUtils\Exceptions\ValueError
*/
public static function create($position, $name, $message)
{
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);

return new self(
\sprintf(
'%s::%s(): The value of argument #%d (%s) %s.',
$stack[1]['class'],
$stack[1]['function'],
$position,
$name,
$message
)
);
}
}
43 changes: 43 additions & 0 deletions Tests/Exceptions/LogicException/LogicExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2024 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/

namespace PHPCSUtils\Tests\Exceptions\LogicException;

use PHPCSUtils\Exceptions\LogicException;
use Yoast\PHPUnitPolyfills\TestCases\TestCase;

/**
* Test class.
*
* @covers \PHPCSUtils\Exceptions\LogicException
*
* @since 1.1.0
*/
final class LogicExceptionTest extends TestCase
{

/**
* Test that the text of the exception is as expected.
*
* @return void
*/
public function testCreate()
{
$message = \sprintf(
'%s(): your message',
__METHOD__
);

$this->expectException('PHPCSUtils\Exceptions\LogicException');
$this->expectExceptionMessage($message);

throw LogicException::create('your message');
}
}
Loading

0 comments on commit f2d8282

Please sign in to comment.