Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@ if ($a===$b) {
$foo=$bar??$a??$b;
} elseif ($a>$b) {
$variable=$foo?'foo':'bar';
}
]]>
</code>
</code_comparison>
<standard>
<![CDATA[
When the "perCompatible" property is set to "3.0" or higher, the requirement for spaces around the single pipe operator in a multi-catch block is changed to a requirement of "no spaces".
]]>
</standard>
<code_comparison>
<code title="Valid: no spaces around the '|' operator in a multi-catch with 'perCompatible=3.0' (or higher).">
<![CDATA[
try {
} catch (Exception|RuntimeException $e) {
}
]]>
</code>
<code title="Invalid: spaces around the '|' operator in a multi-catch with 'perCompatible=3.0' (or higher).">
<![CDATA[
try {
} catch (Exception | RuntimeException $e) {
}
]]>
</code>
Expand Down
56 changes: 56 additions & 0 deletions src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
class OperatorSpacingSniff extends SquizOperatorSpacingSniff
{

/**
* The PER version to be compatible with. For backwards compatibility this is set to 1.0 by default.
*
* @var string
*/
public $perCompatible = '1.0';


/**
* Returns an array of tokens this test wants to listen for.
Expand Down Expand Up @@ -75,6 +82,55 @@ public function process(File $phpcsFile, int $stackPtr)

$operator = $tokens[$stackPtr]['content'];

// PER-CS 3.0: Exception to the rule for pipe operators in multi-catch blocks where no space is required.
// As union types didn't exist when PSR-12 was created, the pipe in catch statements
// was originally treated as a bitwise operator. This check changes the spacing requirement
// for that specific case when opting in to PER-CS 3.0 or higher.
if ($operator === '|' && version_compare($this->perCompatible, '3.0', '>=') === true
&& isset($tokens[$stackPtr]['nested_parenthesis']) === true
) {
$parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']);
$bracket = array_pop($parenthesis);
if (isset($tokens[$bracket]['parenthesis_owner']) === true
&& $tokens[$tokens[$bracket]['parenthesis_owner']]['code'] === T_CATCH
) {
if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE
&& strpos($tokens[($stackPtr - 1)]['content'], $phpcsFile->eolChar) === false
&& $tokens[($stackPtr - 1)]['column'] !== 1
) {
$error = 'Expected 0 spaces before "%s"; %s found';
$data = [
$operator,
$tokens[($stackPtr - 1)]['length'],
];

$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBefore', $data);
if ($fix === true) {
$phpcsFile->fixer->replaceToken(($stackPtr - 1), '');
}
}

if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE
&& strpos($tokens[($stackPtr + 1)]['content'], $phpcsFile->eolChar) === false
) {
$error = 'Expected 0 spaces after "%s"; %s found';
$data = [
$operator,
$tokens[($stackPtr + 1)]['length'],
];

$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfter', $data);
if ($fix === true) {
$phpcsFile->fixer->replaceToken(($stackPtr + 1), '');
}
}

// Now that this special case is handled, we can return early as we don't need to do
// further checks.
return;
}
}

$checkBefore = true;
$checkAfter = true;

Expand Down
94 changes: 94 additions & 0 deletions src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,97 @@ function setDefault(#[ImportValue(
}

declare(strict_types=1);

// Valid.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception
| RuntimeException
| KlausiException
| AnotherException
| ItNeverEndsException $e
) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception |
RuntimeException |
KlausiException |
AnotherException |
ItNeverEndsException $e
) {
}

// Valid because PSR 12 allows more than one space around operators.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Invalid because of no space.
try {
// nothing
} catch (Exception|RuntimeException $e) {
}

// phpcs:set PSR12.Operators.OperatorSpacing perCompatible 3.0

// Valid.
try {
// nothing
} catch (Exception|RuntimeException $e) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception
|RuntimeException
|KlausiException
|AnotherException
|ItNeverEndsException $e
) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception|
RuntimeException|
KlausiException|
AnotherException|
ItNeverEndsException $e
) {
}

// Invalid becasue of one space.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Invalid because of multiple spaces.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Testing that it works with future versions as well.
// phpcs:set PSR12.Operators.OperatorSpacing perCompatible 4.0

try {
// nothing
} catch (Exception | RuntimeException $e) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,97 @@ function setDefault(#[ImportValue(
}

declare(strict_types=1);

// Valid.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception
| RuntimeException
| KlausiException
| AnotherException
| ItNeverEndsException $e
) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception |
RuntimeException |
KlausiException |
AnotherException |
ItNeverEndsException $e
) {
}

// Valid because PSR 12 allows more than one space around operators.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// Invalid because of no space.
try {
// nothing
} catch (Exception | RuntimeException $e) {
}

// phpcs:set PSR12.Operators.OperatorSpacing perCompatible 3.0

// Valid.
try {
// nothing
} catch (Exception|RuntimeException $e) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception
|RuntimeException
|KlausiException
|AnotherException
|ItNeverEndsException $e
) {
}

// Valid because multiline formatting is undefined.
try {
// nothing
} catch (
Exception|
RuntimeException|
KlausiException|
AnotherException|
ItNeverEndsException $e
) {
}

// Invalid becasue of one space.
try {
// nothing
} catch (Exception|RuntimeException $e) {
}

// Invalid because of multiple spaces.
try {
// nothing
} catch (Exception|RuntimeException $e) {
}

// Testing that it works with future versions as well.
// phpcs:set PSR12.Operators.OperatorSpacing perCompatible 4.0

try {
// nothing
} catch (Exception|RuntimeException $e) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@
switch ($testFile) {
case 'OperatorSpacingUnitTest.1.inc':
return [
2 => 1,

Check failure on line 39 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
3 => 2,

Check failure on line 40 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
4 => 1,

Check failure on line 41 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
5 => 2,

Check failure on line 42 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
6 => 4,

Check failure on line 43 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
9 => 3,

Check failure on line 44 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 3 spaces but found 2
10 => 2,

Check failure on line 45 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 2 spaces but found 1
11 => 3,

Check failure on line 46 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 2 spaces but found 1
13 => 3,

Check failure on line 47 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 2 spaces but found 1
14 => 2,

Check failure on line 48 in src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php

View workflow job for this annotation

GitHub Actions / Check PHP code style

Array double arrow not aligned correctly; expected 2 spaces but found 1
18 => 1,
20 => 1,
22 => 2,
Expand All @@ -56,6 +56,10 @@
40 => 1,
44 => 2,
47 => 2,
120 => 2,
158 => 2,
164 => 2,
172 => 2,
];
default:
return [];
Expand Down
Loading