Skip to content
Permalink
Browse files

Use better system for storing inferred types and assertions

  • Loading branch information
muglug committed Nov 25, 2019
1 parent da489d4 commit 0bcb7863f3a581fe398009946b7b1a64e3981ffc
Showing with 2,247 additions and 1,255 deletions.
  1. +4 −1 examples/TemplateChecker.php
  2. +2 −3 examples/plugins/PreventFloatAssignmentChecker.php
  3. +6 −4 examples/plugins/composer-based/echo-checker/EchoChecker.php
  4. +1 −1 src/Psalm/Codebase.php
  5. +22 −11 src/Psalm/Internal/Analyzer/ClassAnalyzer.php
  6. +7 −2 src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php
  7. +15 −2 src/Psalm/Internal/Analyzer/FileAnalyzer.php
  8. +53 −56 src/Psalm/Internal/Analyzer/FunctionAnalyzer.php
  9. +5 −0 src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeAnalyzer.php
  10. +35 −20 src/Psalm/Internal/Analyzer/FunctionLike/ReturnTypeCollector.php
  11. +23 −14 src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php
  12. +4 −1 src/Psalm/Internal/Analyzer/InterfaceAnalyzer.php
  13. +1 −1 src/Psalm/Internal/Analyzer/NamespaceAnalyzer.php
  14. +22 −8 src/Psalm/Internal/Analyzer/ScopeAnalyzer.php
  15. +5 −0 src/Psalm/Internal/Analyzer/SourceAnalyzer.php
  16. +2 −2 src/Psalm/Internal/Analyzer/Statements/Block/ForAnalyzer.php
  17. +16 −4 src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php
  18. +3 −0 src/Psalm/Internal/Analyzer/Statements/Block/IfAnalyzer.php
  19. +11 −2 src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php
  20. +34 −7 src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php
  21. +3 −0 src/Psalm/Internal/Analyzer/Statements/Block/TryAnalyzer.php
  22. +2 −2 src/Psalm/Internal/Analyzer/Statements/Block/WhileAnalyzer.php
  23. +27 −21 src/Psalm/Internal/Analyzer/Statements/Expression/ArrayAnalyzer.php
  24. +294 −219 src/Psalm/Internal/Analyzer/Statements/Expression/AssertionFinder.php
  25. +66 −47 src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/ArrayAssignmentAnalyzer.php
  26. +13 −5 src/Psalm/Internal/Analyzer/Statements/Expression/Assignment/PropertyAssignmentAnalyzer.php
  27. +35 −30 src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php
  28. +61 −40 src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php
  29. +102 −58 src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php
  30. +39 −29 src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php
  31. +24 −17 src/Psalm/Internal/Analyzer/Statements/Expression/Call/NewAnalyzer.php
  32. +49 −26 src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php
  33. +64 −44 src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php
  34. +63 −44 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php
  35. +18 −13 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ClassConstFetchAnalyzer.php
  36. +5 −5 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ConstFetchAnalyzer.php
  37. +88 −53 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/PropertyFetchAnalyzer.php
  38. +16 −14 src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php
  39. +27 −11 src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php
  40. +7 −7 src/Psalm/Internal/Analyzer/Statements/Expression/TernaryAnalyzer.php
  41. +133 −101 src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php
  42. +21 −16 src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php
  43. +4 −3 src/Psalm/Internal/Analyzer/Statements/ThrowAnalyzer.php
  44. +91 −34 src/Psalm/Internal/Analyzer/StatementsAnalyzer.php
  45. +7 −2 src/Psalm/Internal/Analyzer/TypeAnalyzer.php
  46. +19 −7 src/Psalm/Internal/Codebase/CallMap.php
  47. +2 −1 src/Psalm/Internal/Codebase/Functions.php
  48. +13 −6 src/Psalm/Internal/Codebase/Methods.php
  49. +2 −1 src/Psalm/Internal/Codebase/Reflection.php
  50. +0 −16 src/Psalm/Internal/PropertyMap.php
  51. +123 −0 src/Psalm/Internal/Provider/NodeDataProvider.php
  52. +20 −16 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayColumnReturnTypeProvider.php
  53. +5 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFillReturnTypeProvider.php
  54. +34 −31 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayFilterReturnTypeProvider.php
  55. +27 −22 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMapReturnTypeProvider.php
  56. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayMergeReturnTypeProvider.php
  57. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPointerAdjustmentReturnTypeProvider.php
  58. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayPopReturnTypeProvider.php
  59. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayRandReturnTypeProvider.php
  60. +31 −22 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReduceReturnTypeProvider.php
  61. +10 −4 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayReverseReturnTypeProvider.php
  62. +9 −5 src/Psalm/Internal/Provider/ReturnTypeProvider/ArraySliceReturnTypeProvider.php
  63. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayUniqueReturnTypeProvider.php
  64. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayValuesReturnTypeProvider.php
  65. +7 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/DomNodeAppendChild.php
  66. +13 −5 src/Psalm/Internal/Provider/ReturnTypeProvider/FilterVarReturnTypeProvider.php
  67. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/FirstArgStringReturnTypeProvider.php
  68. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/GetClassMethodsReturnTypeProvider.php
  69. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/GetObjectVarsReturnTypeProvider.php
  70. +15 −8 src/Psalm/Internal/Provider/ReturnTypeProvider/IteratorToArrayReturnTypeProvider.php
  71. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/MktimeReturnTypeProvider.php
  72. +5 −3 src/Psalm/Internal/Provider/ReturnTypeProvider/ParseUrlReturnTypeProvider.php
  73. +7 −4 src/Psalm/Internal/Provider/ReturnTypeProvider/PdoStatementSetFetchMode.php
  74. +8 −4 src/Psalm/Internal/Provider/ReturnTypeProvider/RangeReturnTypeProvider.php
  75. +4 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php
  76. +6 −2 src/Psalm/Internal/Provider/ReturnTypeProvider/VersionCompareReturnTypeProvider.php
  77. +73 −48 src/Psalm/Internal/Scanner/PhpStormMetaScanner.php
  78. +31 −0 src/Psalm/Internal/Visitor/ConditionCloningVisitor.php
  79. +10 −2 src/Psalm/Internal/Visitor/NodeCleanerVisitor.php
  80. +31 −5 src/Psalm/Internal/Visitor/ReflectorVisitor.php
  81. +18 −0 src/Psalm/NodeTypeProvider.php
  82. +2 −0 src/Psalm/StatementsSource.php
  83. +58 −27 src/Psalm/Type/Algebra.php
  84. +1 −1 tests/AlgebraTest.php
  85. +19 −1 tests/AssertAnnotationTest.php
  86. +45 −1 tests/SwitchTypeTest.php
  87. +4 −1 tests/TypeReconciliationTest.php
@@ -159,7 +159,10 @@ protected function checkWithViewClass(Context $context, array $stmts)
$view_method_analyzer->addSuppressedIssue('UndefinedVariable');
}
$statements_source = new StatementsAnalyzer($view_method_analyzer);
$statements_source = new StatementsAnalyzer(
$view_method_analyzer,
new \Psalm\Internal\Provider\NodeDataProvider()
);
$statements_source->analyze($pseudo_method_stmts, $context);
}
@@ -3,7 +3,6 @@
use PhpParser;
use Psalm\Checker;
use Psalm\Checker\StatementsChecker;
use Psalm\Codebase;
use Psalm\CodeLocation;
use Psalm\Context;
@@ -35,8 +34,8 @@ public static function afterExpressionAnalysis(
array &$file_replacements = []
) {
if ($expr instanceof PhpParser\Node\Expr\Assign
&& isset($expr->inferredType)
&& $expr->inferredType->hasFloat()
&& ($expr_type = $statements_source->getNodeTypeProvider()->getType($expr))
&& $expr_type->hasFloat()
) {
if (\Psalm\IssueBuffer::accepts(
new NoFloatAssignment(
@@ -29,10 +29,12 @@ public static function afterStatementAnalysis(
) {
if ($stmt instanceof PhpParser\Node\Stmt\Echo_) {
foreach ($stmt->exprs as $expr) {
if (!isset($expr->inferredType) || $expr->inferredType->hasMixed()) {
$expr_type = $statements_source->getNodeTypeProvider()->getType($expr);
if (!$expr_type || $expr_type->hasMixed()) {
if (IssueBuffer::accepts(
new ArgumentTypeCoercion(
'Echo requires an unescaped string, ' . $expr->inferredType . ' provided',
'Echo requires an unescaped string, ' . $expr_type . ' provided',
new CodeLocation($statements_source, $expr),
'echo'
),
@@ -44,7 +46,7 @@ public static function afterStatementAnalysis(
continue;
}
$types = $expr->inferredType->getTypes();
$types = $expr_type->getTypes();
foreach ($types as $type) {
if ($type instanceof \Psalm\Type\Atomic\TString
@@ -53,7 +55,7 @@ public static function afterStatementAnalysis(
) {
if (IssueBuffer::accepts(
new ArgumentTypeCoercion(
'Echo requires an unescaped string, ' . $expr->inferredType . ' provided',
'Echo requires an unescaped string, ' . $expr_type . ' provided',
new CodeLocation($statements_source, $expr),
'echo'
),
@@ -862,7 +862,7 @@ public function isVariadic($method_id)
*/
public function getMethodReturnType($method_id, &$self_class, array $call_args = [])
{
return $this->methods->getMethodReturnType($method_id, $self_class, $call_args);
return $this->methods->getMethodReturnType($method_id, $self_class, null, $call_args);
}
/**
@@ -646,7 +646,13 @@ public function analyze(
}
if ($this->leftover_stmts) {
(new StatementsAnalyzer($this))->analyze($this->leftover_stmts, $class_context);
(new StatementsAnalyzer(
$this,
new \Psalm\Internal\Provider\NodeDataProvider()
))->analyze(
$this->leftover_stmts,
$class_context
);
}
if (!$storage->abstract) {
@@ -902,7 +908,7 @@ public function analyze(
}
}
$statements_analyzer = new StatementsAnalyzer($this);
$statements_analyzer = new StatementsAnalyzer($this, new \Psalm\Internal\Provider\NodeDataProvider());
$statements_analyzer->analyze($member_stmts, $class_context, $global_context, true);
$config = Config::getInstance();
@@ -1010,7 +1016,7 @@ public function analyze(
if ($plugin_fq_class_name::afterStatementAnalysis(
$class,
$storage,
$this->getSource(),
$this,
$codebase,
$file_manipulations
) === false) {
@@ -1237,7 +1243,12 @@ function (FunctionLikeParameter $param) : PhpParser\Node\Arg {
$method_context->vars_in_scope['$this'] = Type::parseString($fq_class_name);
$method_context->vars_possibly_in_scope['$this'] = true;
$constructor_analyzer->analyze($method_context, $global_context, true);
$constructor_analyzer->analyze(
$method_context,
new \Psalm\Internal\Provider\NodeDataProvider(),
$global_context,
true
);
foreach ($uninitialized_typed_properties as $property_id => $property_storage) {
list(,$property_name) = explode('::$', $property_id);
@@ -1395,13 +1406,6 @@ private function analyzeTraitUse(
foreach ($trait_node->stmts as $trait_stmt) {
if ($trait_stmt instanceof PhpParser\Node\Stmt\ClassMethod) {
if ($trait_stmt->stmts) {
$traverser = new PhpParser\NodeTraverser;
$traverser->addVisitor(new \Psalm\Internal\Visitor\NodeCleanerVisitor());
$traverser->traverse($trait_stmt->stmts);
}
$trait_method_analyzer = $this->analyzeClassMethod(
$trait_stmt,
$storage,
@@ -1637,8 +1641,11 @@ private function analyzeClassMethod(
}
$method_context->collect_exceptions = $config->check_for_throws_docblock;
$type_provider = new \Psalm\Internal\Provider\NodeDataProvider();
$method_analyzer->analyze(
$method_context,
$type_provider,
$global_context ? clone $global_context : null
);
@@ -1650,6 +1657,7 @@ private function analyzeClassMethod(
$stmt,
$method_analyzer,
$source,
$type_provider,
$codebase,
$class_storage,
$class_context->self,
@@ -1673,6 +1681,7 @@ public static function analyzeClassMethodReturnType(
PhpParser\Node\Stmt\ClassMethod $stmt,
MethodAnalyzer $method_analyzer,
SourceAnalyzer $source,
\Psalm\Internal\Provider\NodeDataProvider $type_provider,
Codebase $codebase,
ClassLikeStorage $class_storage,
string $fq_classlike_name,
@@ -1778,6 +1787,7 @@ public static function analyzeClassMethodReturnType(
FunctionLike\ReturnTypeAnalyzer::verifyReturnType(
$stmt,
$source,
$type_provider,
$method_analyzer,
$interface_return_type,
$interface_class,
@@ -1790,6 +1800,7 @@ public static function analyzeClassMethodReturnType(
FunctionLike\ReturnTypeAnalyzer::verifyReturnType(
$stmt,
$source,
$type_provider,
$method_analyzer,
$return_type,
$fq_classlike_name,
@@ -137,7 +137,7 @@ public function getMethodMutations(
) {
$method_analyzer = new MethodAnalyzer($stmt, $this);
$method_analyzer->analyze($context, null, true);
$method_analyzer->analyze($context, new \Psalm\Internal\Provider\NodeDataProvider(), null, true);
} elseif ($stmt instanceof PhpParser\Node\Stmt\TraitUse) {
foreach ($stmt->traits as $trait) {
$fq_trait_name = self::getFQCLNFromNameObject(
@@ -172,7 +172,12 @@ public function getMethodMutations(
}
}
$method_analyzer->analyze($context, null, true);
$method_analyzer->analyze(
$context,
new \Psalm\Internal\Provider\NodeDataProvider(),
null,
true
);
}
}
@@ -106,6 +106,9 @@ class FileAnalyzer extends SourceAnalyzer implements StatementsSource
*/
private $first_statement_offset = -1;
/** @var ?\Psalm\Internal\Provider\NodeDataProvider */
private $node_data;
/**
* @param string $file_path
* @param string $file_name
@@ -176,10 +179,11 @@ public function analyze(
}
}
$statements_analyzer = new StatementsAnalyzer($this);
$leftover_stmts = $this->populateCheckers($stmts);
$this->node_data = new \Psalm\Internal\Provider\NodeDataProvider();
$statements_analyzer = new StatementsAnalyzer($this, $this->node_data);
// if there are any leftover statements, evaluate them,
// in turn causing the classes/interfaces be evaluated
if ($leftover_stmts) {
@@ -638,6 +642,15 @@ public function getFirstStatementOffset() : int
return $this->first_statement_offset;
}
public function getNodeTypeProvider() : \Psalm\NodeTypeProvider
{
if (!$this->node_data) {
throw new \UnexpectedValueException('There should be a node type provider');
}
return $this->node_data;
}
public function clearSourceBeforeDestruction() : void
{
/** @psalm-suppress PossiblyNullPropertyAssignmentValue */

0 comments on commit 0bcb786

Please sign in to comment.
You can’t perform that action at this time.