Skip to content

Commit f2d8282

Browse files
authored
Merge pull request #598 from PHPCSStandards/feature/introduce-better-exceptions
✨ Introduce 7 new exceptions
2 parents 4a18f11 + 8b08c1e commit f2d8282

File tree

14 files changed

+612
-1
lines changed

14 files changed

+612
-1
lines changed

PHPCSUtils/Exceptions/InvalidTokenArray.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace PHPCSUtils\Exceptions;
1212

13-
use PHP_CodeSniffer\Exceptions\RuntimeException;
13+
use PHPCSUtils\Exceptions\RuntimeException;
1414

1515
/**
1616
* Exception thrown when an non-existent token array is requested.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for reporting a logic error.
17+
*
18+
* {@internal This exception should probably extend the PHP native `LogicException`, but
19+
* that would inhibit the use of this exception, as replacing existing exceptions with this
20+
* (better) one would then be a breaking change.}
21+
*
22+
* @since 1.1.0
23+
*/
24+
final class LogicException extends RuntimeException
25+
{
26+
27+
/**
28+
* Create a new LogicException with a standardized start of the text.
29+
*
30+
* @param string $message Arbitrary message text.
31+
*
32+
* @return \PHPCSUtils\Exceptions\LogicException
33+
*/
34+
public static function create($message)
35+
{
36+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
37+
38+
return new self(
39+
\sprintf(
40+
'%s::%s(): %s',
41+
$stack[1]['class'],
42+
$stack[1]['function'],
43+
$message
44+
)
45+
);
46+
}
47+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for when a (conditionally) required parameter is not passed.
17+
*
18+
* {@internal This exception should probably extend the PHP native `ArgumentCountError`, but
19+
* that would inhibit the use of this exception, as replacing existing exceptions with this
20+
* (better) one would then be a breaking change.}
21+
*
22+
* @since 1.1.0
23+
*/
24+
final class MissingArgumentError extends RuntimeException
25+
{
26+
27+
/**
28+
* Create a new MissingArgumentError exception with a standardized start of the text.
29+
*
30+
* @param int $position The argument position in the function signature. 1-based.
31+
* @param string $name The argument name in the function signature.
32+
* @param string $message Arbitrary message text, which should indicate under what
33+
* conditions the parameter is required.
34+
*
35+
* @return \PHPCSUtils\Exceptions\MissingArgumentError
36+
*/
37+
public static function create($position, $name, $message)
38+
{
39+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
40+
41+
return new self(
42+
\sprintf(
43+
'%s::%s(): Argument #%d (%s) is required %s.',
44+
$stack[1]['class'],
45+
$stack[1]['function'],
46+
$position,
47+
$name,
48+
$message
49+
)
50+
);
51+
}
52+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for when a stack pointer which doesn't exist in the current file is passed.
17+
*
18+
* {@internal This exception should probably extend the PHP native `OutOfBoundsException`, but
19+
* that would inhibit the use of this exception, as replacing existing exceptions with this
20+
* (better) one would then be a breaking change.}
21+
*
22+
* @since 1.1.0
23+
*/
24+
final class OutOfBoundsStackPtr extends RuntimeException
25+
{
26+
27+
/**
28+
* Create a new OutOfBoundsStackPtr exception with a standardized text.
29+
*
30+
* @param int $position The argument position in the function signature. 1-based.
31+
* @param string $name The argument name in the function signature.
32+
* @param mixed $received The received stack pointer position.
33+
*
34+
* @return \PHPCSUtils\Exceptions\OutOfBoundsStackPtr
35+
*/
36+
public static function create($position, $name, $received)
37+
{
38+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
39+
40+
return new self(
41+
\sprintf(
42+
'%s::%s(): Argument #%d (%s) must be a stack pointer which exists in the $phpcsFile object, %s given.',
43+
$stack[1]['class'],
44+
$stack[1]['function'],
45+
$position,
46+
$name,
47+
\is_scalar($received) ? \var_export($received, true) : \gettype($received)
48+
)
49+
);
50+
}
51+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHP_CodeSniffer\Exceptions\RuntimeException as PHPCSRuntimeException;
14+
15+
/**
16+
* Exception for reporting a runtime error.
17+
*
18+
* @phpcs:disable Universal.Classes.RequireFinalClass -- Deliberately not final.
19+
*
20+
* @since 1.1.0
21+
*/
22+
class RuntimeException extends PHPCSRuntimeException
23+
{
24+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for an invalid argument type passed.
17+
*
18+
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, or
19+
* the PHP 7.0+ `TypeError`, but that would inhibit the use of this exception, as replacing existing
20+
* exceptions with this (better) one would then be a breaking change.}
21+
*
22+
* @since 1.1.0
23+
*/
24+
final class TypeError extends RuntimeException
25+
{
26+
27+
/**
28+
* Create a new TypeError exception with a standardized text.
29+
*
30+
* @param int $position The argument position in the function signature. 1-based.
31+
* @param string $name The argument name in the function signature.
32+
* @param string $expected The argument type expected as a string.
33+
* @param mixed $received The actual argument received.
34+
*
35+
* @return \PHPCSUtils\Exceptions\TypeError
36+
*/
37+
public static function create($position, $name, $expected, $received)
38+
{
39+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
40+
41+
return new self(
42+
\sprintf(
43+
'%s::%s(): Argument #%d (%s) must be of type %s, %s given.',
44+
$stack[1]['class'],
45+
$stack[1]['function'],
46+
$position,
47+
$name,
48+
$expected,
49+
\gettype($received)
50+
)
51+
);
52+
}
53+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for when a stack pointer is passed which is not of the expected token type.
17+
*
18+
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, but
19+
* that would inhibit the use of this exception, as replacing existing exceptions with this
20+
* (better) one would then be a breaking change.}
21+
*
22+
* @since 1.1.0
23+
*/
24+
final class UnexpectedTokenType extends RuntimeException
25+
{
26+
27+
/**
28+
* Create a new UnexpectedTokenType exception with a standardized text.
29+
*
30+
* @param int $position The argument position in the function signature. 1-based.
31+
* @param string $name The argument name in the function signature.
32+
* @param string $acceptedTypes Phrase listing the accepted token type(s).
33+
* @param string $receivedType The received token type.
34+
*
35+
* @return \PHPCSUtils\Exceptions\UnexpectedTokenType
36+
*/
37+
public static function create($position, $name, $acceptedTypes, $receivedType)
38+
{
39+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
40+
41+
return new self(
42+
\sprintf(
43+
'%s::%s(): Argument #%d (%s) must be of type %s; %s given.',
44+
$stack[1]['class'],
45+
$stack[1]['function'],
46+
$position,
47+
$name,
48+
$acceptedTypes,
49+
$receivedType
50+
)
51+
);
52+
}
53+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Exceptions;
12+
13+
use PHPCSUtils\Exceptions\RuntimeException;
14+
15+
/**
16+
* Exception for an invalid argument value passed.
17+
*
18+
* This exception should be used when the argument uses the correct type, but doesn't comply with
19+
* predefined restrictions, like an empty string being passed, when only a non-empty string is accepted
20+
* or a negative integer being passed when a positive integer is expected.
21+
*
22+
* {@internal This exception should probably extend the PHP native `InvalidArgumentException`, or the
23+
* PHP 8.0+ `ValueError`, but that would inhibit the use of this exception, as replacing existing
24+
* exceptions with this (better) one would then be a breaking change.}
25+
*
26+
* @since 1.1.0
27+
*/
28+
final class ValueError extends RuntimeException
29+
{
30+
31+
/**
32+
* Create a new ValueError exception with a standardized start of the text.
33+
*
34+
* @param int $position The argument position in the function signature. 1-based.
35+
* @param string $name The argument name in the function signature.
36+
* @param string $message Arbitrary message text.
37+
*
38+
* @return \PHPCSUtils\Exceptions\ValueError
39+
*/
40+
public static function create($position, $name, $message)
41+
{
42+
$stack = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2);
43+
44+
return new self(
45+
\sprintf(
46+
'%s::%s(): The value of argument #%d (%s) %s.',
47+
$stack[1]['class'],
48+
$stack[1]['function'],
49+
$position,
50+
$name,
51+
$message
52+
)
53+
);
54+
}
55+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2024 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Tests\Exceptions\LogicException;
12+
13+
use PHPCSUtils\Exceptions\LogicException;
14+
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
15+
16+
/**
17+
* Test class.
18+
*
19+
* @covers \PHPCSUtils\Exceptions\LogicException
20+
*
21+
* @since 1.1.0
22+
*/
23+
final class LogicExceptionTest extends TestCase
24+
{
25+
26+
/**
27+
* Test that the text of the exception is as expected.
28+
*
29+
* @return void
30+
*/
31+
public function testCreate()
32+
{
33+
$message = \sprintf(
34+
'%s(): your message',
35+
__METHOD__
36+
);
37+
38+
$this->expectException('PHPCSUtils\Exceptions\LogicException');
39+
$this->expectExceptionMessage($message);
40+
41+
throw LogicException::create('your message');
42+
}
43+
}

0 commit comments

Comments
 (0)