Skip to content

Commit 6441866

Browse files
committed
Merge branch 'php-8.2/file-getclassproperties-add-support-for-readonly-classes' of https://github.com/jrfnl/PHP_CodeSniffer
2 parents 2922ea1 + 3f194e7 commit 6441866

File tree

4 files changed

+260
-0
lines changed

4 files changed

+260
-0
lines changed

package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
148148
<file baseinstalldir="" name="FindImplementedInterfaceNamesTest.php" role="test" />
149149
<file baseinstalldir="" name="FindStartOfStatementTest.inc" role="test" />
150150
<file baseinstalldir="" name="FindStartOfStatementTest.php" role="test" />
151+
<file baseinstalldir="" name="GetClassPropertiesTest.inc" role="test" />
152+
<file baseinstalldir="" name="GetClassPropertiesTest.php" role="test" />
151153
<file baseinstalldir="" name="GetMemberPropertiesTest.inc" role="test" />
152154
<file baseinstalldir="" name="GetMemberPropertiesTest.php" role="test" />
153155
<file baseinstalldir="" name="GetMethodParametersTest.inc" role="test" />
@@ -2157,6 +2159,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
21572159
<install as="CodeSniffer/Core/File/FindImplementedInterfaceNamesTest.inc" name="tests/Core/File/FindImplementedInterfaceNamesTest.inc" />
21582160
<install as="CodeSniffer/Core/File/FindStartOfStatementTest.php" name="tests/Core/File/FindStartOfStatementTest.php" />
21592161
<install as="CodeSniffer/Core/File/FindStartOfStatementTest.inc" name="tests/Core/File/FindStartOfStatementTest.inc" />
2162+
<install as="CodeSniffer/Core/File/GetClassPropertiesTest.php" name="tests/Core/File/GetClassPropertiesTest.php" />
2163+
<install as="CodeSniffer/Core/File/GetClassPropertiesTest.inc" name="tests/Core/File/GetClassPropertiesTest.inc" />
21602164
<install as="CodeSniffer/Core/File/GetMemberPropertiesTest.php" name="tests/Core/File/GetMemberPropertiesTest.php" />
21612165
<install as="CodeSniffer/Core/File/GetMemberPropertiesTest.inc" name="tests/Core/File/GetMemberPropertiesTest.inc" />
21622166
<install as="CodeSniffer/Core/File/GetMethodParametersTest.php" name="tests/Core/File/GetMethodParametersTest.php" />
@@ -2279,6 +2283,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
22792283
<install as="CodeSniffer/Core/File/FindImplementedInterfaceNamesTest.inc" name="tests/Core/File/FindImplementedInterfaceNamesTest.inc" />
22802284
<install as="CodeSniffer/Core/File/FindStartOfStatementTest.php" name="tests/Core/File/FindStartOfStatementTest.php" />
22812285
<install as="CodeSniffer/Core/File/FindStartOfStatementTest.inc" name="tests/Core/File/FindStartOfStatementTest.inc" />
2286+
<install as="CodeSniffer/Core/File/GetClassPropertiesTest.php" name="tests/Core/File/GetClassPropertiesTest.php" />
2287+
<install as="CodeSniffer/Core/File/GetClassPropertiesTest.inc" name="tests/Core/File/GetClassPropertiesTest.inc" />
22822288
<install as="CodeSniffer/Core/File/GetMemberPropertiesTest.php" name="tests/Core/File/GetMemberPropertiesTest.php" />
22832289
<install as="CodeSniffer/Core/File/GetMemberPropertiesTest.inc" name="tests/Core/File/GetMemberPropertiesTest.inc" />
22842290
<install as="CodeSniffer/Core/File/GetMethodParametersTest.php" name="tests/Core/File/GetMethodParametersTest.php" />

src/Files/File.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,6 +1960,7 @@ public function getMemberProperties($stackPtr)
19601960
* array(
19611961
* 'is_abstract' => false, // true if the abstract keyword was found.
19621962
* 'is_final' => false, // true if the final keyword was found.
1963+
* 'is_readonly' => false, // true if the readonly keyword was found.
19631964
* );
19641965
* </code>
19651966
*
@@ -1979,13 +1980,15 @@ public function getClassProperties($stackPtr)
19791980
$valid = [
19801981
T_FINAL => T_FINAL,
19811982
T_ABSTRACT => T_ABSTRACT,
1983+
T_READONLY => T_READONLY,
19821984
T_WHITESPACE => T_WHITESPACE,
19831985
T_COMMENT => T_COMMENT,
19841986
T_DOC_COMMENT => T_DOC_COMMENT,
19851987
];
19861988

19871989
$isAbstract = false;
19881990
$isFinal = false;
1991+
$isReadonly = false;
19891992

19901993
for ($i = ($stackPtr - 1); $i > 0; $i--) {
19911994
if (isset($valid[$this->tokens[$i]['code']]) === false) {
@@ -2000,12 +2003,17 @@ public function getClassProperties($stackPtr)
20002003
case T_FINAL:
20012004
$isFinal = true;
20022005
break;
2006+
2007+
case T_READONLY:
2008+
$isReadonly = true;
2009+
break;
20032010
}
20042011
}//end for
20052012

20062013
return [
20072014
'is_abstract' => $isAbstract,
20082015
'is_final' => $isFinal,
2016+
'is_readonly' => $isReadonly,
20092017
];
20102018

20112019
}//end getClassProperties()
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/* testNotAClass */
4+
interface NotAClass {}
5+
6+
/* testAnonClass */
7+
$anon = new class() {};
8+
9+
/* testEnum */
10+
enum NotAClassEither {}
11+
12+
/* testClassWithoutProperties */
13+
class ClassWithoutProperties {}
14+
15+
/* testAbstractClass */
16+
abstract class AbstractClass {}
17+
18+
/* testFinalClass */
19+
final class FinalClass {}
20+
21+
/* testReadonlyClass */
22+
readonly class ReadOnlyClass {}
23+
24+
/* testFinalReadonlyClass */
25+
final readonly class FinalReadOnlyClass extends Foo {}
26+
27+
/* testReadonlyFinalClass */
28+
readonly /*comment*/ final class ReadOnlyFinalClass {}
29+
30+
/* testAbstractReadonlyClass */
31+
abstract readonly class AbstractReadOnlyClass {}
32+
33+
/* testReadonlyAbstractClass */
34+
readonly
35+
abstract
36+
class ReadOnlyAbstractClass {}
37+
38+
/* testWithCommentsAndNewLines */
39+
abstract
40+
/* comment */
41+
class ClassWithCommentsAndNewLines {}
42+
43+
/* testWithDocblockWithoutProperties */
44+
/**
45+
* Class docblock.
46+
*
47+
* @package SomePackage
48+
*
49+
* @phpcs:disable Standard.Cat.SniffName -- Just because.
50+
*/
51+
class ClassWithDocblock {}
52+
53+
/* testParseErrorAbstractFinal */
54+
final /* comment */
55+
56+
abstract // Intentional parse error, class cannot both be final and abstract.
57+
58+
class AbstractFinal {}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
/**
3+
* Tests for the \PHP_CodeSniffer\Files\File:getClassProperties method.
4+
*
5+
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
6+
* @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600)
7+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\Core\File;
11+
12+
use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;
13+
14+
class GetClassPropertiesTest extends AbstractMethodUnitTest
15+
{
16+
17+
18+
/**
19+
* Test receiving an expected exception when a non class token is passed.
20+
*
21+
* @param string $testMarker The comment which prefaces the target token in the test file.
22+
* @param array $tokenType The type of token to look for after the marker.
23+
*
24+
* @dataProvider dataNotAClassException
25+
*
26+
* @expectedException PHP_CodeSniffer\Exceptions\RuntimeException
27+
* @expectedExceptionMessage $stackPtr must be of type T_CLASS
28+
*
29+
* @return void
30+
*/
31+
public function testNotAClassException($testMarker, $tokenType)
32+
{
33+
$target = $this->getTargetToken($testMarker, $tokenType);
34+
self::$phpcsFile->getClassProperties($target);
35+
36+
}//end testNotAClassException()
37+
38+
39+
/**
40+
* Data provider.
41+
*
42+
* @see testNotAClassException() For the array format.
43+
*
44+
* @return array
45+
*/
46+
public function dataNotAClassException()
47+
{
48+
return [
49+
'interface' => [
50+
'/* testNotAClass */',
51+
\T_INTERFACE,
52+
],
53+
'anon-class' => [
54+
'/* testAnonClass */',
55+
\T_ANON_CLASS,
56+
],
57+
'enum' => [
58+
'/* testEnum */',
59+
\T_ENUM,
60+
],
61+
];
62+
63+
}//end dataNotAClassException()
64+
65+
66+
/**
67+
* Test retrieving the properties for a class declaration.
68+
*
69+
* @param string $testMarker The comment which prefaces the target token in the test file.
70+
* @param array $expected Expected function output.
71+
*
72+
* @dataProvider dataGetClassProperties
73+
*
74+
* @return void
75+
*/
76+
public function testGetClassProperties($testMarker, $expected)
77+
{
78+
$class = $this->getTargetToken($testMarker, \T_CLASS);
79+
$result = self::$phpcsFile->getClassProperties($class);
80+
$this->assertSame($expected, $result);
81+
82+
}//end testGetClassProperties()
83+
84+
85+
/**
86+
* Data provider.
87+
*
88+
* @see testGetClassProperties() For the array format.
89+
*
90+
* @return array
91+
*/
92+
public function dataGetClassProperties()
93+
{
94+
return [
95+
'no-properties' => [
96+
'/* testClassWithoutProperties */',
97+
[
98+
'is_abstract' => false,
99+
'is_final' => false,
100+
'is_readonly' => false,
101+
],
102+
],
103+
'abstract' => [
104+
'/* testAbstractClass */',
105+
[
106+
'is_abstract' => true,
107+
'is_final' => false,
108+
'is_readonly' => false,
109+
],
110+
],
111+
'final' => [
112+
'/* testFinalClass */',
113+
[
114+
'is_abstract' => false,
115+
'is_final' => true,
116+
'is_readonly' => false,
117+
],
118+
],
119+
'readonly' => [
120+
'/* testReadonlyClass */',
121+
[
122+
'is_abstract' => false,
123+
'is_final' => false,
124+
'is_readonly' => true,
125+
],
126+
],
127+
'final-readonly' => [
128+
'/* testFinalReadonlyClass */',
129+
[
130+
'is_abstract' => false,
131+
'is_final' => true,
132+
'is_readonly' => true,
133+
],
134+
],
135+
'readonly-final' => [
136+
'/* testReadonlyFinalClass */',
137+
[
138+
'is_abstract' => false,
139+
'is_final' => true,
140+
'is_readonly' => true,
141+
],
142+
],
143+
'abstract-readonly' => [
144+
'/* testAbstractReadonlyClass */',
145+
[
146+
'is_abstract' => true,
147+
'is_final' => false,
148+
'is_readonly' => true,
149+
],
150+
],
151+
'readonly-abstract' => [
152+
'/* testReadonlyAbstractClass */',
153+
[
154+
'is_abstract' => true,
155+
'is_final' => false,
156+
'is_readonly' => true,
157+
],
158+
],
159+
'comments-and-new-lines' => [
160+
'/* testWithCommentsAndNewLines */',
161+
[
162+
'is_abstract' => true,
163+
'is_final' => false,
164+
'is_readonly' => false,
165+
],
166+
],
167+
'no-properties-with-docblock' => [
168+
'/* testWithDocblockWithoutProperties */',
169+
[
170+
'is_abstract' => false,
171+
'is_final' => false,
172+
'is_readonly' => false,
173+
],
174+
],
175+
'abstract-final-parse-error' => [
176+
'/* testParseErrorAbstractFinal */',
177+
[
178+
'is_abstract' => true,
179+
'is_final' => true,
180+
'is_readonly' => false,
181+
],
182+
],
183+
];
184+
185+
}//end dataGetClassProperties()
186+
187+
188+
}//end class

0 commit comments

Comments
 (0)