Initial Commit
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures this is not assigned to any other var but self.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures this is not assigned to any other var but self.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Objects_AssignThisSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
/**
|
||||
* A list of tokenizers this sniff supports.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $supportedTokenizers = array('JS');
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_THIS);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
// Ignore this.something and other uses of "this" that are not
|
||||
// direct assignments.
|
||||
$next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
|
||||
if ($tokens[$next]['code'] !== T_SEMICOLON) {
|
||||
if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Something must be assigned to "this".
|
||||
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
|
||||
if ($tokens[$prev]['code'] !== T_EQUAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A variable needs to be assigned to "this".
|
||||
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
|
||||
if ($tokens[$prev]['code'] !== T_STRING) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only assign "this" to a var called "self".
|
||||
if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') {
|
||||
$error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"';
|
||||
$phpcsFile->addError($error, $prev, 'NotSelf');
|
||||
}
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures the create() method of widget types properly uses callbacks.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures the create() method of widget types properly uses callbacks.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Objects_CreateWidgetTypeCallbackSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
/**
|
||||
* A list of tokenizers this sniff supports.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $supportedTokenizers = array('JS');
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_OBJECT);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
$className = $tokens[$stackPtr]['content'];
|
||||
if (substr(strtolower($className), -10) !== 'widgettype') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for a create method.
|
||||
$start = ($tokens[$stackPtr]['scope_opener'] + 1);
|
||||
$end = ($tokens[$stackPtr]['scope_closer'] - 1);
|
||||
$create = $phpcsFile->findNext(T_PROPERTY, $start, $end, null, 'create');
|
||||
if ($create === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$function = $phpcsFile->findNext(array(T_WHITESPACE, T_COLON), ($create + 1), null, true);
|
||||
if ($tokens[$function]['code'] !== T_FUNCTION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$start = ($tokens[$function]['scope_opener'] + 1);
|
||||
$end = ($tokens[$function]['scope_closer'] - 1);
|
||||
|
||||
// Check that the first argument is called "callback".
|
||||
$arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true);
|
||||
if ($tokens[$arg]['content'] !== 'callback') {
|
||||
$error = 'The first argument of the create() method of a widget type must be called "callback"';
|
||||
$phpcsFile->addError($error, $arg, 'FirstArgNotCallback');
|
||||
}
|
||||
|
||||
/*
|
||||
Look for return statements within the function. They cannot return
|
||||
anything and must be preceeded by the callback.call() line. The
|
||||
callback itself must contain "self" or "this" as the first argument
|
||||
and there needs to be a call to the callback function somewhere
|
||||
in the create method. All calls to the callback function must be
|
||||
followed by a return statement or the end of the method.
|
||||
*/
|
||||
|
||||
$foundCallback = false;
|
||||
$passedCallback = false;
|
||||
$nestedFunction = null;
|
||||
for ($i = $start; $i <= $end; $i++) {
|
||||
// Keep track of nested functions.
|
||||
if ($nestedFunction !== null) {
|
||||
if ($i === $nestedFunction) {
|
||||
$nestedFunction = null;
|
||||
continue;
|
||||
}
|
||||
} else if ($tokens[$i]['code'] === T_FUNCTION
|
||||
&& isset($tokens[$i]['scope_closer']) === true
|
||||
) {
|
||||
$nestedFunction = $tokens[$i]['scope_closer'];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) {
|
||||
// Make sure return statements are not returning anything.
|
||||
if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) {
|
||||
$error = 'The create() method of a widget type must not return a value';
|
||||
$phpcsFile->addError($error, $i, 'ReturnValue');
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if ($tokens[$i]['code'] !== T_STRING
|
||||
|| $tokens[$i]['content'] !== 'callback'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is the form "callback.call(" then it is a call
|
||||
// to the callback function.
|
||||
if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR
|
||||
|| $tokens[($i + 2)]['content'] !== 'call'
|
||||
|| $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS
|
||||
) {
|
||||
// One last chance; this might be the callback function
|
||||
// being passed to another function, like this
|
||||
// "this.init(something, callback, something)".
|
||||
if (isset($tokens[$i]['nested_parenthesis']) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Just make sure those brackets dont belong to anyone,
|
||||
// like an IF or FOR statement.
|
||||
foreach ($tokens[$i]['nested_parenthesis'] as $bracket) {
|
||||
if (isset($tokens[$bracket]['parenthesis_owner']) === true) {
|
||||
continue(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we use this endBracket down further when checking
|
||||
// for a RETURN statement.
|
||||
$endBracket = end($tokens[$i]['nested_parenthesis']);
|
||||
$bracket = key($tokens[$i]['nested_parenthesis']);
|
||||
|
||||
$prev = $phpcsFile->findPrevious(
|
||||
PHP_CodeSniffer_Tokens::$emptyTokens,
|
||||
($bracket - 1),
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
if ($tokens[$prev]['code'] !== T_STRING) {
|
||||
// This is not a function passing the callback.
|
||||
continue;
|
||||
}
|
||||
|
||||
$passedCallback = true;
|
||||
}//end if
|
||||
|
||||
$foundCallback = true;
|
||||
|
||||
if ($passedCallback === false) {
|
||||
// The first argument must be "this" or "self".
|
||||
$arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true);
|
||||
if ($tokens[$arg]['content'] !== 'this'
|
||||
&& $tokens[$arg]['content'] !== 'self'
|
||||
) {
|
||||
$error = 'The first argument passed to the callback function must be "this" or "self"';
|
||||
$phpcsFile->addError($error, $arg, 'FirstArgNotSelf');
|
||||
}
|
||||
}
|
||||
|
||||
// Now it must be followed by a return statement or the end of the function.
|
||||
if ($passedCallback === false) {
|
||||
$endBracket = $tokens[($i + 3)]['parenthesis_closer'];
|
||||
}
|
||||
|
||||
for ($next = $endBracket; $next <= $end; $next++) {
|
||||
// Skip whitespace so we find the next content after the call.
|
||||
if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip closing braces like END IF because it is not executable code.
|
||||
if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't care about anything on the current line, like a
|
||||
// semicolon. It doesn't matter if there are other statements on the
|
||||
// line because another sniff will check for those.
|
||||
if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($next !== $tokens[$function]['scope_closer']
|
||||
&& $tokens[$next]['code'] !== T_RETURN
|
||||
) {
|
||||
$error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method';
|
||||
$phpcsFile->addError($error, $i, 'NoReturn');
|
||||
}
|
||||
}//end for
|
||||
|
||||
if ($foundCallback === false) {
|
||||
$error = 'The create() method of a widget type must call the callback function';
|
||||
$phpcsFile->addError($error, $create, 'CallbackNotCalled');
|
||||
}
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures that widgets are not manually created.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures that widgets are not manually created.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Objects_DisallowNewWidgetSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_NEW);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* 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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
$className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
|
||||
if ($tokens[$className]['code'] !== T_STRING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') {
|
||||
$widgetType = substr($tokens[$className]['content'], 0, -10);
|
||||
$error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead';
|
||||
$data = array($widgetType);
|
||||
$phpcsFile->addError($error, $stackPtr, 'Found', $data);
|
||||
}
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user