Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1432769
SpacesFixer.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
SpacesFixer.php
View Options
<?php
/**
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
*
* @package PHPCSUtils
* @copyright 2019-2020 PHPCSUtils Contributors
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
* @link https://github.com/PHPCSStandards/PHPCSUtils
*/
namespace
PHPCSUtils\Fixers
;
use
PHP_CodeSniffer\Exceptions\RuntimeException
;
use
PHP_CodeSniffer\Files\File
;
use
PHP_CodeSniffer\Util\Tokens
;
use
PHPCSUtils\Utils\Numbers
;
/**
* Utility to check and, if necessary, fix the whitespace between two tokens.
*
* @since 1.0.0
*/
final
class
SpacesFixer
{
/**
* Check the whitespace between two tokens, throw an error if it doesn't match the
* expected whitespace and if relevant, fix it.
*
* Note:
* - This method will not auto-fix if there is anything but whitespace between the two
* tokens. In that case, it will throw a non-fixable error/warning.
* - If `'newline'` is expected and _no_ new line is encountered, a new line will be added,
* but no assumptions will be made about the intended indentation of the code.
* This should be handled by a (separate) indentation sniff.
* - If `'newline'` is expected and multiple new lines are encountered, this will be accepted
* as valid.
* No assumptions are made about whether additional blank lines are allowed or not.
* If _exactly_ one line is desired, combine this fixer with the {@see \PHPCSUtils\Fixers\BlankLineFixer}
* (upcoming).
* - The fixer will not leave behind any trailing spaces on the original line when fixing
* to `'newline'`, but it will not correct _existing_ trailing spaces when there already
* is a new line in place.
* - This method can optionally record a metric for this check which will be displayed
* when the end-user requests the "info" report.
*
* @since 1.0.0
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the token which should be used
* when reporting an issue.
* @param int $secondPtr The stack pointer to the second token.
* This token can be before or after the `$stackPtr`,
* but should only be separated from the `$stackPtr`
* by whitespace and/or comments/annotations.
* @param string|int $expectedSpaces Number of spaces to enforce.
* Valid values:
* - (int) Number of spaces. Must be `0` or more.
* - (string) `'newline'`.
* @param string $errorTemplate Error message template.
* Note: _The placeholder replacement phrase will be
* in human readable English and include "spaces"/
* "new line", so no need to include that in the template._
* This string should contain two placeholders:
* - `%1$s` = expected spaces phrase.
* - `%2$s` = found spaces phrase.
* @param string $errorCode A violation code unique to the sniff message.
* Defaults to `"Found"`.
* It is strongly recommended to change this if
* this fixer is used for different errors in the
* same sniff.
* @param string $errorType Optional. Whether to report the issue as a
* `"warning"` or an `"error"`. Defaults to `"error"`.
* @param int $errorSeverity Optional. The severity level for this message.
* A value of `0` will be converted into the default
* severity level.
* @param string $metricName Optional. The name of the metric to record.
* This can be a short description phrase.
* Leave empty to not record metrics.
*
* @return void
*
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the tokens passed do not exist or are whitespace
* tokens.
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If `$expectedSpaces` is not a valid value.
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the tokens passed are separated by more than just
* empty (whitespace + comments/annotations) tokens.
*/
public
static
function
checkAndFix
(
File
$phpcsFile
,
$stackPtr
,
$secondPtr
,
$expectedSpaces
,
$errorTemplate
,
$errorCode
=
'Found'
,
$errorType
=
'error'
,
$errorSeverity
=
0
,
$metricName
=
''
)
{
$tokens
=
$phpcsFile
->
getTokens
();
/*
* Validate the received function input.
*/
if
(
isset
(
$tokens
[
$stackPtr
],
$tokens
[
$secondPtr
])
===
false
||
$tokens
[
$stackPtr
][
'code'
]
===
\T_WHITESPACE
||
$tokens
[
$secondPtr
][
'code'
]
===
\T_WHITESPACE
)
{
throw
new
RuntimeException
(
'The $stackPtr and the $secondPtr token must exist and not be whitespace'
);
}
$expected
=
false
;
if
(
$expectedSpaces
===
'newline'
)
{
$expected
=
$expectedSpaces
;
}
elseif
(
\is_int
(
$expectedSpaces
)
===
true
&&
$expectedSpaces
>=
0
)
{
$expected
=
$expectedSpaces
;
}
elseif
(
\is_string
(
$expectedSpaces
)
===
true
&&
Numbers
::
isDecimalInt
(
$expectedSpaces
)
===
true
)
{
$expected
=
(
int
)
$expectedSpaces
;
}
if
(
$expected
===
false
)
{
throw
new
RuntimeException
(
'The $expectedSpaces setting should be either "newline", 0 or a positive integer'
);
}
$ptrA
=
$stackPtr
;
$ptrB
=
$secondPtr
;
if
(
$stackPtr
>
$secondPtr
)
{
$ptrA
=
$secondPtr
;
$ptrB
=
$stackPtr
;
}
$nextNonEmpty
=
$phpcsFile
->
findNext
(
Tokens
::
$emptyTokens
,
(
$ptrA
+
1
),
null
,
true
);
if
(
$nextNonEmpty
!==
false
&&
$nextNonEmpty
<
$ptrB
)
{
throw
new
RuntimeException
(
'The $stackPtr and the $secondPtr token must be adjacent tokens separated only'
.
' by whitespace and/or comments'
);
}
/*
* Determine how many spaces are between the two tokens.
*/
$found
=
0
;
$foundPhrase
=
'no spaces'
;
if
(
$tokens
[
$ptrA
][
'line'
]
!==
$tokens
[
$ptrB
][
'line'
])
{
$found
=
'newline'
;
$foundPhrase
=
'a new line'
;
if
((
$tokens
[
$ptrA
][
'line'
]
+
1
)
!==
$tokens
[
$ptrB
][
'line'
])
{
$foundPhrase
=
'multiple new lines'
;
}
}
elseif
((
$ptrA
+
1
)
!==
$ptrB
)
{
if
(
$tokens
[(
$ptrA
+
1
)][
'code'
]
===
\T_WHITESPACE
)
{
$found
=
$tokens
[(
$ptrA
+
1
)][
'length'
];
$foundPhrase
=
$found
.
((
$found
===
1
)
?
' space'
:
' spaces'
);
}
else
{
$found
=
'non-whitespace tokens'
;
$foundPhrase
=
'non-whitespace tokens'
;
}
}
if
(
$metricName
!==
''
)
{
$phpcsFile
->
recordMetric
(
$stackPtr
,
$metricName
,
$foundPhrase
);
}
if
(
$found
===
$expected
)
{
return
;
}
/*
* Handle the violation message.
*/
$expectedPhrase
=
'no space'
;
if
(
$expected
===
'newline'
)
{
$expectedPhrase
=
'a new line'
;
}
elseif
(
$expected
===
1
)
{
$expectedPhrase
=
$expected
.
' space'
;
}
elseif
(
$expected
>
1
)
{
$expectedPhrase
=
$expected
.
' spaces'
;
}
$fixable
=
true
;
$nextNonWhitespace
=
$phpcsFile
->
findNext
(
\T_WHITESPACE
,
(
$ptrA
+
1
),
null
,
true
);
if
(
$nextNonWhitespace
!==
$ptrB
)
{
// Comment found between the tokens and we don't know where it should go, so don't auto-fix.
$fixable
=
false
;
}
if
(
$found
===
'newline'
&&
$tokens
[
$ptrA
][
'code'
]
===
\T_COMMENT
&&
\substr
(
$tokens
[
$ptrA
][
'content'
],
-
2
)
!==
'*/'
)
{
/*
* $ptrA is a slash-style trailing comment, removing the new line would comment out
* the code, so don't auto-fix.
*/
$fixable
=
false
;
}
$method
=
'add'
;
$method
.=
(
$fixable
===
true
)
?
'Fixable'
:
''
;
$method
.=
(
$errorType
===
'error'
)
?
'Error'
:
'Warning'
;
$recorded
=
$phpcsFile
->
$method
(
$errorTemplate
,
$stackPtr
,
$errorCode
,
[
$expectedPhrase
,
$foundPhrase
],
$errorSeverity
);
if
(
$fixable
===
false
||
$recorded
===
false
)
{
return
;
}
/*
* Fix the violation.
*/
$phpcsFile
->
fixer
->
beginChangeset
();
/*
* Remove existing whitespace. No need to check if it's whitespace as otherwise the fixer
* wouldn't have kicked in.
*/
for
(
$i
=
(
$ptrA
+
1
);
$i
<
$ptrB
;
$i
++)
{
$phpcsFile
->
fixer
->
replaceToken
(
$i
,
''
);
}
// If necessary: add the correct amount whitespace.
if
(
$expected
!==
0
)
{
if
(
$expected
===
'newline'
)
{
$phpcsFile
->
fixer
->
addContent
(
$ptrA
,
$phpcsFile
->
eolChar
);
}
else
{
$replacement
=
$tokens
[
$ptrA
][
'content'
]
.
\str_repeat
(
' '
,
$expected
);
$phpcsFile
->
fixer
->
replaceToken
(
$ptrA
,
$replacement
);
}
}
$phpcsFile
->
fixer
->
endChangeset
();
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 22:17 (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a4/76/de3cb7899457560f2a469e2fe63b
Default Alt Text
SpacesFixer.php (10 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment