From 2f2cd85a6aeb5ad36eaad4bd702f2c03e46b2b69 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Fri, 27 Dec 2019 10:34:51 -0500 Subject: [PATCH] Identify invalid static property array assignment --- .../Assignment/ArrayAssignmentAnalyzer.php | 10 ++++++++++ src/Psalm/Internal/Codebase/Analyzer.php | 3 ++- src/Psalm/Internal/Codebase/CallMap.php | 2 +- src/Psalm/Internal/Codebase/Scanner.php | 3 ++- .../Provider/FileReferenceProvider.php | 18 +++++------------- src/Psalm/IssueBuffer.php | 2 +- src/Psalm/Type.php | 2 +- tests/PropertyTypeTest.php | 18 ++++++++++++++++++ 8 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php index c7a29ae7279..99676255694 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php @@ -649,6 +649,16 @@ public static function updateArrayType( return false; } } + } elseif ($root_array_expr instanceof PhpParser\Node\Expr\StaticPropertyFetch + && $root_array_expr->name instanceof PhpParser\Node\Identifier + ) { + PropertyAssignmentAnalyzer::analyzeStatic( + $statements_analyzer, + $root_array_expr, + null, + $root_type, + $context + ); } elseif ($root_var_id) { $context->vars_in_scope[$root_var_id] = $root_type; } diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index eccdd36a1f9..57aec9f3161 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -39,7 +39,8 @@ * snippet_from: int, * snippet_to: int, * column_from: int, - * column_to: int + * column_to: int, + * selected_text: string * } * * @psalm-type TaggedCodeType = array diff --git a/src/Psalm/Internal/Codebase/CallMap.php b/src/Psalm/Internal/Codebase/CallMap.php index e9ef6cf6ce1..598f411c5d1 100644 --- a/src/Psalm/Internal/Codebase/CallMap.php +++ b/src/Psalm/Internal/Codebase/CallMap.php @@ -34,7 +34,7 @@ class CallMap private static $loaded_php_minor_version = null; /** - * @var array>|null + * @var array>|null */ private static $call_map = null; diff --git a/src/Psalm/Internal/Codebase/Scanner.php b/src/Psalm/Internal/Codebase/Scanner.php index 1397b6d35a6..0723d2961d4 100644 --- a/src/Psalm/Internal/Codebase/Scanner.php +++ b/src/Psalm/Internal/Codebase/Scanner.php @@ -38,7 +38,8 @@ * snippet_from: int, * snippet_to: int, * column_from: int, - * column_to: int + * column_to: int, + * selected_text: string * } * * @psalm-type PoolData = array{ diff --git a/src/Psalm/Internal/Provider/FileReferenceProvider.php b/src/Psalm/Internal/Provider/FileReferenceProvider.php index b49711f93af..2cd6d43a0d1 100644 --- a/src/Psalm/Internal/Provider/FileReferenceProvider.php +++ b/src/Psalm/Internal/Provider/FileReferenceProvider.php @@ -25,7 +25,8 @@ * snippet_from: int, * snippet_to: int, * column_from: int, - * column_to: int + * column_to: int, + * selected_text: string * } * * @psalm-type TaggedCodeType = array @@ -63,14 +64,7 @@ class FileReferenceProvider private static $file_references_to_missing_class_members = []; /** - * A lookup table used for getting all the files that reference any other file - * - * @var array> - */ - private static $referencing_files = []; - - /** - * @var array> + * @var array> */ private static $files_inheriting_classes = []; @@ -187,7 +181,6 @@ function ($file_name) { */ public function addFileReferenceToClass(string $source_file, string $fq_class_name_lc) { - self::$referencing_files[$source_file] = true; self::$file_references_to_classes[$fq_class_name_lc][$source_file] = true; } @@ -310,7 +303,7 @@ public function addMethodParamUse(string $method_id, int $offset, string $refere /** * @param string $file * - * @return array + * @return array */ private function calculateFilesReferencingFile(Codebase $codebase, $file) { @@ -333,7 +326,7 @@ private function calculateFilesReferencingFile(Codebase $codebase, $file) /** * @param string $file * - * @return array + * @return array */ private function calculateFilesInheritingFile(Codebase $codebase, $file) { @@ -1015,7 +1008,6 @@ public function getFileMaps() public static function clearCache() { self::$file_references_to_classes = []; - self::$referencing_files = []; self::$files_inheriting_classes = []; self::$deleted_files = null; self::$file_references = []; diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index 3029cd6ba75..aaf5995a712 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -349,7 +349,7 @@ public static function getErrorCount() /** * @param array $issues_data + * snippet_to: int, column_from: int, column_to: int, selected_text: string}> $issues_data * * @return void */ diff --git a/src/Psalm/Type.php b/src/Psalm/Type.php index 51b0b471cf5..193580ac268 100644 --- a/src/Psalm/Type.php +++ b/src/Psalm/Type.php @@ -952,9 +952,9 @@ public static function tokenize($string_type, $ignore_space = true) $was_space = false; } + /** @var list $type_tokens */ self::$memoized_tokens[$string_type] = $type_tokens; - /** @var list */ return $type_tokens; } diff --git a/tests/PropertyTypeTest.php b/tests/PropertyTypeTest.php index d152a782fc4..ebccbb02610 100644 --- a/tests/PropertyTypeTest.php +++ b/tests/PropertyTypeTest.php @@ -2819,6 +2819,24 @@ function takesA(?A $a) : void { }', 'error_message' => 'PossiblyNullArgument', ], + 'catchBadArrayStaticProperty' => [ + ' */ + public array $map = []; + + /** + * @param string $class + */ + public function get(string $class) : void { + $this->map[$class] = 5; + } + }', + 'error_message' => 'InvalidPropertyAssignmentValue' + ], ]; } }