From 032edd95aa0abbedddb55f494a3bf4d59eab7847 Mon Sep 17 00:00:00 2001 From: kkmuffme <11071985+kkmuffme@users.noreply.github.com> Date: Thu, 28 Mar 2024 02:36:19 +0100 Subject: [PATCH] add support for @internal in functions --- .../Expression/Call/FunctionCallAnalyzer.php | 27 ++++++ tests/InternalAnnotationTest.php | 90 +++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php index 98e192c72f7..0d27349bf1c 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php @@ -10,6 +10,7 @@ use Psalm\Internal\Algebra\FormulaGenerator; use Psalm\Internal\Analyzer\AlgebraAnalyzer; use Psalm\Internal\Analyzer\FunctionLikeAnalyzer; +use Psalm\Internal\Analyzer\NamespaceAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer; use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer; @@ -23,6 +24,8 @@ use Psalm\Internal\Type\TypeCombiner; use Psalm\Issue\DeprecatedFunction; use Psalm\Issue\ImpureFunctionCall; +use Psalm\Issue\InternalClass; +use Psalm\Issue\InternalMethod; use Psalm\Issue\InvalidFunctionCall; use Psalm\Issue\MixedFunctionCall; use Psalm\Issue\NullFunctionCall; @@ -402,6 +405,30 @@ public static function analyze( $statements_analyzer->getSuppressedIssues(), ); } + + if (!$context->collect_initializations + && !$context->collect_mutations + && $function_call_info->function_id !== null + ) { + $caller_identifier = $statements_analyzer->getFullyQualifiedFunctionMethodOrNamespaceName(); + if ($caller_identifier !== null + && !NamespaceAnalyzer::isWithinAny( + $caller_identifier, + $function_call_info->function_storage->internal, + )) { + IssueBuffer::maybeAdd( + new InternalMethod( + 'The function ' . $function_call_info->function_id + . ' is internal to ' + . InternalClass::listToPhrase($function_call_info->function_storage->internal) + . ' but called from ' . ($caller_identifier ?: 'root namespace'), + $code_location, + $function_call_info->function_id, + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + } } if ($function_name instanceof PhpParser\Node\Name && $function_call_info->function_id) { diff --git a/tests/InternalAnnotationTest.php b/tests/InternalAnnotationTest.php index 87c8a1fb750..3f9443add34 100644 --- a/tests/InternalAnnotationTest.php +++ b/tests/InternalAnnotationTest.php @@ -1080,6 +1080,96 @@ function hello(): void { }', 'error_message' => 'InternalClass', ], + 'internalFunctionOutsideClass' => [ + 'code' => ' 'InternalMethod', + ], + 'internalFunctionOutsideClassGlobalNamespace' => [ + 'code' => ' 'InternalMethod', + ], + 'internalFunctionInsideFunction' => [ + 'code' => ' 'InternalMethod', + ], + 'internalFunctionInsideFunctionGlobalNamespace' => [ + 'code' => ' 'InternalMethod', + ], + 'internalFunctionInsideClass' => [ + 'code' => ' 'InternalMethod', + ], + 'internalFunctionInsideClassGlobalNamespace' => [ + 'code' => ' 'InternalMethod', + ], 'magicPropertyGetInternalExplicit' => [ 'code' => '