Skip to content

Commit d931828

Browse files
committed
Merge remote-tracking branch 'upstream/master' into fixer-conflict/PSR12.ControlStructures.ControlStructureSpacing
2 parents c52b6ed + 41a426c commit d931828

34 files changed

+668
-23
lines changed

.github/workflows/test.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ jobs:
2525
runs-on: ubuntu-latest
2626
name: "Build Phar on PHP: 8.0"
2727

28+
permissions:
29+
id-token: write
30+
contents: read
31+
attestations: write
32+
2833
steps:
2934
- name: Checkout code
3035
uses: actions/checkout@v4
@@ -39,6 +44,17 @@ jobs:
3944
- name: Build the phar
4045
run: php scripts/build-phar.php
4146

47+
# Provide provenance for generated binaries.
48+
# Only attests the build artifacts which will be used in the published releases as per the guidelines in "what to attest".
49+
# https://docs.github.com/en/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds
50+
- name: Generate artifact attestations
51+
if: ${{ github.ref_type == 'tag' }}
52+
uses: actions/attest-build-provenance@v1
53+
with:
54+
subject-path: |
55+
${{ github.workspace }}/phpcs.phar
56+
${{ github.workspace }}/phpcbf.phar
57+
4258
- name: Upload the PHPCS phar
4359
uses: actions/upload-artifact@v4
4460
with:

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ _Nothing yet._
396396
- **_In contrast to earlier information, the `squizlabs/php_codesniffer` package now points to the new repository and everything will continue to work as before._**
397397
- PHIVE users may need to clear the PHIVE URL cache.
398398
- PHIVE users who don't use the package alias, but refer to the package URL, will need to update the URL from `https://squizlabs.github.io/PHP_CodeSniffer/phars/` to `https://phars.phpcodesniffer.com/phars/`.
399-
- Users who download the PHAR files using curl or wget, will need to update the download URL from `https://squizlabs.github.io/PHP_CodeSniffer/[phpcs|phpcbf].phar` or `https://github.com/squizlabs/PHP_CodeSnifffer/releases/latest/download/[phpcs|phpcbf].phar` to `https://phars.phpcodesniffer.com/[phpcs|phpcbf].phar`.
399+
- Users who download the PHAR files using curl or wget, will need to update the download URL from `https://squizlabs.github.io/PHP_CodeSniffer/[phpcs|phpcbf].phar` or `https://github.com/squizlabs/PHP_CodeSniffer/releases/latest/download/[phpcs|phpcbf].phar` to `https://phars.phpcodesniffer.com/[phpcs|phpcbf].phar`.
400400
- For users who install PHP_CodeSniffer via the [Setup-PHP](https://github.com/shivammathur/setup-php/) action runner for GitHub Actions, nothing changes.
401401
- Users using a git clone will need to update the clone address from `git@github.com:squizlabs/PHP_CodeSniffer.git` to `git@github.com:PHPCSStandards/PHP_CodeSniffer.git`.
402402
- Contributors will need to fork the new repo and add both the new fork as well as the new repo as remotes to their local git copy of PHP_CodeSniffer.

src/Sniffs/AbstractPatternSniff.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,11 @@ protected function processPattern($patternInfo, File $phpcsFile, $stackPtr)
416416
$lastAddedStackPtr = null;
417417
$patternLen = count($pattern);
418418

419+
if (($stackPtr + $patternLen - $patternInfo['listen_pos']) > $phpcsFile->numTokens) {
420+
// Pattern can never match as there are not enough tokens left in the file.
421+
return false;
422+
}
423+
419424
for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) {
420425
if (isset($tokens[$stackPtr]) === false) {
421426
break;

src/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,12 @@ public function register()
2727
{
2828
$targets = Tokens::$contextSensitiveKeywords;
2929
$targets += [
30+
T_ANON_CLASS => T_ANON_CLASS,
3031
T_CLOSURE => T_CLOSURE,
31-
T_EMPTY => T_EMPTY,
3232
T_ENUM_CASE => T_ENUM_CASE,
33-
T_EVAL => T_EVAL,
34-
T_ISSET => T_ISSET,
3533
T_MATCH_DEFAULT => T_MATCH_DEFAULT,
3634
T_PARENT => T_PARENT,
3735
T_SELF => T_SELF,
38-
T_UNSET => T_UNSET,
3936
];
4037

4138
return $targets;

src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,14 @@ EnuM ENUM: string
4444
Case HEARTS;
4545
}
4646

47+
new Class {};
48+
new clasS extends stdClass {};
49+
new class {};
50+
51+
if (isset($a) && !empty($a)) { unset($a); }
52+
if (ISSET($a) && !Empty($a)) { UnSeT($a); }
53+
eval('foo');
54+
eVaL('foo');
55+
4756
__HALT_COMPILER(); // An exception due to phar support.
4857
function

src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,14 @@ enum ENUM: string
4444
case HEARTS;
4545
}
4646

47+
new class {};
48+
new class extends stdClass {};
49+
new class {};
50+
51+
if (isset($a) && !empty($a)) { unset($a); }
52+
if (isset($a) && !empty($a)) { unset($a); }
53+
eval('foo');
54+
eval('foo');
55+
4756
__HALT_COMPILER(); // An exception due to phar support.
4857
function

src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public function getErrorList()
4848
39 => 2,
4949
42 => 1,
5050
44 => 1,
51+
47 => 1,
52+
48 => 1,
53+
52 => 3,
54+
54 => 1,
5155
];
5256

5357
}//end getErrorList()

src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,23 @@ protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr)
221221
*/
222222
protected function getNamespaceOfScope(File $phpcsFile, $stackPtr)
223223
{
224-
$namespace = '\\';
225-
$namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr);
224+
$namespace = '\\';
225+
$tokens = $phpcsFile->getTokens();
226+
227+
while (($namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr)) !== false) {
228+
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($namespaceDeclaration + 1), null, true);
229+
if ($tokens[$nextNonEmpty]['code'] === T_NS_SEPARATOR) {
230+
// Namespace operator. Ignore.
231+
$stackPtr = ($namespaceDeclaration - 1);
232+
continue;
233+
}
226234

227-
if ($namespaceDeclaration !== false) {
228235
$endOfNamespaceDeclaration = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_CLOSE_TAG], $namespaceDeclaration);
229236
$namespace = $this->getDeclarationNameWithNamespace(
230237
$phpcsFile->getTokens(),
231238
($endOfNamespaceDeclaration - 1)
232239
);
240+
break;
233241
}
234242

235243
return $namespace;

src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,23 @@ public function addMissingBracketsError($phpcsFile, $stackPtr)
354354
}
355355

356356
if ($tokens[$after]['code'] === T_OPEN_PARENTHESIS) {
357+
if (isset($tokens[$after]['parenthesis_closer']) === false) {
358+
// Live coding/parse error. Ignore.
359+
return;
360+
}
361+
357362
$after = $tokens[$after]['parenthesis_closer'];
358363
continue;
359364
}
360365

361-
if ($tokens[$after]['code'] === T_OPEN_SQUARE_BRACKET) {
362-
$after = $tokens[$after]['bracket_closer'];
363-
continue;
364-
}
366+
if (($tokens[$after]['code'] === T_OPEN_SQUARE_BRACKET
367+
|| $tokens[$after]['code'] === T_OPEN_SHORT_ARRAY)
368+
) {
369+
if (isset($tokens[$after]['bracket_closer']) === false) {
370+
// Live coding/parse error. Ignore.
371+
return;
372+
}
365373

366-
if ($tokens[$after]['code'] === T_OPEN_SHORT_ARRAY) {
367374
$after = $tokens[$after]['bracket_closer'];
368375
continue;
369376
}

src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,14 @@ private function validateInlineEmbeddedPhp($phpcsFile, $stackPtr, $closeTag)
379379
}
380380

381381
// Check that there is one, and only one space at the start of the statement.
382-
$leadingSpace = 0;
383-
if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) {
382+
$leadingSpace = 0;
383+
$isLongOpenTag = false;
384+
if ($tokens[$stackPtr]['code'] === T_OPEN_TAG
385+
&& stripos($tokens[$stackPtr]['content'], '<?php') === 0
386+
) {
384387
// The long open tag token in a single line tag set always contains a single space after it.
385-
$leadingSpace = 1;
388+
$leadingSpace = 1;
389+
$isLongOpenTag = true;
386390
}
387391

388392
if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
@@ -394,7 +398,7 @@ private function validateInlineEmbeddedPhp($phpcsFile, $stackPtr, $closeTag)
394398
$data = [$leadingSpace];
395399
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data);
396400
if ($fix === true) {
397-
if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) {
401+
if ($isLongOpenTag === true) {
398402
$phpcsFile->fixer->replaceToken(($stackPtr + 1), '');
399403
} else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
400404
// Short open tag with too much whitespace.

src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,17 @@ class Baz {
183183
\EndsIn\CloseTag\Baz::something();
184184
}
185185
}
186+
187+
// Issue PHPCSStandards/PHP_CodeSniffer#553.
188+
namespace TestMe;
189+
190+
namespace\functionCall();
191+
namespace\anotherFunctionCall();
192+
193+
class SelfMemberReference
194+
{
195+
public function falseNegative()
196+
{
197+
$testResults[] = \TestMe\SelfMemberReference::test();
198+
}
199+
}

src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,17 @@ class Baz {
171171
self::something();
172172
}
173173
}
174+
175+
// Issue PHPCSStandards/PHP_CodeSniffer#553.
176+
namespace TestMe;
177+
178+
namespace\functionCall();
179+
namespace\anotherFunctionCall();
180+
181+
class SelfMemberReference
182+
{
183+
public function falseNegative()
184+
{
185+
$testResults[] = self::test();
186+
}
187+
}

src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function getErrorList()
4747
162 => 1,
4848
171 => 1,
4949
183 => 1,
50+
197 => 1,
5051
];
5152

5253
}//end getErrorList()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
// Intentional parse error. This has to be the last (and only) test in the file.
4+
// Live coding test. The sniff should stay silent.
5+
class ParseErrors {
6+
const A|(B PARSE_ERROR = null;
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
// Intentional parse error. This has to be the last (and only) test in the file.
4+
// Live coding test. The sniff should stay silent.
5+
$a = [10, 20] + [

src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ final class OperatorBracketUnitTest extends AbstractSniffUnitTest
3333
public function getErrorList($testFile='')
3434
{
3535
switch ($testFile) {
36-
case 'OperatorBracketUnitTest.inc':
36+
case 'OperatorBracketUnitTest.1.inc':
3737
return [
3838
3 => 1,
3939
6 => 1,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
// Intentional parse error. This has to be the last (and only) test in the file.
4+
// Live coding test. The sniff should stay silent.
5+
function
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
// Intentional parse error. This has to be the last (and only) test in the file.
4+
// Live coding test. The sniff should stay silent.
5+
function // Comment.

src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,22 @@ final class FunctionDeclarationUnitTest extends AbstractSniffUnitTest
2626
* The key of the array should represent the line number and the value
2727
* should represent the number of errors that should occur on that line.
2828
*
29+
* @param string $testFile The name of the file being tested.
30+
*
2931
* @return array<int, int>
3032
*/
31-
public function getErrorList()
33+
public function getErrorList($testFile='')
3234
{
33-
return [
34-
55 => 1,
35-
68 => 1,
36-
];
35+
switch ($testFile) {
36+
case 'FunctionDeclarationUnitTest.1.inc':
37+
return [
38+
55 => 1,
39+
68 => 1,
40+
];
41+
42+
default:
43+
return [];
44+
}//end switch
3745

3846
}//end getErrorList()
3947

src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ echo 'the PHP tag is correctly indented as an indent less than the previous code
265265
echo 'the PHP tag is incorrectly indented as the indent is more than 4 different from the indent of the previous code';
266266
?>
267267

268+
<?PHP echo 'Uppercase long open tag'; ?>
269+
270+
<?PHP echo 'Extra space after uppercase long open tag '; ?>
271+
268272
<?php
269273
// This test case file MUST always end with an unclosed long open PHP tag (with this comment) to prevent
270274
// the tests running into the "last PHP closing tag excepted" condition breaking tests.

src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc.fixed

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ echo 'the PHP tag is correctly indented as an indent less than the previous code
277277
echo 'the PHP tag is incorrectly indented as the indent is more than 4 different from the indent of the previous code';
278278
?>
279279

280+
<?PHP echo 'Uppercase long open tag'; ?>
281+
282+
<?PHP echo 'Extra space after uppercase long open tag '; ?>
283+
280284
<?php
281285
// This test case file MUST always end with an unclosed long open PHP tag (with this comment) to prevent
282286
// the tests running into the "last PHP closing tag excepted" condition breaking tests.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?
2+
3+
// This test case file MUST always start with a open PHP tag set (with this comment) to prevent
4+
// the tests running into the "first PHP open tag excepted" condition breaking the tests.
5+
// Tests related to that "first PHP open tag excepted" condition should go in separate files.
6+
7+
// This test case file only deals with SHORT OPEN TAGS.
8+
9+
?>
10+
11+
<?
12+
/* Contrary to the long open tag token, the short open tag token does not contain a space after the
13+
tag and the sniff should handle it accordingly. The test below protects against regressions
14+
related to https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/588. */
15+
?>
16+
<? echo 'one space after short open tag'; ?>
17+
18+
<? echo 'two spaces after short open tag'; ?>
19+
20+
<?echo 'without space after short open tag'; ?>
21+
22+
<?
23+
// This test case file MUST always end with an unclosed open PHP tag (with this comment) to prevent
24+
// the tests running into the "last PHP closing tag excepted" condition breaking tests.
25+
// Tests related to that "last PHP closing tag excepted" condition should go in separate files.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?
2+
3+
// This test case file MUST always start with a open PHP tag set (with this comment) to prevent
4+
// the tests running into the "first PHP open tag excepted" condition breaking the tests.
5+
// Tests related to that "first PHP open tag excepted" condition should go in separate files.
6+
7+
// This test case file only deals with SHORT OPEN TAGS.
8+
9+
?>
10+
11+
<?
12+
/* Contrary to the long open tag token, the short open tag token does not contain a space after the
13+
tag and the sniff should handle it accordingly. The test below protects against regressions
14+
related to https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/588. */
15+
?>
16+
<? echo 'one space after short open tag'; ?>
17+
18+
<? echo 'two spaces after short open tag'; ?>
19+
20+
<? echo 'without space after short open tag'; ?>
21+
22+
<?
23+
// This test case file MUST always end with an unclosed open PHP tag (with this comment) to prevent
24+
// the tests running into the "last PHP closing tag excepted" condition breaking tests.
25+
// Tests related to that "last PHP closing tag excepted" condition should go in separate files.

src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public function getErrorList($testFile='')
100100
258 => 1,
101101
263 => 1,
102102
264 => 1,
103+
270 => 1,
103104
];
104105

105106
case 'EmbeddedPhpUnitTest.2.inc':
@@ -190,6 +191,16 @@ public function getErrorList($testFile='')
190191
22 => 2,
191192
];
192193

194+
case 'EmbeddedPhpUnitTest.24.inc':
195+
$shortOpenTagDirective = (bool) ini_get('short_open_tag');
196+
if ($shortOpenTagDirective === true) {
197+
return [
198+
18 => 1,
199+
20 => 1,
200+
];
201+
}
202+
return [];
203+
193204
default:
194205
return [];
195206
}//end switch

0 commit comments

Comments
 (0)