Skip to content

Commit 051cc15

Browse files
committed
Ruleset: wire in MessageCollector
This commit adds a mechanism to handle errors encountered while loading a ruleset in a more user-friendly manner. * Errors and notices aimed at end-users and ruleset maintainers will be collected while processing the ruleset. * Only once the complete processing of the ruleset is finished, will all errors/notices be displayed. This prevents "one error hiding behind another". * If there are only notices (deprecations/notices/warnings), these will not display when running `-e` (explain), `-q` (quiet mode) or `--generator=...` (documentation). * Errors will always display and will hard exit out of the run with a non-zero exit code. This implementation should be seen as an interim - "good enough for now" - solution, which can be iterated on in the future. I can imagine a more code-base wide solution at some later point in time, but that should not block this initial improvement. As the current implementation doesn't change the public API (the only new methods are `private`), it should be feasible to transform the current solution to whatever form a future solution will take without breaking changes. Includes tests covering the new functionality.
1 parent 863cb7d commit 051cc15

File tree

2 files changed

+358
-5
lines changed

2 files changed

+358
-5
lines changed

src/Ruleset.php

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHP_CodeSniffer\Exceptions\RuntimeException;
1515
use PHP_CodeSniffer\Sniffs\DeprecatedSniff;
1616
use PHP_CodeSniffer\Util\Common;
17+
use PHP_CodeSniffer\Util\MessageCollector;
1718
use PHP_CodeSniffer\Util\Standards;
1819
use RecursiveDirectoryIterator;
1920
use RecursiveIteratorIterator;
@@ -138,21 +139,36 @@ class Ruleset
138139
*/
139140
private $deprecatedSniffs = [];
140141

142+
/**
143+
* Message collector object.
144+
*
145+
* User-facing messages should be collected via this object for display once the ruleset processing has finished.
146+
*
147+
* The following type of errors should *NOT* be collected, but should still throw their own `RuntimeException`:
148+
* - Errors which could cause other (uncollectable) errors further into the ruleset processing, like a missing autoload file.
149+
* - Errors which are directly aimed at and only intended for sniff developers or integrators
150+
* (in contrast to ruleset maintainers or end-users).
151+
*
152+
* @var \PHP_CodeSniffer\Util\MessageCollector
153+
*/
154+
private $msgCache;
155+
141156

142157
/**
143158
* Initialise the ruleset that the run will use.
144159
*
145160
* @param \PHP_CodeSniffer\Config $config The config data for the run.
146161
*
147162
* @return void
148-
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If no sniffs were registered.
163+
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If blocking errors were encountered when processing the ruleset.
149164
*/
150165
public function __construct(Config $config)
151166
{
152-
$this->config = $config;
153-
$restrictions = $config->sniffs;
154-
$exclusions = $config->exclude;
155-
$sniffs = [];
167+
$this->config = $config;
168+
$restrictions = $config->sniffs;
169+
$exclusions = $config->exclude;
170+
$sniffs = [];
171+
$this->msgCache = new MessageCollector();
156172

157173
$standardPaths = [];
158174
foreach ($config->standards as $standard) {
@@ -249,6 +265,8 @@ public function __construct(Config $config)
249265
throw new RuntimeException('ERROR: No sniffs were registered');
250266
}
251267

268+
$this->displayCachedMessages();
269+
252270
}//end __construct()
253271

254272

@@ -480,6 +498,35 @@ public function showSniffDeprecations()
480498
}//end showSniffDeprecations()
481499

482500

501+
/**
502+
* Print any notices encountered while processing the ruleset(s).
503+
*
504+
* Note: these messages aren't shown at the time they are encountered to avoid "one error hiding behind another".
505+
* This way the (end-)user gets to see all of them in one go.
506+
*
507+
* @return void
508+
*
509+
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If blocking errors were encountered.
510+
*/
511+
private function displayCachedMessages()
512+
{
513+
// Don't show deprecations/notices/warnings in quiet mode, in explain mode
514+
// or when the documentation is being shown.
515+
// Documentation and explain will call the Ruleset multiple times which
516+
// would lead to duplicate display of the messages.
517+
if ($this->msgCache->containsBlockingErrors() === false
518+
&& ($this->config->quiet === true
519+
|| $this->config->explain === true
520+
|| $this->config->generator !== null)
521+
) {
522+
return;
523+
}
524+
525+
$this->msgCache->display();
526+
527+
}//end displayCachedMessages()
528+
529+
483530
/**
484531
* Processes a single ruleset and returns a list of the sniffs it represents.
485532
*

0 commit comments

Comments
 (0)