mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Treat methods of internal or psalm internal classes as internal (#3698)
When both the method and the class are annotated as psalm-internal, but to different namespaces, we consider the method internal to whichever namespace is longer, i.e. the smaller code module. Issue reported at https://github.com/vimeo/psalm/issues/3457
This commit is contained in:
parent
0f727e7607
commit
3f8aa64ee9
@ -68,6 +68,7 @@ use function substr;
|
|||||||
use function trim;
|
use function trim;
|
||||||
use function preg_split;
|
use function preg_split;
|
||||||
use php_user_filter;
|
use php_user_filter;
|
||||||
|
use function strlen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -2133,6 +2134,12 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
|
|
||||||
$doc_comment = $stmt->getDocComment();
|
$doc_comment = $stmt->getDocComment();
|
||||||
|
|
||||||
|
|
||||||
|
if ($class_storage && ! $class_storage->is_trait) {
|
||||||
|
$storage->internal = $class_storage->internal;
|
||||||
|
$storage->psalm_internal = $class_storage->psalm_internal;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$doc_comment) {
|
if (!$doc_comment) {
|
||||||
if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod
|
if ($stmt instanceof PhpParser\Node\Stmt\ClassMethod
|
||||||
&& $stmt->name->name === '__construct'
|
&& $stmt->name->name === '__construct'
|
||||||
@ -2190,7 +2197,12 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements PhpParse
|
|||||||
$storage->internal = true;
|
$storage->internal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($docblock_info->psalm_internal) {
|
if (null === $class_storage ||
|
||||||
|
null === $class_storage->psalm_internal ||
|
||||||
|
(null !== $docblock_info->psalm_internal &&
|
||||||
|
strlen($docblock_info->psalm_internal) > strlen($class_storage->psalm_internal)
|
||||||
|
)
|
||||||
|
) {
|
||||||
$storage->psalm_internal = $docblock_info->psalm_internal;
|
$storage->psalm_internal = $docblock_info->psalm_internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,30 @@ class InternalAnnotationTest extends TestCase
|
|||||||
}
|
}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'internalClassWithInstanceCall' => [
|
||||||
|
'<?php
|
||||||
|
namespace A {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class Foo {
|
||||||
|
public function barBar(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFoo(): Foo {
|
||||||
|
return new Foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace A\B {
|
||||||
|
class Bat {
|
||||||
|
public function batBat(): void {
|
||||||
|
\A\getFoo()->barBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
'internalClassExtendingNamespaceWithStaticCall' => [
|
'internalClassExtendingNamespaceWithStaticCall' => [
|
||||||
'<?php
|
'<?php
|
||||||
namespace A {
|
namespace A {
|
||||||
@ -244,6 +268,31 @@ class InternalAnnotationTest extends TestCase
|
|||||||
}',
|
}',
|
||||||
'error_message' => 'InternalClass',
|
'error_message' => 'InternalClass',
|
||||||
],
|
],
|
||||||
|
'internalClassWithInstanceCall' => [
|
||||||
|
'<?php
|
||||||
|
namespace A {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class Foo {
|
||||||
|
public function barBar(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFoo(): Foo {
|
||||||
|
return new Foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace B {
|
||||||
|
class Bat {
|
||||||
|
public function batBat(): void {
|
||||||
|
\A\getFoo()->barBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
'error_message' => 'InternalMethod',
|
||||||
|
],
|
||||||
'internalClassWithNew' => [
|
'internalClassWithNew' => [
|
||||||
'<?php
|
'<?php
|
||||||
namespace A {
|
namespace A {
|
||||||
|
@ -64,7 +64,7 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public static function barBar(): void {
|
public static function barBar(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function foo(): void {
|
public static function foo(): void {
|
||||||
self::barBar();
|
self::barBar();
|
||||||
}
|
}
|
||||||
@ -92,6 +92,31 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
}
|
}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'internalClassWithInstanceCall' => [
|
||||||
|
'<?php
|
||||||
|
namespace A\B {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @psalm-internal A\B
|
||||||
|
*/
|
||||||
|
class Foo {
|
||||||
|
public function barBar(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFoo(): Foo {
|
||||||
|
return new Foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace A\B\C {
|
||||||
|
class Bat {
|
||||||
|
public function batBat(\A\B\Foo $instance): void {
|
||||||
|
\A\B\getFoo()->barBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
'internalClassExtendingNamespaceWithStaticCall' => [
|
'internalClassExtendingNamespaceWithStaticCall' => [
|
||||||
'<?php
|
'<?php
|
||||||
namespace A {
|
namespace A {
|
||||||
@ -294,6 +319,32 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
}',
|
}',
|
||||||
'error_message' => 'InternalClass',
|
'error_message' => 'InternalClass',
|
||||||
],
|
],
|
||||||
|
'internalClassWithInstanceCall' => [
|
||||||
|
'<?php
|
||||||
|
namespace A\B {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @psalm-internal A\B
|
||||||
|
*/
|
||||||
|
class Foo {
|
||||||
|
public function barBar(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFoo(): Foo {
|
||||||
|
return new Foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace A\C {
|
||||||
|
class Bat {
|
||||||
|
public function batBat(): void {
|
||||||
|
\A\B\getFoo()->barBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
'error_message' => 'The method A\B\Foo::barBar has been marked as internal to A\B',
|
||||||
|
],
|
||||||
'internalClassWithNew' => [
|
'internalClassWithNew' => [
|
||||||
'<?php
|
'<?php
|
||||||
namespace A\B {
|
namespace A\B {
|
||||||
@ -387,10 +438,10 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
'internalPropertyMissingNamespace' => [
|
'internalPropertyMissingNamespace' => [
|
||||||
'<?php
|
'<?php
|
||||||
class Foo {
|
class Foo {
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
* @internal
|
* @internal
|
||||||
* @psalm-internal
|
* @psalm-internal
|
||||||
*/
|
*/
|
||||||
var $bar;
|
var $bar;
|
||||||
}
|
}
|
||||||
@ -401,8 +452,8 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
'<?php
|
'<?php
|
||||||
class Foo {
|
class Foo {
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
* @psalm-internal
|
* @psalm-internal
|
||||||
*/
|
*/
|
||||||
function Bar(): void {}
|
function Bar(): void {}
|
||||||
}
|
}
|
||||||
@ -429,7 +480,7 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
* @var int
|
* @var int
|
||||||
* @psalm-internal A\B
|
* @psalm-internal A\B
|
||||||
*/
|
*/
|
||||||
public $foo;
|
public $foo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
',
|
',
|
||||||
@ -438,13 +489,13 @@ class PsalmInternalAnnotationTest extends TestCase
|
|||||||
'internalFunctionMissingInternalAnnotation' => [
|
'internalFunctionMissingInternalAnnotation' => [
|
||||||
'<?php
|
'<?php
|
||||||
namespace A\B {
|
namespace A\B {
|
||||||
class Foo {
|
class Foo {
|
||||||
/**
|
/**
|
||||||
* @psalm-internal A\B
|
* @psalm-internal A\B
|
||||||
*/
|
*/
|
||||||
public function foo()
|
public function foo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
',
|
',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user