Skip to content

Commit 72949bb

Browse files
authored
Improve error message for an invalid sniff code (PHPCSStandards#344)
.. when using the `--sniffs=...` or `--exclude=...` CLI flags. Instead of piecemealing the errors, all errors for the complete argument will now be shown in one go.
1 parent d694aea commit 72949bb

File tree

2 files changed

+251
-60
lines changed

2 files changed

+251
-60
lines changed

src/Config.php

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -885,32 +885,14 @@ public function processLongArgument($arg, $pos)
885885
break;
886886
}
887887

888-
$sniffs = explode(',', substr($arg, 7));
889-
foreach ($sniffs as $sniff) {
890-
if (substr_count($sniff, '.') !== 2) {
891-
$error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL;
892-
$error .= $this->printShortUsage(true);
893-
throw new DeepExitException($error, 3);
894-
}
895-
}
896-
897-
$this->sniffs = $sniffs;
888+
$this->sniffs = $this->parseSniffCodes(substr($arg, 7), 'sniffs');
898889
self::$overriddenDefaults['sniffs'] = true;
899890
} else if (substr($arg, 0, 8) === 'exclude=') {
900891
if (isset(self::$overriddenDefaults['exclude']) === true) {
901892
break;
902893
}
903894

904-
$sniffs = explode(',', substr($arg, 8));
905-
foreach ($sniffs as $sniff) {
906-
if (substr_count($sniff, '.') !== 2) {
907-
$error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL;
908-
$error .= $this->printShortUsage(true);
909-
throw new DeepExitException($error, 3);
910-
}
911-
}
912-
913-
$this->exclude = $sniffs;
895+
$this->exclude = $this->parseSniffCodes(substr($arg, 8), 'exclude');
914896
self::$overriddenDefaults['exclude'] = true;
915897
} else if (defined('PHP_CODESNIFFER_IN_TESTS') === false
916898
&& substr($arg, 0, 6) === 'cache='
@@ -1277,6 +1259,93 @@ public function processLongArgument($arg, $pos)
12771259
}//end processLongArgument()
12781260

12791261

1262+
/**
1263+
* Parse supplied string into a list of validated sniff codes.
1264+
*
1265+
* @param string $input Comma-separated string of sniff codes.
1266+
* @param string $argument The name of the argument which is being processed.
1267+
*
1268+
* @return array<string>
1269+
* @throws DeepExitException When any of the provided codes are not valid as sniff codes.
1270+
*/
1271+
private function parseSniffCodes($input, $argument)
1272+
{
1273+
$errors = [];
1274+
$sniffs = [];
1275+
1276+
$possibleSniffs = array_filter(explode(',', $input));
1277+
1278+
if ($possibleSniffs === []) {
1279+
$errors[] = 'No codes specified / empty argument';
1280+
}
1281+
1282+
foreach ($possibleSniffs as $sniff) {
1283+
$sniff = trim($sniff);
1284+
1285+
$partCount = substr_count($sniff, '.');
1286+
if ($partCount === 2) {
1287+
// Correct number of parts.
1288+
$sniffs[] = $sniff;
1289+
continue;
1290+
}
1291+
1292+
if ($partCount === 0) {
1293+
$errors[] = 'Standard codes are not supported: '.$sniff;
1294+
} else if ($partCount === 1) {
1295+
$errors[] = 'Category codes are not supported: '.$sniff;
1296+
} else if ($partCount === 3) {
1297+
$errors[] = 'Message codes are not supported: '.$sniff;
1298+
} else {
1299+
$errors[] = 'Too many parts: '.$sniff;
1300+
}
1301+
1302+
if ($partCount > 2) {
1303+
$parts = explode('.', $sniff, 4);
1304+
$sniffs[] = $parts[0].'.'.$parts[1].'.'.$parts[2];
1305+
}
1306+
}//end foreach
1307+
1308+
$sniffs = array_reduce(
1309+
$sniffs,
1310+
static function ($carry, $item) {
1311+
$lower = strtolower($item);
1312+
1313+
foreach ($carry as $found) {
1314+
if ($lower === strtolower($found)) {
1315+
// This sniff is already in our list.
1316+
return $carry;
1317+
}
1318+
}
1319+
1320+
$carry[] = $item;
1321+
1322+
return $carry;
1323+
},
1324+
[]
1325+
);
1326+
1327+
if ($errors !== []) {
1328+
$error = 'ERROR: The --'.$argument.' option only supports sniff codes.'.PHP_EOL;
1329+
$error .= 'Sniff codes are in the form "Standard.Category.Sniff".'.PHP_EOL;
1330+
$error .= PHP_EOL;
1331+
$error .= 'The following problems were detected:'.PHP_EOL;
1332+
$error .= '* '.implode(PHP_EOL.'* ', $errors).PHP_EOL;
1333+
1334+
if ($sniffs !== []) {
1335+
$error .= PHP_EOL;
1336+
$error .= 'Perhaps try --'.$argument.'="'.implode(',', $sniffs).'" instead.'.PHP_EOL;
1337+
}
1338+
1339+
$error .= PHP_EOL;
1340+
$error .= $this->printShortUsage(true);
1341+
throw new DeepExitException(ltrim($error), 3);
1342+
}
1343+
1344+
return $sniffs;
1345+
1346+
}//end parseSniffCodes()
1347+
1348+
12801349
/**
12811350
* Processes an unknown command line argument.
12821351
*

0 commit comments

Comments
 (0)