@@ -0,0 +1,139 @@ | |||
<?php | |||
/** | |||
* @author Joas Schilling <nickvergessen@owncloud.com> | |||
* | |||
* @copyright Copyright (c) 2015, ownCloud, Inc. | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OC\App\CodeChecker; | |||
abstract class AbstractCheck implements ICheck { | |||
/** @var ICheck */ | |||
protected $check; | |||
/** | |||
* @param ICheck $check | |||
*/ | |||
public function __construct(ICheck $check) { | |||
$this->check = $check; | |||
} | |||
/** | |||
* @param int $errorCode | |||
* @param string $errorObject | |||
* @return string | |||
*/ | |||
public function getDescription($errorCode, $errorObject) { | |||
switch ($errorCode) { | |||
case CodeChecker::STATIC_CALL_NOT_ALLOWED: | |||
$functions = $this->getLocalFunctions(); | |||
$functions = array_change_key_case($functions, CASE_LOWER); | |||
if (isset($functions[$errorObject])) { | |||
return $this->getLocalDescription(); | |||
} | |||
// no break; | |||
case CodeChecker::CLASS_EXTENDS_NOT_ALLOWED: | |||
case CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED: | |||
case CodeChecker::CLASS_NEW_NOT_ALLOWED: | |||
case CodeChecker::CLASS_USE_NOT_ALLOWED: | |||
$classes = $this->getLocalClasses(); | |||
$classes = array_change_key_case($classes, CASE_LOWER); | |||
if (isset($classes[$errorObject])) { | |||
return $this->getLocalDescription(); | |||
} | |||
break; | |||
case CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED: | |||
$constants = $this->getLocalConstants(); | |||
$constants = array_change_key_case($constants, CASE_LOWER); | |||
if (isset($constants[$errorObject])) { | |||
return $this->getLocalDescription(); | |||
} | |||
break; | |||
case CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED: | |||
$methods = $this->getLocalMethods(); | |||
$methods = array_change_key_case($methods, CASE_LOWER); | |||
if (isset($methods[$errorObject])) { | |||
return $this->getLocalDescription(); | |||
} | |||
break; | |||
} | |||
return $this->check->getDescription($errorCode, $errorObject); | |||
} | |||
/** | |||
* @return string | |||
*/ | |||
abstract protected function getLocalDescription(); | |||
/** | |||
* @return array | |||
*/ | |||
abstract protected function getLocalClasses(); | |||
/** | |||
* @return array | |||
*/ | |||
abstract protected function getLocalConstants(); | |||
/** | |||
* @return array | |||
*/ | |||
abstract protected function getLocalFunctions(); | |||
/** | |||
* @return array | |||
*/ | |||
abstract protected function getLocalMethods(); | |||
/** | |||
* @return array E.g.: `'ClassName' => 'oc version',` | |||
*/ | |||
public function getClasses() { | |||
return array_merge($this->getLocalClasses(), $this->check->getClasses()); | |||
} | |||
/** | |||
* @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',` | |||
*/ | |||
public function getConstants() { | |||
return array_merge($this->getLocalConstants(), $this->check->getConstants()); | |||
} | |||
/** | |||
* @return array E.g.: `'functionName' => 'oc version',` | |||
*/ | |||
public function getFunctions() { | |||
return array_merge($this->getLocalFunctions(), $this->check->getFunctions()); | |||
} | |||
/** | |||
* @return array E.g.: `'ClassName::methodName' => 'oc version',` | |||
*/ | |||
public function getMethods() { | |||
return array_merge($this->getLocalMethods(), $this->check->getMethods()); | |||
} | |||
/** | |||
* @return bool | |||
*/ | |||
public function checkStrongComparisons() { | |||
return $this->check->checkStrongComparisons(); | |||
} | |||
} |
@@ -41,7 +41,7 @@ class CodeChecker extends BasicEmitter { | |||
const CLASS_IMPLEMENTS_NOT_ALLOWED = 1001; | |||
const STATIC_CALL_NOT_ALLOWED = 1002; | |||
const CLASS_CONST_FETCH_NOT_ALLOWED = 1003; | |||
const CLASS_NEW_FETCH_NOT_ALLOWED = 1004; | |||
const CLASS_NEW_NOT_ALLOWED = 1004; | |||
const OP_OPERATOR_USAGE_DISCOURAGED = 1005; | |||
const CLASS_USE_NOT_ALLOWED = 1006; | |||
const CLASS_METHOD_CALL_NOT_ALLOWED = 1007; |
@@ -21,30 +21,19 @@ | |||
namespace OC\App\CodeChecker; | |||
class DeprecationCheck implements ICheck { | |||
/** @var ICheck */ | |||
protected $check; | |||
/** | |||
* @param ICheck $check | |||
*/ | |||
public function __construct(ICheck $check) { | |||
$this->check = $check; | |||
} | |||
class DeprecationCheck extends AbstractCheck implements ICheck { | |||
/** | |||
* @return string | |||
*/ | |||
public function getDescription() { | |||
$innerDescription = $this->check->getDescription(); | |||
return 'deprecated' . (($innerDescription === '') ? '' : ' ' . $innerDescription); | |||
protected function getLocalDescription() { | |||
return 'deprecated'; | |||
} | |||
/** | |||
* @return array E.g.: `'ClassName' => 'oc version',` | |||
*/ | |||
public function getClasses() { | |||
return array_merge([ | |||
protected function getLocalClasses() { | |||
return [ | |||
'OCP\Config' => '8.0.0', | |||
'OCP\Contacts' => '8.1.0', | |||
'OCP\DB' => '8.1.0', | |||
@@ -52,14 +41,14 @@ class DeprecationCheck implements ICheck { | |||
'OCP\JSON' => '8.1.0', | |||
'OCP\Response' => '8.1.0', | |||
'OCP\AppFramework\IApi' => '8.0.0', | |||
], $this->check->getClasses()); | |||
]; | |||
} | |||
/** | |||
* @return array E.g.: `'ClassName::CONSTANT_NAME' => 'oc version',` | |||
*/ | |||
public function getConstants() { | |||
return array_merge([ | |||
protected function getLocalConstants() { | |||
return [ | |||
'OCP::PERMISSION_CREATE' => '8.0.0', | |||
'OCP::PERMISSION_READ' => '8.0.0', | |||
'OCP::PERMISSION_UPDATE' => '8.0.0', | |||
@@ -67,14 +56,14 @@ class DeprecationCheck implements ICheck { | |||
'OCP::PERMISSION_SHARE' => '8.0.0', | |||
'OCP::PERMISSION_ALL' => '8.0.0', | |||
'OCP::FILENAME_INVALID_CHARS' => '8.0.0', | |||
], $this->check->getConstants()); | |||
]; | |||
} | |||
/** | |||
* @return array E.g.: `'functionName' => 'oc version',` | |||
*/ | |||
public function getFunctions() { | |||
return array_merge([ | |||
protected function getLocalFunctions() { | |||
return [ | |||
'OCP::image_path' => '8.0.0', | |||
'OCP::mimetype_icon' => '8.0.0', | |||
'OCP::preview_icon' => '8.0.0', | |||
@@ -83,14 +72,14 @@ class DeprecationCheck implements ICheck { | |||
'OCP::relative_modified_date' => '8.0.0', | |||
'OCP::simple_file_size' => '8.0.0', | |||
'OCP::html_select_options' => '8.0.0', | |||
], $this->check->getFunctions()); | |||
]; | |||
} | |||
/** | |||
* @return array E.g.: `'ClassName::methodName' => 'oc version',` | |||
*/ | |||
public function getMethods() { | |||
return array_merge([ | |||
protected function getLocalMethods() { | |||
return [ | |||
'OCP\App::register' => '8.1.0', | |||
'OCP\App::addNavigationEntry' => '8.1.0', | |||
'OCP\App::setActiveNavigationEntry' => '8.1.0', | |||
@@ -151,13 +140,6 @@ class DeprecationCheck implements ICheck { | |||
'OCP\Util::imagePath' => '8.1.0', | |||
'OCP\Util::isValidFileName' => '8.1.0', | |||
'OCP\Util::generateRandomBytes' => '8.1.0', | |||
], $this->check->getMethods()); | |||
} | |||
/** | |||
* @return bool | |||
*/ | |||
public function checkStrongComparisons() { | |||
return $this->check->checkStrongComparisons(); | |||
]; | |||
} | |||
} |
@@ -22,9 +22,11 @@ namespace OC\App\CodeChecker; | |||
class EmptyCheck implements ICheck { | |||
/** | |||
* @param int $errorCode | |||
* @param string $errorObject | |||
* @return string | |||
*/ | |||
public function getDescription() { | |||
public function getDescription($errorCode, $errorObject) { | |||
return ''; | |||
} | |||
@@ -22,9 +22,11 @@ namespace OC\App\CodeChecker; | |||
interface ICheck { | |||
/** | |||
* @param int $errorCode | |||
* @param string $errorObject | |||
* @return string | |||
*/ | |||
public function getDescription(); | |||
public function getDescription($errorCode, $errorObject); | |||
/** | |||
* @return array E.g.: `'ClassName' => 'oc version',` |
@@ -27,6 +27,9 @@ use PhpParser\Node\Name; | |||
use PhpParser\NodeVisitorAbstract; | |||
class NodeVisitor extends NodeVisitorAbstract { | |||
/** @var ICheck */ | |||
protected $list; | |||
/** @var string */ | |||
protected $blackListDescription; | |||
/** @var string[] */ | |||
@@ -46,7 +49,7 @@ class NodeVisitor extends NodeVisitorAbstract { | |||
* @param ICheck $list | |||
*/ | |||
public function __construct(ICheck $list) { | |||
$this->blackListDescription = $list->getDescription(); | |||
$this->list = $list; | |||
$this->blackListedClassNames = []; | |||
foreach ($list->getClasses() as $class => $blackListInfo) { | |||
@@ -80,13 +83,13 @@ class NodeVisitor extends NodeVisitorAbstract { | |||
$this->checkEqualOperatorUsage = $list->checkStrongComparisons(); | |||
$this->errorMessages = [ | |||
CodeChecker::CLASS_EXTENDS_NOT_ALLOWED => "{$this->blackListDescription} class must not be extended", | |||
CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED => "{$this->blackListDescription} interface must not be implemented", | |||
CodeChecker::STATIC_CALL_NOT_ALLOWED => "Static method of {$this->blackListDescription} class must not be called", | |||
CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED => "Constant of {$this->blackListDescription} class must not not be fetched", | |||
CodeChecker::CLASS_NEW_FETCH_NOT_ALLOWED => "{$this->blackListDescription} class must not be instanciated", | |||
CodeChecker::CLASS_USE_NOT_ALLOWED => "{$this->blackListDescription} class must not be imported with a use statement", | |||
CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED => "Method of {$this->blackListDescription} class must not be called", | |||
CodeChecker::CLASS_EXTENDS_NOT_ALLOWED => "%s class must not be extended", | |||
CodeChecker::CLASS_IMPLEMENTS_NOT_ALLOWED => "%s interface must not be implemented", | |||
CodeChecker::STATIC_CALL_NOT_ALLOWED => "Static method of %s class must not be called", | |||
CodeChecker::CLASS_CONST_FETCH_NOT_ALLOWED => "Constant of %s class must not not be fetched", | |||
CodeChecker::CLASS_NEW_NOT_ALLOWED => "%s class must not be instantiated", | |||
CodeChecker::CLASS_USE_NOT_ALLOWED => "%s class must not be imported with a use statement", | |||
CodeChecker::CLASS_METHOD_CALL_NOT_ALLOWED => "Method of %s class must not be called", | |||
CodeChecker::OP_OPERATOR_USAGE_DISCOURAGED => "is discouraged", | |||
]; | |||
@@ -171,7 +174,7 @@ class NodeVisitor extends NodeVisitorAbstract { | |||
if ($node instanceof Node\Expr\New_) { | |||
if (!is_null($node->class)) { | |||
if ($node->class instanceof Name) { | |||
$this->checkBlackList($node->class->toString(), CodeChecker::CLASS_NEW_FETCH_NOT_ALLOWED, $node); | |||
$this->checkBlackList($node->class->toString(), CodeChecker::CLASS_NEW_NOT_ALLOWED, $node); | |||
} | |||
if ($node->class instanceof Node\Expr\Variable) { | |||
/** | |||
@@ -294,7 +297,8 @@ class NodeVisitor extends NodeVisitorAbstract { | |||
private function buildReason($name, $errorCode) { | |||
if (isset($this->errorMessages[$errorCode])) { | |||
return $this->errorMessages[$errorCode]; | |||
$desc = $this->list->getDescription($errorCode, $name); | |||
return sprintf($this->errorMessages[$errorCode], $desc); | |||
} | |||
return "$name usage not allowed - error: $errorCode"; |
@@ -23,30 +23,19 @@ | |||
namespace OC\App\CodeChecker; | |||
class PrivateCheck implements ICheck { | |||
/** @var ICheck */ | |||
protected $check; | |||
/** | |||
* @param ICheck $check | |||
*/ | |||
public function __construct(ICheck $check) { | |||
$this->check = $check; | |||
} | |||
class PrivateCheck extends AbstractCheck implements ICheck { | |||
/** | |||
* @return string | |||
*/ | |||
public function getDescription() { | |||
$innerDescription = $this->check->getDescription(); | |||
return 'private' . (($innerDescription === '') ? '' : ' ' . $innerDescription); | |||
protected function getLocalDescription() { | |||
return 'private'; | |||
} | |||
/** | |||
* @return array | |||
*/ | |||
public function getClasses() { | |||
return array_merge([ | |||
public function getLocalClasses() { | |||
return [ | |||
// classes replaced by the public api | |||
'OC_API' => '6.0.0', | |||
'OC_App' => '6.0.0', | |||
@@ -71,34 +60,27 @@ class PrivateCheck implements ICheck { | |||
'OC_Template' => '6.0.0', | |||
'OC_User' => '6.0.0', | |||
'OC_Util' => '6.0.0', | |||
], $this->check->getClasses()); | |||
]; | |||
} | |||
/** | |||
* @return array | |||
*/ | |||
public function getConstants() { | |||
return $this->check->getConstants(); | |||
public function getLocalConstants() { | |||
return []; | |||
} | |||
/** | |||
* @return array | |||
*/ | |||
public function getFunctions() { | |||
return $this->check->getFunctions(); | |||
public function getLocalFunctions() { | |||
return []; | |||
} | |||
/** | |||
* @return array | |||
*/ | |||
public function getMethods() { | |||
return $this->check->getMethods(); | |||
} | |||
/** | |||
* @return bool | |||
*/ | |||
public function checkStrongComparisons() { | |||
return $this->check->checkStrongComparisons(); | |||
public function getLocalMethods() { | |||
return []; | |||
} | |||
} |
@@ -35,10 +35,12 @@ class StrongComparisonCheck implements ICheck { | |||
} | |||
/** | |||
* @param int $errorCode | |||
* @param string $errorObject | |||
* @return string | |||
*/ | |||
public function getDescription() { | |||
return $this->check->getDescription(); | |||
public function getDescription($errorCode, $errorObject) { | |||
return $this->check->getDescription($errorCode, $errorObject); | |||
} | |||
/** |
@@ -35,9 +35,11 @@ class TestList implements ICheck { | |||
} | |||
/** | |||
* @param int $errorCode | |||
* @param string $errorObject | |||
* @return string | |||
*/ | |||
public function getDescription() { | |||
public function getDescription($errorCode, $errorObject) { | |||
return 'testing'; | |||
} | |||