mirror of
https://github.com/10h30/genesis-simple-sidebars.git
synced 2026-07-14 12:06:14 +09:00
Introducing coding standards validation.
This commit is contained in:
committed by
Nathan Rice
parent
6e40c921ab
commit
fd504d41ac
+78
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantArraysUsingConstSniff.
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
|
||||
namespace PHPCompatibility\Sniffs\InitialValue;
|
||||
|
||||
use PHPCompatibility\Sniff;
|
||||
use PHP_CodeSniffer_File as File;
|
||||
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantArraysUsingConstSniff.
|
||||
*
|
||||
* Constant arrays using the const keyword in PHP 5.6
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
class NewConstantArraysUsingConstSniff extends Sniff
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_CONST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes this test, when one of its tokens is encountered.
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the current token in the
|
||||
* stack passed in $tokens.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process(File $phpcsFile, $stackPtr)
|
||||
{
|
||||
if ($this->supportsBelow('5.5') !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
$find = array(
|
||||
T_ARRAY => T_ARRAY,
|
||||
T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY,
|
||||
);
|
||||
|
||||
while (($hasArray = $phpcsFile->findNext($find, ($stackPtr + 1), null, false, null, true)) !== false) {
|
||||
$phpcsFile->addError(
|
||||
'Constant arrays using the "const" keyword are not allowed in PHP 5.5 or earlier',
|
||||
$hasArray,
|
||||
'Found'
|
||||
);
|
||||
|
||||
// Skip past the content of the array.
|
||||
$stackPtr = $hasArray;
|
||||
if ($tokens[$hasArray]['code'] === T_OPEN_SHORT_ARRAY && isset($tokens[$hasArray]['bracket_closer'])) {
|
||||
$stackPtr = $tokens[$hasArray]['bracket_closer'];
|
||||
} elseif ($tokens[$hasArray]['code'] === T_ARRAY && isset($tokens[$hasArray]['parenthesis_closer'])) {
|
||||
$stackPtr = $tokens[$hasArray]['parenthesis_closer'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantArraysUsingDefineSniff.
|
||||
*
|
||||
* PHP version 7.0
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Wim Godden <wim@cu.be>
|
||||
*/
|
||||
|
||||
namespace PHPCompatibility\Sniffs\InitialValue;
|
||||
|
||||
use PHPCompatibility\Sniff;
|
||||
use PHP_CodeSniffer_File as File;
|
||||
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantArraysUsingDefineSniff.
|
||||
*
|
||||
* Constant arrays using define in PHP 7.0
|
||||
*
|
||||
* PHP version 7.0
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Wim Godden <wim@cu.be>
|
||||
*/
|
||||
class NewConstantArraysUsingDefineSniff extends Sniff
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes this test, when one of its tokens is encountered.
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the current token in the
|
||||
* stack passed in $tokens.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function process(File $phpcsFile, $stackPtr)
|
||||
{
|
||||
if ($this->supportsBelow('5.6') !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
$ignore = array(
|
||||
T_DOUBLE_COLON => true,
|
||||
T_OBJECT_OPERATOR => true,
|
||||
T_FUNCTION => true,
|
||||
T_CONST => true,
|
||||
);
|
||||
|
||||
$prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
|
||||
if (isset($ignore[$tokens[$prevToken]['code']]) === true) {
|
||||
// Not a call to a PHP function.
|
||||
return;
|
||||
}
|
||||
|
||||
$functionLc = strtolower($tokens[$stackPtr]['content']);
|
||||
if ($functionLc !== 'define') {
|
||||
return;
|
||||
}
|
||||
|
||||
$secondParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, 2);
|
||||
if (isset($secondParam['start'], $secondParam['end']) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$targetNestingLevel = 0;
|
||||
if (isset($tokens[$secondParam['start']]['nested_parenthesis'])) {
|
||||
$targetNestingLevel = count($tokens[$secondParam['start']]['nested_parenthesis']);
|
||||
}
|
||||
|
||||
$array = $phpcsFile->findNext(array(T_ARRAY, T_OPEN_SHORT_ARRAY), $secondParam['start'], ($secondParam['end'] + 1));
|
||||
if ($array !== false) {
|
||||
if ((isset($tokens[$array]['nested_parenthesis']) === false && $targetNestingLevel === 0) || count($tokens[$array]['nested_parenthesis']) === $targetNestingLevel) {
|
||||
$phpcsFile->addError(
|
||||
'Constant arrays using define are not allowed in PHP 5.6 or earlier',
|
||||
$array,
|
||||
'Found'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+534
@@ -0,0 +1,534 @@
|
||||
<?php
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantScalarExpressionsSniff.
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
|
||||
namespace PHPCompatibility\Sniffs\InitialValue;
|
||||
|
||||
use PHPCompatibility\Sniff;
|
||||
use PHPCompatibility\PHPCSHelper;
|
||||
use PHP_CodeSniffer_File as File;
|
||||
use PHP_CodeSniffer_Tokens as Tokens;
|
||||
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewConstantScalarExpressionsSniff.
|
||||
*
|
||||
* Since PHP 5.6, it is now possible to provide a scalar expression involving
|
||||
* numeric and string literals and/or constants in contexts where PHP previously
|
||||
* expected a static value, such as constant and property declarations and
|
||||
* default function arguments.
|
||||
*
|
||||
* PHP version 5.6
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
class NewConstantScalarExpressionsSniff extends Sniff
|
||||
{
|
||||
|
||||
/**
|
||||
* Error message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ERROR_PHRASE = 'Constant scalar expressions are not allowed %s in PHP 5.5 or earlier.';
|
||||
|
||||
/**
|
||||
* Partial error phrases to be used in combination with the error message constant.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errorPhrases = array(
|
||||
'const' => 'when defining constants using the const keyword',
|
||||
'property' => 'in property declarations',
|
||||
'staticvar' => 'in static variable declarations',
|
||||
'default' => 'in default function arguments',
|
||||
);
|
||||
|
||||
/**
|
||||
* Tokens which were allowed to be used in these declarations prior to PHP 5.6.
|
||||
*
|
||||
* This list will be enriched in the setProperties() method.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $safeOperands = array(
|
||||
T_LNUMBER => T_LNUMBER,
|
||||
T_DNUMBER => T_DNUMBER,
|
||||
T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING,
|
||||
T_TRUE => T_TRUE,
|
||||
T_FALSE => T_FALSE,
|
||||
T_NULL => T_NULL,
|
||||
|
||||
T_LINE => T_LINE,
|
||||
T_FILE => T_FILE,
|
||||
T_DIR => T_DIR,
|
||||
T_FUNC_C => T_FUNC_C,
|
||||
T_CLASS_C => T_CLASS_C,
|
||||
T_TRAIT_C => T_TRAIT_C,
|
||||
T_METHOD_C => T_METHOD_C,
|
||||
T_NS_C => T_NS_C,
|
||||
|
||||
// Special cases:
|
||||
T_NS_SEPARATOR => T_NS_SEPARATOR,
|
||||
/*
|
||||
* This can be neigh anything, but for any usage except constants,
|
||||
* the T_STRING will be combined with non-allowed tokens, so we should be good.
|
||||
*/
|
||||
T_STRING => T_STRING,
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// Set the properties up only once.
|
||||
$this->setProperties();
|
||||
|
||||
return array(
|
||||
T_CONST,
|
||||
T_VARIABLE,
|
||||
T_FUNCTION,
|
||||
T_CLOSURE,
|
||||
T_STATIC,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make some adjustments to the $safeOperands property.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setProperties()
|
||||
{
|
||||
$this->safeOperands += Tokens::$heredocTokens;
|
||||
$this->safeOperands += Tokens::$emptyTokens;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do a version check to determine if this sniff needs to run at all.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function bowOutEarly()
|
||||
{
|
||||
return ($this->supportsBelow('5.5') !== true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes this test, when one of its tokens is encountered.
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the current token in the
|
||||
* stack passed in $tokens.
|
||||
*
|
||||
* @return void|int Null or integer stack pointer to skip forward.
|
||||
*/
|
||||
public function process(File $phpcsFile, $stackPtr)
|
||||
{
|
||||
if ($this->bowOutEarly() === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
switch ($tokens[$stackPtr]['type']) {
|
||||
case 'T_FUNCTION':
|
||||
case 'T_CLOSURE':
|
||||
$params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr);
|
||||
if (empty($params)) {
|
||||
// No parameters.
|
||||
return;
|
||||
}
|
||||
|
||||
$funcToken = $tokens[$stackPtr];
|
||||
|
||||
if (isset($funcToken['parenthesis_owner'], $funcToken['parenthesis_opener'], $funcToken['parenthesis_closer']) === false
|
||||
|| $funcToken['parenthesis_owner'] !== $stackPtr
|
||||
|| isset($tokens[$funcToken['parenthesis_opener']], $tokens[$funcToken['parenthesis_closer']]) === false
|
||||
) {
|
||||
// Hmm.. something is going wrong as these should all be available & valid.
|
||||
return;
|
||||
}
|
||||
|
||||
$opener = $funcToken['parenthesis_opener'];
|
||||
$closer = $funcToken['parenthesis_closer'];
|
||||
|
||||
// Which nesting level is the one we are interested in ?
|
||||
$nestedParenthesisCount = 1;
|
||||
if (isset($tokens[$opener]['nested_parenthesis'])) {
|
||||
$nestedParenthesisCount += count($tokens[$opener]['nested_parenthesis']);
|
||||
}
|
||||
|
||||
foreach ($params as $param) {
|
||||
if (isset($param['default']) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$end = $param['token'];
|
||||
while (($end = $phpcsFile->findNext(array(T_COMMA, T_CLOSE_PARENTHESIS), ($end + 1), ($closer + 1))) !== false) {
|
||||
$maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $nestedParenthesisCount);
|
||||
if ($maybeSkipTo !== true) {
|
||||
$end = $maybeSkipTo;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore closing parenthesis/bracket if not 'ours'.
|
||||
if ($tokens[$end]['code'] === T_CLOSE_PARENTHESIS && $end !== $closer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, we've found the end of the param default value declaration.
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->isValidAssignment($phpcsFile, $param['token'], $end) === false) {
|
||||
$this->throwError($phpcsFile, $param['token'], 'default', $param['content']);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No need for the sniff to be triggered by the T_VARIABLEs in the function
|
||||
* definition as we've already examined them above, so let's skip over them.
|
||||
*/
|
||||
return $closer;
|
||||
|
||||
case 'T_VARIABLE':
|
||||
case 'T_STATIC':
|
||||
case 'T_CONST':
|
||||
$type = 'const';
|
||||
|
||||
// Filter out non-property declarations.
|
||||
if ($tokens[$stackPtr]['code'] === T_VARIABLE) {
|
||||
if ($this->isClassProperty($phpcsFile, $stackPtr) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$type = 'property';
|
||||
|
||||
// Move back one token to have the same starting point as the others.
|
||||
$stackPtr = ($stackPtr - 1);
|
||||
}
|
||||
|
||||
// Filter out late static binding and class properties.
|
||||
if ($tokens[$stackPtr]['code'] === T_STATIC) {
|
||||
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true);
|
||||
if ($next === false || $tokens[$next]['code'] !== T_VARIABLE) {
|
||||
// Late static binding.
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->isClassProperty($phpcsFile, $next) === true) {
|
||||
// Class properties are examined based on the T_VARIABLE token.
|
||||
return;
|
||||
}
|
||||
unset($next);
|
||||
|
||||
$type = 'staticvar';
|
||||
}
|
||||
|
||||
$endOfStatement = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_TAG), ($stackPtr + 1));
|
||||
if ($endOfStatement === false) {
|
||||
// No semi-colon - live coding.
|
||||
return;
|
||||
}
|
||||
|
||||
$targetNestingLevel = 0;
|
||||
if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
|
||||
$targetNestingLevel = count($tokens[$stackPtr]['nested_parenthesis']);
|
||||
}
|
||||
|
||||
// Examine each variable/constant in multi-declarations.
|
||||
$start = $stackPtr;
|
||||
$end = $stackPtr;
|
||||
while (($end = $phpcsFile->findNext(array(T_COMMA, T_SEMICOLON, T_OPEN_SHORT_ARRAY, T_CLOSE_TAG), ($end + 1), ($endOfStatement + 1))) !== false) {
|
||||
|
||||
$maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $targetNestingLevel);
|
||||
if ($maybeSkipTo !== true) {
|
||||
$end = $maybeSkipTo;
|
||||
continue;
|
||||
}
|
||||
|
||||
$start = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), $end, true);
|
||||
if ($start === false
|
||||
|| ($tokens[$stackPtr]['code'] === T_CONST && $tokens[$start]['code'] !== T_STRING)
|
||||
|| ($tokens[$stackPtr]['code'] !== T_CONST && $tokens[$start]['code'] !== T_VARIABLE)
|
||||
) {
|
||||
// Shouldn't be possible.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isValidAssignment($phpcsFile, $start, $end) === false) {
|
||||
// Create the "found" snippet.
|
||||
$content = '';
|
||||
$tokenCount = ($end - $start);
|
||||
if ($tokenCount < 20) {
|
||||
// Prevent large arrays from being added to the error message.
|
||||
$content = $phpcsFile->getTokensAsString($start, ($tokenCount + 1));
|
||||
}
|
||||
|
||||
$this->throwError($phpcsFile, $start, $type, $content);
|
||||
}
|
||||
|
||||
$start = $end;
|
||||
}
|
||||
|
||||
// Skip to the end of the statement to prevent duplicate messages for multi-declarations.
|
||||
return $endOfStatement;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is a value declared and is the value declared valid pre-PHP 5.6 ?
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the current token in the
|
||||
* stack passed in $tokens.
|
||||
* @param int $end The end of the value definition.
|
||||
* This will normally be a comma or semi-colon.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidAssignment(File $phpcsFile, $stackPtr, $end)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true);
|
||||
if ($next === false || $tokens[$next]['code'] !== T_EQUAL) {
|
||||
// No value assigned.
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->isStaticValue($phpcsFile, $tokens, ($next + 1), ($end - 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is a value declared and is the value declared constant as accepted in PHP 5.5 and lower ?
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param array $tokens The token stack of the current file.
|
||||
* @param int $start The stackPtr from which to start examining.
|
||||
* @param int $end The end of the value definition (inclusive),
|
||||
* i.e. this token will be examined as part of
|
||||
* the snippet.
|
||||
* @param bool $nestedArrays Optional. Array nesting level when examining
|
||||
* the content of an array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isStaticValue(File $phpcsFile, $tokens, $start, $end, $nestedArrays = 0)
|
||||
{
|
||||
$nextNonSimple = $phpcsFile->findNext($this->safeOperands, $start, ($end + 1), true);
|
||||
if ($nextNonSimple === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, so we have at least one token which needs extra examination.
|
||||
*/
|
||||
switch ($tokens[$nextNonSimple]['code']) {
|
||||
case T_MINUS:
|
||||
case T_PLUS:
|
||||
if ($this->isNumber($phpcsFile, $start, $end, true) !== false) {
|
||||
// Int or float with sign.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case T_NAMESPACE:
|
||||
case T_PARENT:
|
||||
case T_SELF:
|
||||
case T_DOUBLE_COLON:
|
||||
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true);
|
||||
|
||||
if ($tokens[$nextNonSimple]['code'] === T_NAMESPACE) {
|
||||
// Allow only `namespace\...`.
|
||||
if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== T_NS_SEPARATOR) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($tokens[$nextNonSimple]['code'] === T_PARENT
|
||||
|| $tokens[$nextNonSimple]['code'] === T_SELF
|
||||
) {
|
||||
// Allow only `parent::` and `self::`.
|
||||
if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== T_DOUBLE_COLON) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($tokens[$nextNonSimple]['code'] === T_DOUBLE_COLON) {
|
||||
// Allow only `T_STRING::T_STRING`.
|
||||
if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== T_STRING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextNonSimple - 1), null, true);
|
||||
// No need to worry about parent/self, that's handled above and
|
||||
// the double colon is skipped over in that case.
|
||||
if ($prevNonEmpty === false || $tokens[$prevNonEmpty]['code'] !== T_STRING) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Examine what comes after the namespace/parent/self/double colon, if anything.
|
||||
return $this->isStaticValue($phpcsFile, $tokens, ($nextNonEmpty + 1), $end, $nestedArrays);
|
||||
|
||||
case T_ARRAY:
|
||||
case T_OPEN_SHORT_ARRAY:
|
||||
++$nestedArrays;
|
||||
|
||||
$arrayItems = $this->getFunctionCallParameters($phpcsFile, $nextNonSimple);
|
||||
if (empty($arrayItems) === false) {
|
||||
foreach ($arrayItems as $item) {
|
||||
// Check for a double arrow, but only if it's for this array item, not for a nested array.
|
||||
$doubleArrow = false;
|
||||
|
||||
$maybeDoubleArrow = $phpcsFile->findNext(
|
||||
array(T_DOUBLE_ARROW, T_ARRAY, T_OPEN_SHORT_ARRAY),
|
||||
$item['start'],
|
||||
($item['end'] + 1)
|
||||
);
|
||||
if ($maybeDoubleArrow !== false && $tokens[$maybeDoubleArrow]['code'] === T_DOUBLE_ARROW) {
|
||||
// Double arrow is for this nesting level.
|
||||
$doubleArrow = $maybeDoubleArrow;
|
||||
}
|
||||
|
||||
if ($doubleArrow === false) {
|
||||
if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], $item['end'], $nestedArrays) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Examine array key.
|
||||
if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], ($doubleArrow - 1), $nestedArrays) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Examine array value.
|
||||
if ($this->isStaticValue($phpcsFile, $tokens, ($doubleArrow + 1), $item['end'], $nestedArrays) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
--$nestedArrays;
|
||||
|
||||
/*
|
||||
* Find the end of the array.
|
||||
* We already know we will have a valid closer as otherwise we wouldn't have been
|
||||
* able to get the array items.
|
||||
*/
|
||||
$closer = ($nextNonSimple + 1);
|
||||
if ($tokens[$nextNonSimple]['code'] === T_OPEN_SHORT_ARRAY
|
||||
&& isset($tokens[$nextNonSimple]['bracket_closer']) === true
|
||||
) {
|
||||
$closer = $tokens[$nextNonSimple]['bracket_closer'];
|
||||
} else {
|
||||
$maybeOpener = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true);
|
||||
if ($tokens[$maybeOpener]['code'] === T_OPEN_PARENTHESIS) {
|
||||
$opener = $maybeOpener;
|
||||
if (isset($tokens[$opener]['parenthesis_closer']) === true) {
|
||||
$closer = $tokens[$opener]['parenthesis_closer'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($closer === $end) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Examine what comes after the array, if anything.
|
||||
return $this->isStaticValue($phpcsFile, $tokens, ($closer + 1), $end, $nestedArrays);
|
||||
|
||||
}
|
||||
|
||||
// Ok, so this unsafe token was not one of the exceptions, i.e. this is a PHP 5.6+ syntax.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throw an error if a scalar expression is found.
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the token to link the error to.
|
||||
* @param string $type Type of usage found.
|
||||
* @param string $content Optional. The value for the declaration as found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function throwError(File $phpcsFile, $stackPtr, $type, $content = '')
|
||||
{
|
||||
$error = static::ERROR_PHRASE;
|
||||
$phrase = '';
|
||||
$errorCode = 'Found';
|
||||
|
||||
if (isset($this->errorPhrases[$type]) === true) {
|
||||
$errorCode = $this->stringToErrorCode($type) . 'Found';
|
||||
$phrase = $this->errorPhrases[$type];
|
||||
}
|
||||
|
||||
$data = array($phrase);
|
||||
|
||||
if (empty($content) === false) {
|
||||
$error .= ' Found: %s';
|
||||
$data[] = $content;
|
||||
}
|
||||
|
||||
$phpcsFile->addError($error, $stackPtr, $errorCode, $data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to find the end of multi variable/constant declarations.
|
||||
*
|
||||
* Checks whether a certain part of a declaration needs to be skipped over or
|
||||
* if it is the real end of the declaration.
|
||||
*
|
||||
* @param array $tokens Token stack of the current file.
|
||||
* @param int $endPtr The token to examine as a candidate end pointer.
|
||||
* @param int $targetLevel Target nesting level.
|
||||
*
|
||||
* @return bool|int True if this is the real end. Int stackPtr to skip to if not.
|
||||
*/
|
||||
private function isRealEndOfDeclaration($tokens, $endPtr, $targetLevel)
|
||||
{
|
||||
// Ignore anything within short array definition brackets for now.
|
||||
if ($tokens[$endPtr]['code'] === T_OPEN_SHORT_ARRAY
|
||||
&& (isset($tokens[$endPtr]['bracket_opener'])
|
||||
&& $tokens[$endPtr]['bracket_opener'] === $endPtr)
|
||||
&& isset($tokens[$endPtr]['bracket_closer'])
|
||||
) {
|
||||
// Skip forward to the end of the short array definition.
|
||||
return $tokens[$endPtr]['bracket_closer'];
|
||||
}
|
||||
|
||||
// Skip past comma's at a lower nesting level.
|
||||
if ($tokens[$endPtr]['code'] === T_COMMA) {
|
||||
// Check if a comma is at the nesting level we're targetting.
|
||||
$nestingLevel = 0;
|
||||
if (isset($tokens[$endPtr]['nested_parenthesis']) === true) {
|
||||
$nestingLevel = count($tokens[$endPtr]['nested_parenthesis']);
|
||||
}
|
||||
if ($nestingLevel > $targetLevel) {
|
||||
return $endPtr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewHeredocSniff.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
|
||||
namespace PHPCompatibility\Sniffs\InitialValue;
|
||||
|
||||
use PHPCompatibility\Sniffs\InitialValue\NewConstantScalarExpressionsSniff;
|
||||
use PHP_CodeSniffer_File as File;
|
||||
use PHP_CodeSniffer_Tokens as Tokens;
|
||||
|
||||
/**
|
||||
* \PHPCompatibility\Sniffs\InitialValue\NewHeredocSniff.
|
||||
*
|
||||
* As of PHP 5.3.0, it's possible to initialize static variables, class properties
|
||||
* and constants declared using the `const` keyword, using the Heredoc syntax.
|
||||
* And while not documented, heredoc initialization can now also be used for function param defaults.
|
||||
* See: https://3v4l.org/JVH8W
|
||||
*
|
||||
* These heredocs (still) cannot contain variables. That's, however, outside the scope of the
|
||||
* PHPCompatibility library until such time as there is a PHP version in which this would be accepted.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHPCompatibility
|
||||
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
|
||||
*/
|
||||
class NewHeredocSniff extends NewConstantScalarExpressionsSniff
|
||||
{
|
||||
|
||||
/**
|
||||
* Error message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ERROR_PHRASE = 'Initializing %s using the Heredoc syntax was not supported in PHP 5.2 or earlier';
|
||||
|
||||
/**
|
||||
* Partial error phrases to be used in combination with the error message constant.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errorPhrases = array(
|
||||
'const' => 'constants',
|
||||
'property' => 'class properties',
|
||||
'staticvar' => 'static variables',
|
||||
'default' => 'default parameter values',
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Do a version check to determine if this sniff needs to run at all.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function bowOutEarly()
|
||||
{
|
||||
return ($this->supportsBelow('5.2') !== true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is a value declared and does the declared value not contain an heredoc ?
|
||||
*
|
||||
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
||||
* @param int $stackPtr The position of the current token in the
|
||||
* stack passed in $tokens.
|
||||
* @param int $end The end of the value definition.
|
||||
*
|
||||
* @return bool True if no heredoc (or assignment) is found, false otherwise.
|
||||
*/
|
||||
protected function isValidAssignment(File $phpcsFile, $stackPtr, $end)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true);
|
||||
if ($next === false || $tokens[$next]['code'] !== T_EQUAL) {
|
||||
// No value assigned.
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($phpcsFile->findNext(T_START_HEREDOC, ($next + 1), $end, false, null, true) === false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user