Skip to content

Commit 390bffe

Browse files
committed
Generic.WhiteSpace.ScopeIndent now disables exact indent checking inside all arrays (ref #2281)
The sniff also now looks for exact property value changes throughout the file, which helps with unit testing as well
1 parent ed1faae commit 390bffe

File tree

8 files changed

+159
-189
lines changed

8 files changed

+159
-189
lines changed

package.xml

Lines changed: 8 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -17,179 +17,21 @@ http://pear.php.net/dtd/package-2.0.xsd">
1717
<date>2018-12-20</date>
1818
<time>10:54:00</time>
1919
<version>
20-
<release>3.4.0</release>
21-
<api>3.4.0</api>
20+
<release>3.4.1</release>
21+
<api>3.4.1</api>
2222
</version>
2323
<stability>
2424
<release>stable</release>
2525
<api>stable</api>
2626
</stability>
2727
<license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD 3-Clause License</license>
2828
<notes>
29-
- The Generic.Formatting.NoSpaceAfterCast sniff has been deprecated and will be removed in version 4
30-
-- The functionality of this sniff is now available in the Generic.Formatting.SpaceAfterCast sniff
31-
--- Include the Generic.Formatting.SpaceAfterCast sniff and set the "spacing" property to "0"
32-
-- As soon as possible, replace all instances of the old sniff code with the new sniff code and property setting
33-
--- The existing sniff will continue to work until version 4 has been released
34-
35-
- Rule include patterns in a ruleset.xml file are now evaluated as OR instead of AND
36-
-- Previously, a file had to match every include pattern and no exclude patterns to be included
37-
-- Now, a file must match at least one include pattern and no exclude patterns to be included
38-
-- This is a bug fix as include patterns are already documented to work this way
39-
- New token T_BITWISE_NOT added for the bitwise not operator
40-
-- This token was previously tokenized as T_NONE
41-
-- Any sniffs specifically looking for T_NONE tokens with a tilde as the contents must now also look for T_BITWISE_NOT
42-
-- Sniffs can continue looking for T_NONE as well as T_BITWISE_NOT to support older PHP_CodeSniffer versions
43-
- All types of binary casting are now tokenzied as T_BINARY_CAST
44-
-- Previously, the 'b' in 'b"some string with $var"' would be a T_BINARY_CAST, but only when the string contained a var
45-
-- This change ensures the 'b' is always tokenized as T_BINARY_CAST
46-
-- This change also converts '(binary)' from T_STRING_CAST to T_BINARY_CAST
47-
-- Thanks to Juliette Reinders Folmer for the help with this patch
48-
- Array properties set inside a ruleset.xml file can now extend a previous value instead of always overwriting it
49-
-- e.g., if you include a ruleset that defines forbidden functions, can you now add to that list instead of having to redefine it
50-
-- To use this feature, add extend="true" to the property tag
51-
--- e.g., property name="forbiddenFunctionNames" type="array" extend="true"
52-
-- Thanks to Michael Moravec for the patch
53-
- If $XDG_CACHE_HOME is set and points to a valid directory, it will be used for caching instead of the system temp directory
54-
- PHPCBF now disables parallel running if you are passing content on STDIN
55-
-- Stops an error from being shown after the fixed output is printed
56-
- The progress report now shows files with tokenizer errors as skipped (S) instead of a warning (W)
57-
-- The tokenizer error is still displayed in reports as normal
58-
-- Thanks to Juliette Reinders Folmer for the patch
59-
- The Squiz standard now ensures there is no space between an increment/decrement operator and its variable
60-
- The File::getMethodParamaters() method now includes a has_body array index in the return value
61-
-- TRUE if the method has no body (as with abstract and interface methods) or FALSe otherwise
62-
-- Thanks to Chris Wilkinson for the patch
63-
- The File::getTokensAsString() method now throws an exception if the $start param is invalid
64-
-- If the $length param is invalid, an empty string will be returned
65-
-- Stops an infinite loop when the function is passed invalid data
66-
-- Thanks to Juliette Reinders Folmer for the patch
67-
- Added new Generic.CodeAnalysis.EmptyPHPStatement sniff
68-
-- Warns when it finds empty PHP open/close tag combinations or superfluous semicolons
69-
-- Thanks to Juliette Reinders Folmer for the contribution
70-
- Added new Generic.Formatting.SpaceBeforeCast sniff
71-
-- Ensures there is exactly 1 space before a type cast, unless the cast statement is indented or mutli-line
72-
-- Thanks to Juliette Reinders Folmer for the contribution
73-
- Added new Generic.VersionControl.GitMergeConflict sniff
74-
-- Detects merge conflict artifacts left in files
75-
-- Thanks to Juliette Reinders Folmer for the contribution
76-
- Added Generic.WhiteSpace.IncrementDecrementSpacing sniff
77-
-- Ensures there is no space between the operator and the variable it applies to
78-
-- Thanks to Juliette Reinders Folmer for the contribution
79-
- Added PSR12.Functions.NullableTypeDeclaration sniff
80-
-- Ensures there is no space after the question mark in a nullable type declaration
81-
-- Thanks to Timo Schinkel for the contribution
82-
- A number of sniffs have improved support for methods in anonymous classes
83-
-- These sniffs would often throw the same error twice for functions in nested classes
84-
-- Error messages have also been changed to be less confusing
85-
-- The full list of affected sniffs is:
86-
--- Generic.NamingConventions.CamelCapsFunctionName
87-
--- PEAR.NamingConventions.ValidFunctionName
88-
--- PSR1.Methods.CamelCapsMethodName
89-
--- PSR2.Methods.MethodDeclaration
90-
--- Squiz.Scope.MethodScope
91-
--- Squiz.Scope.StaticThisUsage
92-
-- Thanks to Juliette Reinders Folmer for the patch
93-
- Generic.CodeAnalysis.UnusedFunctionParameter now only skips functions with empty bodies when the class implements an interface
94-
-- Thanks to Juliette Reinders Folmer for the patch
95-
- Generic.CodeAnalysis.UnusedFunctionParameter now has additional error codes to indicate where unused params were found
96-
-- The new error code prefixes are:
97-
--- FoundInExtendedClass: when the class extends another
98-
--- FoundInImplementedInterface: when the class implements an interface
99-
--- Found: used in all other cases, including closures
100-
-- The new error code suffixes are:
101-
--- BeforeLastUsed: the unused param was positioned before the last used param in the function signature
102-
--- AfterLastUsed: the unused param was positioned after the last used param in the function signature
103-
-- This makes the new error code list for this sniff:
104-
--- Found
105-
--- FoundBeforeLastUsed
106-
--- FoundAfterLastUsed
107-
--- FoundInExtendedClass
108-
--- FoundInExtendedClassBeforeLastUsed
109-
--- FoundInExtendedClassAfterLastUsed
110-
--- FoundInImplementedInterface
111-
--- FoundInImplementedInterfaceBeforeLastUsed
112-
--- FoundInImplementedInterfaceAfterLastUsed
113-
-- These errors code make it easier for specific cases to be ignored or promoted using a ruleset.xml file
114-
-- Thanks to Juliette Reinders Folmer for the contribution
115-
- Generic.Classes.DuplicateClassName now inspects traits for duplicate names as well as classes and interfaces
116-
-- Thanks to Chris Wilkinson for the patch
117-
- Generic.Files.InlineHTML now ignores a BOM at the start of the file
118-
-- Thanks to Chris Wilkinson for the patch
119-
- Generic.PHP.CharacterBeforePHPOpeningTag now ignores a BOM at the start of the file
120-
-- Thanks to Chris Wilkinson for the patch
121-
- Generic.Formatting.SpaceAfterCast now has a setting to specify how many spaces are required after a type cast
122-
-- Default remains 1
123-
-- Override the "spacing" setting in a ruleset.xml file to change
124-
-- Thanks to Juliette Reinders Folmer for the patch
125-
- Generic.Formatting.SpaceAfterCast now has a setting to ignore newline characters after a type cast
126-
-- Default remains FALSE, so newlines are not allowed
127-
-- Override the "ignoreNewlines" setting in a ruleset.xml file to change
128-
-- Thanks to Juliette Reinders Folmer for the patch
129-
- Generic.Formatting.SpaceAfterNot now has a setting to specify how many spaces are required after a NOT operator
130-
-- Default remains 1
131-
-- Override the "spacing" setting in a ruleset.xml file to change
132-
-- Thanks to Juliette Reinders Folmer for the patch
133-
- Generic.Formatting.SpaceAfterNot now has a setting to ignore newline characters after the NOT operator
134-
-- Default remains FALSE, so newlines are not allowed
135-
-- Override the "ignoreNewlines" setting in a ruleset.xml file to change
136-
-- Thanks to Juliette Reinders Folmer for the patch
137-
- PEAR.Functions.FunctionDeclaration now checks spacing before the opening parenthesis of functions with no body
138-
-- Thanks to Chris Wilkinson for the patch
139-
- PEAR.Functions.FunctionDeclaration now enforces no space before the semicolon in functions with no body
140-
-- Thanks to Chris Wilkinson for the patch
141-
- PSR2.Classes.PropertyDeclaration now checks the order of property modifier keywords
142-
-- This is a rule that is documented in PSR-2 but was not enforced by the included PSR2 standard until now
143-
-- This sniff is also able to fix the order of the modifier keywords if they are incorrect
144-
-- Thanks to Juliette Reinders Folmer for the patch
145-
- PSR2.Methods.MethodDeclaration now checks method declarations inside traits
146-
-- Thanks to Chris Wilkinson for the patch
147-
- Squiz.Commenting.InlineComment now has better detection of comment block boundaries
148-
- Squiz.Classes.ClassFileName now checks that a trait name matches the filename
149-
-- Thanks to Chris Wilkinson for the patch
150-
- Squiz.Classes.SelfMemberReference now supports scoped declarations and anonymous classes
151-
-- Thanks to Juliette Reinders Folmer for the patch
152-
- Squiz.Classes.SelfMemberReference now fixes multiple errors at once, increasing fixer performance
153-
-- Thanks to Gabriel Ostrolucký for the patch
154-
- Squiz.Functions.LowercaseFunctionKeywords now checks abstract and final prefixes, and auto-fixes errors
155-
-- Thanks to Juliette Reinders Folmer for the patch
156-
- Squiz.Objects.ObjectMemberComma.Missing has been renamed to Squiz.Objects.ObjectMemberComma.Found
157-
-- The error is thrown when the comma is found but not required, so the error code was incorrect
158-
-- If you are referencing the old error code in a ruleset XML file, please use the new code instead
159-
-- If you wish to maintain backwards compatibility, you can provide rules for both the old and new codes
160-
-- Thanks to Juliette Reinders Folmer for the patch
161-
- Squiz.WhiteSpace.ObjectOperatorSpacing is now more tolerant of parse errors
162-
- Squiz.WhiteSpace.ObjectOperatorSpacing now fixes errors more efficiently
163-
-- Thanks to Juliette Reinders Folmer for the patch
164-
- Fixed bug #2109 : Generic.Functions.CallTimePassByReference false positive for bitwise and used in function argument
165-
- Fixed bug #2165 : Conflict between Squiz.Arrays.ArrayDeclaration and ScopeIndent sniffs when heredoc used in array
166-
- Fixed bug #2167 : Generic.WhiteSpace.ScopeIndent shows invalid error when scope opener indented inside inline HTML
167-
- Fixed bug #2178 : Generic.NamingConventions.ConstructorName matches methods in anon classes with same name as containing class
168-
-- Thanks to Juliette Reinders Folmer for the patch
169-
- Fixed bug #2190 : PEAR.Functions.FunctionCallSignature incorrect error when encountering trailing PHPCS annotation
170-
-- Thanks to Juliette Reinders Folmer for the patch
171-
- Fixed bug #2194 : Generic.Whitespace.LanguageConstructSpacing should not be checking namespace operators
172-
-- Thanks to Juliette Reinders Folmer for the patch
173-
- Fixed bug #2202 : Squiz.WhiteSpace.OperatorSpacing throws error for negative index when using curly braces for string access
174-
-- Same issue fixed in Squiz.Formatting.OperatorBracket
175-
-- Thanks to Andreas Buchenrieder for the patch
176-
- Fixed bug #2210 : Generic.NamingConventions.CamelCapsFunctionName not ignoring SoapClient __getCookies() method
177-
-- Thanks to Juliette Reinders Folmer for the patch
178-
- Fixed bug #2211 : PSR2.Methods.MethodDeclaration gets confused over comments between modifier keywords
179-
-- Thanks to Juliette Reinders Folmer for the patch
180-
- Fixed bug #2212 : FUNCTION and CONST in use groups being tokenised as T_FUNCTION and T_CONST
181-
-- Thanks to Chris Wilkinson for the patch
182-
- Fixed bug #2214 : File::getMemberProperties() is recognizing method params as properties
183-
-- Thanks to Juliette Reinders Folmer for the patch
184-
- Fixed bug #2236 : Memory info measurement unit is Mb but probably should be MB
185-
- Fixed bug #2246 : CSS tokenizer does not tokenize class names correctly when they contain the string NEW
186-
-- Thanks to Juliette Reinders Folmer for the patch
187-
- Fixed bug #2278 : Squiz.Operators.ComparisonOperatorUsage false positive when inline IF contained in parentheses
188-
-- Thanks to Arnout Boks for the patch
189-
- Fixed bug #2284 : Squiz.Functions.FunctionDeclarationArgumentSpacing removing type hint during fixing
190-
-- Thanks to Michał Bundyra for the patch
191-
- Fixed bug #2297 : Anonymous class not tokenized correctly when used as argument to another anon class
192-
-- Thanks to Michał Bundyra for the patch
29+
- T_PHPCS_SET tokens now contain sniffCode, sniffProperty, and sniffPropertyValue indexes
30+
-- Sniffs can use this information instead of having to parse the token content manually
31+
- Generic.WhiteSpace.ScopeIndent now respects changes to the "exact" property using phpcs:set mid-way through a file
32+
-- This allows you change the "exact" rule for only some parts of a file
33+
- Generic.WhiteSpace.ScopeIndent now disables exact indent checking inside all arrays
34+
-- Previously, this was only done when using long array syntax, but it now works for short array syntax as well
19335
</notes>
19436
<contents>
19537
<dir name="/">

src/Config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Config
2323
*
2424
* @var string
2525
*/
26-
const VERSION = '3.4.0';
26+
const VERSION = '3.4.1';
2727

2828
/**
2929
* Package stability; either stable, beta or alpha.

src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,12 @@ public function process(File $phpcsFile, $stackPtr)
142142
}
143143
}
144144

145-
$lastOpenTag = $stackPtr;
146-
$lastCloseTag = null;
147-
$openScopes = [];
148-
$adjustments = [];
149-
$setIndents = [];
145+
$lastOpenTag = $stackPtr;
146+
$lastCloseTag = null;
147+
$openScopes = [];
148+
$adjustments = [];
149+
$setIndents = [];
150+
$disableExactEnd = 0;
150151

151152
$tokens = $phpcsFile->getTokens();
152153
$first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr);
@@ -180,20 +181,65 @@ public function process(File $phpcsFile, $stackPtr)
180181
$this->exact = (bool) $this->exact;
181182
$this->tabIndent = (bool) $this->tabIndent;
182183

184+
$checkAnnotations = $phpcsFile->config->annotations;
185+
183186
for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
184187
if ($i === false) {
185188
// Something has gone very wrong; maybe a parse error.
186189
break;
187190
}
188191

192+
if ($checkAnnotations === true
193+
&& $tokens[$i]['code'] === T_PHPCS_SET
194+
&& isset($tokens[$i]['sniffCode']) === true
195+
&& $tokens[$i]['sniffCode'] === 'Generic.WhiteSpace.ScopeIndent'
196+
&& $tokens[$i]['sniffProperty'] === 'exact'
197+
) {
198+
$value = $tokens[$i]['sniffPropertyValue'];
199+
if ($value === 'true') {
200+
$value = true;
201+
} else if ($value === 'false') {
202+
$value = false;
203+
} else {
204+
$value = (bool) $value;
205+
}
206+
207+
$this->exact = $value;
208+
209+
if ($this->debug === true) {
210+
$line = $tokens[$i]['line'];
211+
if ($this->exact === true) {
212+
$value = 'true';
213+
} else {
214+
$value = 'false';
215+
}
216+
217+
echo "* token $i on line $line set exact flag to $value *".PHP_EOL;
218+
}
219+
}//end if
220+
189221
$checkToken = null;
190222
$checkIndent = null;
191223

192-
$exact = (bool) $this->exact;
193-
if ($exact === true && isset($tokens[$i]['nested_parenthesis']) === true) {
194-
// Don't check indents exactly between parenthesis as they
195-
// tend to have custom rules, such as with multi-line function calls
196-
// and control structure conditions.
224+
/*
225+
Don't check indents exactly between parenthesis or arrays as they
226+
tend to have custom rules, such as with multi-line function calls
227+
and control structure conditions.
228+
*/
229+
230+
$exact = $this->exact;
231+
232+
if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
233+
$disableExactEnd = max($disableExactEnd, $tokens[$i]['bracket_closer']);
234+
}
235+
236+
if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS
237+
&& isset($tokens[$i]['parenthesis_closer']) === true
238+
) {
239+
$disableExactEnd = max($disableExactEnd, $tokens[$i]['parenthesis_closer']);
240+
}
241+
242+
if ($exact === true && $i < $disableExactEnd) {
197243
$exact = false;
198244
}
199245

src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,26 @@ default:
12941294
break;
12951295
}
12961296

1297+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact true
1298+
$shortArray = [
1299+
'hello',
1300+
'world',
1301+
];
1302+
1303+
$shortArray = array(
1304+
'hello',
1305+
'world',
1306+
);
1307+
1308+
function foo() {
1309+
echo 'foo';
1310+
echo 'bar';
1311+
if ($foo) {
1312+
echo 'baz';
1313+
}
1314+
}
1315+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact false
1316+
12971317
function test() {
12981318
return [
12991319
<<<'SQLDATA'

src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,26 @@ switch ( $a ) {
12941294
break;
12951295
}
12961296

1297+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact true
1298+
$shortArray = [
1299+
'hello',
1300+
'world',
1301+
];
1302+
1303+
$shortArray = array(
1304+
'hello',
1305+
'world',
1306+
);
1307+
1308+
function foo() {
1309+
echo 'foo';
1310+
echo 'bar';
1311+
if ($foo) {
1312+
echo 'baz';
1313+
}
1314+
}
1315+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact false
1316+
12971317
function test() {
12981318
return [
12991319
<<<'SQLDATA'

src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,26 @@ default:
12941294
break;
12951295
}
12961296

1297+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact true
1298+
$shortArray = [
1299+
'hello',
1300+
'world',
1301+
];
1302+
1303+
$shortArray = array(
1304+
'hello',
1305+
'world',
1306+
);
1307+
1308+
function foo() {
1309+
echo 'foo';
1310+
echo 'bar';
1311+
if ($foo) {
1312+
echo 'baz';
1313+
}
1314+
}
1315+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact false
1316+
12971317
function test() {
12981318
return [
12991319
<<<'SQLDATA'

src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,26 @@ switch ( $a ) {
12941294
break;
12951295
}
12961296

1297+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact true
1298+
$shortArray = [
1299+
'hello',
1300+
'world',
1301+
];
1302+
1303+
$shortArray = array(
1304+
'hello',
1305+
'world',
1306+
);
1307+
1308+
function foo() {
1309+
echo 'foo';
1310+
echo 'bar';
1311+
if ($foo) {
1312+
echo 'baz';
1313+
}
1314+
}
1315+
// phpcs:set Generic.WhiteSpace.ScopeIndent exact false
1316+
12971317
function test() {
12981318
return [
12991319
<<<'SQLDATA'

0 commit comments

Comments
 (0)