diff --git a/src/Psalm/Internal/Analyzer/Statements/DeclareAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/DeclareAnalyzer.php new file mode 100644 index 00000000000..3a6da24af1d --- /dev/null +++ b/src/Psalm/Internal/Analyzer/Statements/DeclareAnalyzer.php @@ -0,0 +1,98 @@ +declares as $declaration) { + $declaration_key = (string) $declaration->key; + + if ($declaration_key === 'strict_types') { + self::analyzeStrictTypesDeclaration($statements_analyzer, $declaration, $context); + } elseif ($declaration_key === 'ticks') { + self::analyzeTicksDeclaration($statements_analyzer, $declaration); + } elseif ($declaration_key === 'encoding') { + self::analyzeEncodingDeclaration($statements_analyzer, $declaration); + } else { + IssueBuffer::maybeAdd( + new UnrecognizedStatement( + 'Psalm does not understand the declare statement ' . $declaration->key, + new CodeLocation($statements_analyzer, $declaration), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + } + } + + private static function analyzeStrictTypesDeclaration( + StatementsAnalyzer $statements_analyzer, + PhpParser\Node\Stmt\DeclareDeclare $declaration, + Context $context + ): void { + if (!$declaration->value instanceof PhpParser\Node\Scalar\LNumber + || !in_array($declaration->value->value, [0, 1], true) + ) { + IssueBuffer::maybeAdd( + new UnrecognizedStatement( + 'strict_types declaration can only have 1 or 0 as a value', + new CodeLocation($statements_analyzer, $declaration), + ), + $statements_analyzer->getSuppressedIssues(), + ); + + return; + } + + if ($declaration->value->value === 1) { + $context->strict_types = true; + } + } + + private static function analyzeTicksDeclaration( + StatementsAnalyzer $statements_analyzer, + PhpParser\Node\Stmt\DeclareDeclare $declaration + ): void { + if (!$declaration->value instanceof PhpParser\Node\Scalar\LNumber) { + IssueBuffer::maybeAdd( + new UnrecognizedStatement( + 'ticks declaration should have integer as a value', + new CodeLocation($statements_analyzer, $declaration), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + } + + private static function analyzeEncodingDeclaration( + StatementsAnalyzer $statements_analyzer, + PhpParser\Node\Stmt\DeclareDeclare $declaration + ): void { + if (!$declaration->value instanceof PhpParser\Node\Scalar\String_) { + IssueBuffer::maybeAdd( + new UnrecognizedStatement( + 'encoding declaration should have string as a value', + new CodeLocation($statements_analyzer, $declaration), + ), + $statements_analyzer->getSuppressedIssues(), + ); + } + } +} diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index f1d4044bfc1..dfe109cc0b7 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -21,6 +21,7 @@ use Psalm\Internal\Analyzer\Statements\Block\WhileAnalyzer; use Psalm\Internal\Analyzer\Statements\BreakAnalyzer; use Psalm\Internal\Analyzer\Statements\ContinueAnalyzer; +use Psalm\Internal\Analyzer\Statements\DeclareAnalyzer; use Psalm\Internal\Analyzer\Statements\EchoAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\Assignment\InstancePropertyAssignmentAnalyzer; use Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer; @@ -597,14 +598,7 @@ private static function analyzeStatement( } elseif ($stmt instanceof PhpParser\Node\Stmt\Label) { // do nothing } elseif ($stmt instanceof PhpParser\Node\Stmt\Declare_) { - foreach ($stmt->declares as $declaration) { - if ((string) $declaration->key === 'strict_types' - && $declaration->value instanceof PhpParser\Node\Scalar\LNumber - && $declaration->value->value === 1 - ) { - $context->strict_types = true; - } - } + DeclareAnalyzer::analyze($statements_analyzer, $stmt, $context); } elseif ($stmt instanceof PhpParser\Node\Stmt\HaltCompiler) { $context->has_returned = true; } else { diff --git a/tests/Internal/Analyzer/DeclareAnalyzerTest.php b/tests/Internal/Analyzer/DeclareAnalyzerTest.php new file mode 100644 index 00000000000..9583ec807ae --- /dev/null +++ b/tests/Internal/Analyzer/DeclareAnalyzerTest.php @@ -0,0 +1,73 @@ + [ + 'code' => <<<'PHP' + [ + 'code' => <<<'PHP' + [ + 'code' => <<<'PHP' + [ + 'code' => <<<'PHP' + [ + 'code' => <<<'PHP' + 'UnrecognizedStatement', + ]; + + yield 'declareUnknownValueForStrictTypes' => [ + 'code' => <<<'PHP' + 'UnrecognizedStatement', + ]; + + yield 'declareInvalidValueForTicks' => [ + 'code' => <<<'PHP' + 'UnrecognizedStatement', + ]; + + yield 'declareInvalidValueForEncoding' => [ + 'code' => <<<'PHP' + 'UnrecognizedStatement', + ]; + } +}