1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Add better class visibiity checks

This commit is contained in:
Matthew Brown 2016-08-07 12:23:29 -04:00
parent 4d26b9b3af
commit 7a1cded329
3 changed files with 47 additions and 16 deletions

View File

@ -69,7 +69,9 @@ class ClassChecker implements StatementsSource
$this->_suppressed_issues = $source->getSuppressedIssues(); $this->_suppressed_issues = $source->getSuppressedIssues();
$this->_parent_class = $this->_class->extends ? ClassChecker::getAbsoluteClassFromName($this->_class->extends, $this->_namespace, $this->_aliased_classes) : null; $this->_parent_class = $this->_class->extends
? ClassChecker::getAbsoluteClassFromName($this->_class->extends, $this->_namespace, $this->_aliased_classes)
: null;
self::$_existing_classes[$absolute_class] = true; self::$_existing_classes[$absolute_class] = true;

View File

@ -57,6 +57,7 @@ class Config
protected $custom_error_levels = [ protected $custom_error_levels = [
'InvalidDocblock' => self::REPORT_INFO, 'InvalidDocblock' => self::REPORT_INFO,
'NullPropertyFetch' => self::REPORT_INFO, 'NullPropertyFetch' => self::REPORT_INFO,
'MissingPropertyDeclaration' => self::REPORT_INFO,
'MixedMethodCall' => self::REPORT_SUPPRESS, 'MixedMethodCall' => self::REPORT_SUPPRESS,
'TooManyArguments' => self::REPORT_SUPPRESS 'TooManyArguments' => self::REPORT_SUPPRESS
]; ];

View File

@ -1132,12 +1132,15 @@ class StatementsChecker
return; return;
} }
$class_visibility = if ($var_name === 'this' || $lhs_type_part->value === $this->_absolute_class) {
$var_name === 'this' $class_visibility = \ReflectionProperty::IS_PRIVATE;
|| $lhs_type_part->value === $this->_absolute_class }
|| ClassChecker::classExtends($lhs_type_part->value, $this->_absolute_class) elseif (ClassChecker::classExtends($lhs_type_part->value, $this->_absolute_class)) {
? \ReflectionProperty::IS_PRIVATE $class_visibility = \ReflectionProperty::IS_PROTECTED;
: \ReflectionProperty::IS_PUBLIC; }
else {
$class_visibility = \ReflectionProperty::IS_PUBLIC;
}
$class_properties = ClassChecker::getInstancePropertiesForClass( $class_properties = ClassChecker::getInstancePropertiesForClass(
$lhs_type_part->value, $lhs_type_part->value,
@ -1221,6 +1224,14 @@ class StatementsChecker
$var_id = 'this->' . $prop_name; $var_id = 'this->' . $prop_name;
} }
else { else {
if (!isset($context->vars_in_scope[$stmt->var->name])) {
if ($this->_checkVariable($stmt->var, $context) === false) {
return false;
}
return;
}
$lhs_type = $context->vars_in_scope[$stmt->var->name]; $lhs_type = $context->vars_in_scope[$stmt->var->name];
if (!$lhs_type) { if (!$lhs_type) {
@ -1277,17 +1288,24 @@ class StatementsChecker
continue; continue;
} }
if ((string) $lhs_type_part === 'stdClass') { if ($lhs_type_part->value === 'stdClass') {
$class_property_types[] = new Type\Union([$lhs_type_part]); $class_property_types[] = new Type\Union([$lhs_type_part]);
continue; continue;
} }
$class_visibility = if (self::isMock($lhs_type_part->value)) {
$stmt->var->name === 'this' return;
|| (string) $lhs_type_part === $this->_absolute_class }
|| ClassChecker::classExtends((string) $lhs_type_part, $this->_absolute_class)
? \ReflectionProperty::IS_PRIVATE if ($stmt->var->name === 'this' || $lhs_type_part->value === $this->_absolute_class) {
: \ReflectionProperty::IS_PUBLIC; $class_visibility = \ReflectionProperty::IS_PRIVATE;
}
elseif (ClassChecker::classExtends($lhs_type_part->value, $this->_absolute_class)) {
$class_visibility = \ReflectionProperty::IS_PROTECTED;
}
else {
$class_visibility = \ReflectionProperty::IS_PUBLIC;
}
$class_properties = ClassChecker::getInstancePropertiesForClass( $class_properties = ClassChecker::getInstancePropertiesForClass(
(string) $lhs_type_part, (string) $lhs_type_part,
@ -2599,9 +2617,19 @@ class StatementsChecker
} }
if ($absolute_class && $this->_check_variables && is_string($stmt->name) && !self::isMock($absolute_class)) { if ($absolute_class && $this->_check_variables && is_string($stmt->name) && !self::isMock($absolute_class)) {
if ($absolute_class === $this->_absolute_class) {
$class_visibility = \ReflectionProperty::IS_PRIVATE;
}
elseif (ClassChecker::classExtends($this->_absolute_class, $absolute_class)) {
$class_visibility = \ReflectionProperty::IS_PROTECTED;
}
else {
$class_visibility = \ReflectionProperty::IS_PUBLIC;
}
$visible_class_properties = ClassChecker::getStaticPropertiesForClass( $visible_class_properties = ClassChecker::getStaticPropertiesForClass(
$absolute_class, $absolute_class,
$absolute_class === $this->_absolute_class ? \ReflectionProperty::IS_PRIVATE : \ReflectionProperty::IS_PUBLIC $class_visibility
); );
if (!isset($visible_class_properties[$stmt->name])) { if (!isset($visible_class_properties[$stmt->name])) {
@ -2612,7 +2640,7 @@ class StatementsChecker
if ($absolute_class !== $this->_absolute_class) { if ($absolute_class !== $this->_absolute_class) {
$all_class_properties = ClassChecker::getStaticPropertiesForClass( $all_class_properties = ClassChecker::getStaticPropertiesForClass(
$absolute_class, $absolute_class,
\ReflectionProperty::IS_PUBLIC \ReflectionProperty::IS_PRIVATE
); );
} }