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

psalm-internal - extract function NamespaceAnalyzer::isWithin

Also adjust behaviour so things can be internal to classes, not just to
namespace, and namespace comparision is case insensitive
This commit is contained in:
Barney Laurance 2019-05-14 22:30:16 +01:00 committed by Matthew Brown
parent cd673538f1
commit 14843ed58a
8 changed files with 84 additions and 6 deletions

View File

@ -212,7 +212,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer
}
if ($parent_class_storage->psalm_internal &&
strpos($fq_class_name, trim($parent_class_storage->psalm_internal, '\\') . '\\') !== 0
! NamespaceAnalyzer::isWithin($fq_class_name, $parent_class_storage->psalm_internal)
) {
if (IssueBuffer::accepts(
new InternalClass(

View File

@ -212,7 +212,8 @@ class MethodAnalyzer extends FunctionLikeAnalyzer
&& !$context->collect_initializations
&& !$context->collect_mutations
) {
if (strpos($context->self, trim($storage->psalm_internal, '\\') . '\\') !== 0) {
if (! NamespaceAnalyzer::isWithin($context->self, $storage->psalm_internal)
) {
if (IssueBuffer::accepts(
new InternalMethod(
'The method ' . $codebase_methods->getCasedMethodId($method_id) .

View File

@ -166,4 +166,20 @@ class NamespaceAnalyzer extends SourceAnalyzer implements StatementsSource
{
return $this->source;
}
/**
* @param string $namespace Generally a namespace, but may also be a fully qualified class name (FQCN)_.
* @param string $className Generally a FQCN, but may be a FQCN
*
* Returns true if $className is the same as, or starts with $namespace, in a case-insensitive comparision.
*
* @return bool
*/
public static function isWithin(string $className, string $namespace): bool
{
$className = strtolower(trim($className, '\\') . '\\');
$namespace = strtolower(trim($namespace, '\\') . '\\');
return $className === $namespace || strpos($className, $namespace) === 0;
}
}

View File

@ -5,6 +5,7 @@ use PhpParser;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\PropertyProperty;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;
@ -497,7 +498,7 @@ class PropertyAssignmentAnalyzer
}
if ($property_storage->psalm_internal && $context->self) {
if (strpos($context->self, trim($property_storage->psalm_internal, '\\') . '\\') !== 0) {
if (! NamespaceAnalyzer::isWithin($context->self, $property_storage->psalm_internal)) {
if (IssueBuffer::accepts(
new InternalProperty(
$property_id . ' is marked internal to ' . $property_storage->psalm_internal,

View File

@ -5,6 +5,7 @@ use PhpParser;
use Psalm\Internal\Analyzer\ClassAnalyzer;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\MethodAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\CodeLocation;
@ -310,7 +311,7 @@ class NewAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\CallAna
if ($storage->psalm_internal && $context->self) {
if (strpos($context->self, trim($storage->psalm_internal, '\\') . '\\') !== 0) {
if (! NamespaceAnalyzer::isWithin($context->self, $storage->psalm_internal)) {
if (IssueBuffer::accepts(
new InternalClass(
$fq_class_name . ' is marked internal to ' . $storage->psalm_internal,

View File

@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\Call;
use PhpParser;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\MethodAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\CodeLocation;
@ -581,7 +582,7 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
if ($class_storage->psalm_internal
&& $context->self
&& strpos($context->self, trim($class_storage->psalm_internal, '\\') . '\\') !== 0
&& ! NamespaceAnalyzer::isWithin($context->self, $class_storage->psalm_internal)
) {
if (IssueBuffer::accepts(
new InternalClass(

View File

@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\Fetch;
use PhpParser;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\FunctionLikeAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\CodeLocation;
@ -595,7 +596,7 @@ class PropertyFetchAnalyzer
}
if ($property_storage->psalm_internal && $context->self) {
if (strpos($context->self, trim($property_storage->psalm_internal, '\\') . '\\') !== 0) {
if (! NamespaceAnalyzer::isWithin($context->self, $property_storage->psalm_internal)) {
if (IssueBuffer::accepts(
new InternalProperty(
$property_id . ' is marked internal to ' . $property_storage->psalm_internal,

View File

@ -33,6 +33,42 @@ class PsalmInternalAnnotationTest extends TestCase
}
}',
],
'internalMethodWithCallWithCaseMisMatched' => [
'<?php
namespace A\B {
class Foo {
/**
* @psalm-internal A\B
*/
public static function barBar(): void {
}
}
}
namespace a\b\c {
class Bat {
public function batBat() : void {
\A\B\Foo::barBar();
}
}
}',
],
'internalToClassMethodWithCall' => [
'<?php
namespace A\B {
class Foo {
/**
* @psalm-internal A\B\Foo
*/
public static function barBar(): void {
}
public static function foo(): void {
self::barBar();
}
}
}',
],
'internalClassWithStaticCall' => [
'<?php
namespace A\B {
@ -204,6 +240,27 @@ class PsalmInternalAnnotationTest extends TestCase
}',
'error_message' => 'The method A\B\Foo::barBar has been marked as internal to A\B',
],
'internalToClassMethodWithCall' => [
'<?php
namespace A\B {
class Foo {
/**
* @psalm-internal A\B\Foo
*/
public static function barBar(): void {
}
}
}
namespace A\C {
class Bat {
public function batBat(): void {
\A\B\Foo::barBar();
}
}
}',
'error_message' => 'The method A\B\Foo::barBar has been marked as internal to A\B\Foo',
],
'internalClassWithStaticCall' => [
'<?php
namespace A\B {