[ 'foo = "hello"; $a->bar = "hello"; // not a property', ], 'propertyOfTypeClassDocblock' => [ 'foo = new PropertyType();', ], 'propertySealedDocblockDefinedPropertyFetch' => [ 'foo;', ], /** * With a magic setter and no annotations specifying properties or types, we can * set anything we want on any variable name. The magic setter is trusted to figure * it out. */ 'magicSetterUndefinedPropertyNoAnnotation' => [ '__set("foo", new stdClass()); } }', ], /** * With a magic getter and no annotations specifying properties or types, we can * get anything we want with any variable name. The magic getter is trusted to figure * it out. */ 'magicGetterUndefinedPropertyNoAnnotation' => [ '__get("foo"); } }', ], /** * The property $foo is defined as a string with the `@property` annotation. We * use the magic setter to set it to a string, so everything is cool. */ 'magicSetterValidAssignmentType' => [ '__set("foo", "value"); } }', ], 'propertyDocblockAssignmentToMixed' => [ '__set("foo", $b); }', 'assertions' => [], 'error_level' => ['MixedAssignment', 'MixedTypeCoercion'], ], 'namedPropertyByVariable' => [ '$var_name; } return null; } }', ], 'getPropertyExplicitCall' => [ '__get("test"); } }', ], 'inheritedGetPropertyExplicitCall' => [ '__get("test"); } }', ], 'undefinedThisPropertyFetchWithMagic' => [ 'name; } public function goodGet2(): void { echo $this->otherName; } } $a = new A(); echo $a->name; echo $a->otherName;', ], 'directFetchForMagicProperty' => [ 'test; } }', ], 'magicPropertyFetchOnProtected' => [ 'foo = "bar"; echo $c->foo;', 'assertions' => [], 'error_level' => ['MixedArgument'], ], ]; } /** * @return array */ public function providerFileCheckerInvalidCodeParse() { return [ 'propertyDocblockInvalidAssignment' => [ 'foo = 5;', 'error_message' => 'InvalidPropertyAssignmentValue', ], 'propertyInvalidClassAssignment' => [ 'foo = new SomeOtherPropertyType();', 'error_message' => 'InvalidPropertyAssignmentValue - src' . DIRECTORY_SEPARATOR . 'somefile.php:29 - $a->foo with declared type' . ' \'Bar\PropertyType\' cannot', ], 'propertyWriteDocblockInvalidAssignment' => [ 'foo = 5;', 'error_message' => 'InvalidPropertyAssignmentValue', ], 'propertySealedDocblockUndefinedPropertyAssignment' => [ 'bar = 5;', 'error_message' => 'UndefinedPropertyAssignment', ], 'propertySealedDocblockDefinedPropertyAssignment' => [ 'foo = 5;', 'error_message' => 'InvalidPropertyAssignmentValue', ], 'propertyReadInvalidFetch' => [ 'foo);', 'error_message' => 'InvalidArgument', ], 'propertySealedDocblockUndefinedPropertyFetch' => [ 'bar;', 'error_message' => 'UndefinedPropertyFetch', ], /** * The property $foo is not defined on the object, but accessed with the magic setter. * This is an error because `@psalm-seal-properties` is specified on the class block. */ 'magicSetterUndefinedProperty' => [ '__set("foo", "value"); } }', 'error_message' => 'UndefinedThisPropertyAssignment', ], /** * The property $foo is not defined on the object, but accessed with the magic getter. * This is an error because `@psalm-seal-properties` is specified on the class block. */ 'magicGetterUndefinedProperty' => [ '__get("foo"); } }', 'error_message' => 'UndefinedThisPropertyFetch', ], /** * The property $foo is defined as a string with the `@property` annotation, but * the magic setter is used to set it to an object. */ 'magicSetterInvalidAssignmentType' => [ '__set("foo", new stdClass()); } }', 'error_message' => 'InvalidPropertyAssignmentValue', ], 'propertyDocblockAssignmentToMixed' => [ '__set("foo", $b); }', 'error_message' => 'MixedTypeCoercion', 'error_levels' => ['MixedAssignment'], ], 'misnamedPropertyByVariable' => [ '$var_name; } return null; } }', 'error_message' => 'UndefinedThisPropertyFetch', ], ]; } }