[ 'code' => 'fooFoo(); } }', ], 'accessibleProtectedMethodFromTrait' => [ 'code' => 'fooFoo(); } }', ], 'accessiblePublicMethodFromTrait' => [ 'code' => 'fooFoo(); } }', ], 'accessiblePrivatePropertyFromTrait' => [ 'code' => 'fooFoo; $this->fooFoo = "hello"; } }', ], 'accessibleProtectedPropertyFromTrait' => [ 'code' => 'fooFoo; $this->fooFoo = "hello"; } }', ], 'accessiblePublicPropertyFromTrait' => [ 'code' => 'fooFoo; $this->fooFoo = "hello"; } }', ], 'accessibleProtectedMethodFromInheritedTrait' => [ 'code' => 'fooFoo(); } }', ], 'accessiblePublicMethodFromInheritedTrait' => [ 'code' => 'fooFoo(); } }', ], 'staticClassMethodFromWithinTrait' => [ 'code' => ' [ 'code' => 'fooFoo("hello");', ], 'redefinedTraitMethodWithAlias' => [ 'code' => 'barBar(); } }', ], 'traitSelf' => [ 'code' => 'g();', 'assertions' => [ '$a' => 'A', ], ], 'parentTraitSelf' => [ 'code' => 'g();', 'assertions' => [ '$a' => 'A', ], ], 'directStaticCall' => [ 'code' => ' [ 'code' => 'foo(); } }', ], 'instanceOfTraitUser' => [ 'code' => ' [ 'code' => 'foo(); } } } class A { use T; } class B { use T; public function foo() : void {} }', ], 'staticClassTraitUser' => [ 'code' => 'foo(); } } } class A { use T; } class B { use T; public function foo() : void {} }', ], 'isAClassTraitUserStringClass' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'getA(); }', ], 'useAndMap' => [ 'code' => ' [ 'code' => ' [ 'code' => 'foo(); } } class A { use T; public function foo(string $s = null) : void { } }', ], 'aliasedMethodInternalCallNoReplacement' => [ 'code' => 'bar(); } public function bar() : int { return 3; } } class A { use T { bar as bat; } public function baz() : int { return $this->bar(); } }', ], 'aliasedMethodInternalCallWithLocalDefinition' => [ 'code' => 'bar(); } }', ], 'allMethodsReplaced' => [ 'code' => 'foo(); } } class C { use T; protected function foo(string $s) : void {} public function bat() : void { $this->foo("bat"); } }', ], 'aliasedPrivateMethodInternalCallWithLocalDefinition' => [ 'code' => 'bar(); } } trait T2 { private function bar() : int { return 3; } } class A { use T1; private function baz() : int { return $this->bar(); } }', ], 'traitClassConst' => [ 'code' => ' [ 'code' => 'getConstants(); $callback = /** @param mixed $v */ function ($v) : bool { return \is_int($v) || \is_string($v); }; if (is_a($type, \Bat::class, true)) { $callback = /** @param mixed $v */ function ($v) : bool { return \is_int($v) && 0 === ($v & $v - 1) && $v > 0; }; } return array_filter($values, $callback); } } class Bar { use Foo; } class Bat { use Foo; }', ], 'nonMemoizedAssertions' => [ 'code' => 'value === $this->value) {} } } } class O {} class A extends O { use T; /** @var string */ private $value; public function __construct(string $string) { $this->value = $string; } } class B extends O { use T; /** @var bool */ private $value; public function __construct(bool $bool) { $this->value = $bool; } }', ], 'manyTraitAliases' => [ 'code' => 'fine(); $b->good(); Bar::foo(); Bar::foobar(); $b::foo(); $b::foobar(); $b->foo(); $b->foobar(); $b->bad();', ], 'inheritedProtectedTraitMethodAccess' => [ 'code' => 'bar(); } }', ], 'inheritedPublicTraitMethodAccess' => [ 'code' => 'bar();', ], 'allowImplementMethodMadePublicInClass' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'bar($f1);', ], 'traitSelfDocblockReturn' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'originalSayHello(); } } class BrokenPerson extends Person { protected function originalSayHello() : string { return "bad"; } }', ], 'instanceofStaticInsideTrait' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'fooFoo(); } }', 'error_message' => 'InaccessibleMethod', ], 'undefinedTrait' => [ 'code' => ' 'UndefinedTrait', ], 'missingPropertyType' => [ 'code' => 'foo = 5; } }', 'error_message' => 'MissingPropertyType - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:32 - Property T::$foo does not have a ' . 'declared type - consider int|null', ], 'missingPropertyTypeWithConstructorInit' => [ 'code' => 'foo = 5; } }', 'error_message' => 'MissingPropertyType - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:32 - Property T::$foo does not have a ' . 'declared type - consider int', ], 'missingPropertyTypeWithConstructorInitAndNull' => [ 'code' => 'foo = 5; } public function makeNull(): void { $this->foo = null; } }', 'error_message' => 'MissingPropertyType - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:32 - Property T::$foo does not have a ' . 'declared type - consider int|null', ], 'missingPropertyTypeWithConstructorInitAndNullDefault' => [ 'code' => 'foo = 5; } }', 'error_message' => 'MissingPropertyType - src' . DIRECTORY_SEPARATOR . 'somefile.php:3:32 - Property T::$foo does not have a ' . 'declared type - consider int|null', ], 'redefinedTraitMethodInSubclass' => [ 'code' => ' 'MethodSignatureMismatch', ], 'missingTraitPropertyType' => [ 'code' => ' 'MissingPropertyType', ], 'nestedTraitWithBadReturnType' => [ 'code' => ' 'InvalidReturnType', ], 'replaceTraitMethod' => [ 'code' => 'foo(); } } class C { use T; protected function foo(string $s) : void {} }', 'error_message' => 'TooFewArguments', ], 'traitMethodMadePrivate' => [ 'code' => 'traitFoo(); } } class D extends C { public function bar() : void { $this->traitFoo(); // should fail } }', 'error_message' => 'InaccessibleMethod', ], 'preventTraitPropertyType' => [ 'code' => ' 'UndefinedDocblockClass', ], ]; } }