1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-29 20:28:59 +01:00

document that @psalm-internal works for namespace + class too

as used in https://github.com/vimeo/psalm/issues/9584
This commit is contained in:
kkmuffme 2024-03-27 23:44:34 +01:00
parent 4b01704558
commit c8f0671b33
2 changed files with 158 additions and 5 deletions

View File

@ -252,9 +252,10 @@ $b = $a->bar(); // this call fails
### `@psalm-internal`
Used to mark a class, property or function as internal to a given namespace. Psalm treats this slightly differently to
the PHPDoc `@internal` tag. For `@internal`, an issue is raised if the calling code is in a namespace completely
unrelated to the namespace of the calling code, i.e. not sharing the first element of the namespace.
Used to mark a class, property or function as internal to a given namespace or class or even method.
Psalm treats this slightly differently to the PHPDoc `@internal` tag. For `@internal`,
an issue is raised if the calling code is in a namespace completely unrelated to the namespace of the calling code,
i.e. not sharing the first element of the namespace.
In contrast for `@psalm-internal`, the docblock line must specify a namespace. An issue is raised if the calling code
is not within the given namespace.
@ -272,7 +273,15 @@ namespace A\B {
namespace A\B\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
$a = new \A\B\Foo(); // this is fine
}
}
}
namespace A {
class B {
public function batBat(): void {
$a = new \A\B\Foo(); // this is fine
}
}
}
@ -280,7 +289,28 @@ namespace A\B\C {
namespace A\C {
class Bat {
public function batBat(): void {
$a = new \A\B\Foo(); // error
$a = new \A\B\Foo(); // error
}
}
}
namespace X {
class Foo {
/**
* @psalm-internal Y\Bat::batBat
*/
public static function barBar(): void {
}
}
}
namespace Y {
class Bat {
public function batBat() : void {
\X\Foo::barBar(); // this is fine
}
public function fooFoo(): void {
\X\Foo::barBar(); // error
}
}
}

View File

@ -606,6 +606,66 @@ class InternalAnnotationTest extends TestCase
}
',
],
'psalmInternalClassWithCallClass' => [
'code' => '<?php
namespace A {
/**
* @psalm-internal B\Bat
*/
class Foo {
public static function barBar(): void {
}
}
}
namespace B {
class Bat {
public function batBat() : void {
\A\Foo::barBar();
}
}
}',
],
'psalmInternalMethodWithCallClass' => [
'code' => '<?php
namespace A {
class Foo {
/**
* @psalm-internal B\Bat
*/
public static function barBar(): void {
}
}
}
namespace B {
class Bat {
public function batBat() : void {
\A\Foo::barBar();
}
}
}',
],
'psalmInternalMethodWithMethod' => [
'code' => '<?php
namespace X {
class Foo {
/**
* @psalm-internal Y\Bat::batBat
*/
public static function barBar(): void {
}
}
}
namespace Y {
class Bat {
public function batBat() : void {
\X\Foo::barBar();
}
}
}',
],
'callToInternalMethodFromAnonymousClass' => [
'code' => <<<'PHP'
<?php
@ -1118,6 +1178,69 @@ class InternalAnnotationTest extends TestCase
',
'error_message' => 'InternalMethod',
],
'psalmInternalClassWithCallClass' => [
'code' => '<?php
namespace A {
/**
* @psalm-internal B\Bar
*/
class Foo {
public static function barBar(): void {
}
}
}
namespace B {
class Bat {
public function batBat() : void {
\A\Foo::barBar();
}
}
}',
'error_message' => 'InternalClass',
],
'psalmInternalMethodWithCallClass' => [
'code' => '<?php
namespace A {
class Foo {
/**
* @psalm-internal B\Bar
*/
public static function barBar(): void {
}
}
}
namespace B {
class Bat {
public function batBat() : void {
\A\Foo::barBar();
}
}
}',
'error_message' => 'InternalMethod',
],
'psalmInternalMethodWithMethod' => [
'code' => '<?php
namespace X {
class Foo {
/**
* @psalm-internal Y\Bat::batBat
*/
public static function barBar(): void {
}
}
}
namespace Y {
class Bat {
public function fooFoo(): void {
\X\Foo::barBar();
}
}
}',
'error_message' => 'InternalMethod',
],
];
}
}