From 4d224d56dbaccb6c845a7d47cb4f0b8c15d32e6e Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Tue, 25 Oct 2016 11:40:09 -0400 Subject: [PATCH] Handle user-defined code in root namespace (e.g. OAuth) better --- src/Psalm/Checker/ClassLikeChecker.php | 14 ++++++++++++++ src/Psalm/Checker/FunctionLikeChecker.php | 17 +++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/Psalm/Checker/ClassLikeChecker.php b/src/Psalm/Checker/ClassLikeChecker.php index 4753fdf0b..a3bdc36ed 100644 --- a/src/Psalm/Checker/ClassLikeChecker.php +++ b/src/Psalm/Checker/ClassLikeChecker.php @@ -154,6 +154,13 @@ abstract class ClassLikeChecker implements StatementsSource */ protected static $registered_classes = []; + /** + * A lookup table to record which classes are user-defined + * + * @var array + */ + protected static $user_defined = []; + /** * A lookup table used for storing the results of ClassChecker::classImplements * @@ -195,6 +202,7 @@ abstract class ClassLikeChecker implements StatementsSource $config = Config::getInstance(); self::$registered_classes[$this->absolute_class] = true; + self::$user_defined[$this->absolute_class] = true; $leftover_stmts = []; @@ -1021,6 +1029,12 @@ abstract class ClassLikeChecker implements StatementsSource return isset(self::$file_classes[$file_name]) ? array_unique(self::$file_classes[$file_name]) : []; } + public static function isUserDefined($absolute_class) + { + self::registerClass($absolute_class); + return isset(self::$user_defined[$absolute_class]); + } + public static function clearCache() { self::$this_class = null; diff --git a/src/Psalm/Checker/FunctionLikeChecker.php b/src/Psalm/Checker/FunctionLikeChecker.php index f0e1db6b4..bf144d82c 100644 --- a/src/Psalm/Checker/FunctionLikeChecker.php +++ b/src/Psalm/Checker/FunctionLikeChecker.php @@ -800,14 +800,19 @@ abstract class FunctionLikeChecker implements StatementsSource */ public static function getParamsById($method_id, array $args, $file_name) { - if (FunctionChecker::inCallMap($method_id) || !strpos($method_id, '::')) { - $function_param_options = FunctionChecker::getParamsFromCallMap($method_id); - } - else { + $absolute_class = strpos($method_id, '::') ? explode($method_id, '::')[0] : null; + + if ($absolute_class && ClassLikeChecker::isUserDefined($absolute_class)) { return MethodChecker::getMethodParams($method_id); } - - if ($function_param_options === null) { + elseif (!$absolute_class && FunctionChecker::inCallMap($method_id)) { + $function_param_options = FunctionChecker::getParamsFromCallMap($method_id); + } + elseif ($absolute_class) { + // fall back to using reflected params anyway + return MethodChecker::getMethodParams($method_id); + } + else { return FunctionChecker::getParams(strtolower($method_id), $file_name); }