mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Improve accuracy and durability of mixed counts
This commit is contained in:
parent
07768cf505
commit
ee56419fd6
@ -1178,7 +1178,9 @@ class Config
|
||||
*/
|
||||
public function reportTypeStatsForFile($file_path)
|
||||
{
|
||||
return $this->project_files && $this->project_files->reportTypeStats($file_path);
|
||||
return $this->project_files
|
||||
&& $this->project_files->allows($file_path)
|
||||
&& $this->project_files->reportTypeStats($file_path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +133,15 @@ class PropertyAssignmentAnalyzer
|
||||
}
|
||||
|
||||
if ($lhs_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedPropertyAssignment(
|
||||
@ -148,7 +156,15 @@ class PropertyAssignmentAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($lhs_type->isNull()) {
|
||||
if (IssueBuffer::accepts(
|
||||
|
@ -214,7 +214,15 @@ class AssignmentAnalyzer
|
||||
$statements_analyzer
|
||||
);
|
||||
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (!$assign_var instanceof PhpParser\Node\Expr\PropertyFetch
|
||||
&& !strpos($root_var_id ?? '', '->')
|
||||
@ -230,7 +238,15 @@ class AssignmentAnalyzer
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($var_id
|
||||
&& isset($context->byref_constraints[$var_id])
|
||||
|
@ -937,8 +937,16 @@ class BinaryOpAnalyzer
|
||||
|| $left_type_part instanceof TTemplateParam
|
||||
|| $right_type_part instanceof TTemplateParam
|
||||
) {
|
||||
if ($statements_source && $codebase) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_source->getFilePath());
|
||||
if ($statements_source && $codebase && $context) {
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_source->getFilePath() === $statements_source->getRootFilePath()
|
||||
&& (!(($source = $statements_source->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_source->getFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
if ($left_type_part instanceof TMixed || $left_type_part instanceof TTemplateParam) {
|
||||
@ -987,8 +995,16 @@ class BinaryOpAnalyzer
|
||||
return $result_type;
|
||||
}
|
||||
|
||||
if ($statements_source && $codebase) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_source->getFilePath());
|
||||
if ($statements_source && $codebase && $context) {
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_source->getFilePath() === $statements_source->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_source->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_source->getFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
if ($left_type_part instanceof TArray
|
||||
@ -1273,7 +1289,15 @@ class BinaryOpAnalyzer
|
||||
$result_type = Type::getString();
|
||||
|
||||
if ($left_type->hasMixed() || $right_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($left_type->hasMixed()) {
|
||||
if (IssueBuffer::accepts(
|
||||
@ -1300,7 +1324,15 @@ class BinaryOpAnalyzer
|
||||
return;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($left_type->isNull()) {
|
||||
if (IssueBuffer::accepts(
|
||||
|
@ -455,7 +455,15 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
case Type\Atomic\TNonEmptyMixed::class:
|
||||
case Type\Atomic\TObject::class:
|
||||
case Type\Atomic\TObjectWithProperties::class:
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
$has_mixed_method_call = true;
|
||||
|
||||
@ -488,7 +496,15 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
return;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
$has_valid_method_call_type = true;
|
||||
|
||||
|
@ -1193,7 +1193,15 @@ class CallAnalyzer
|
||||
|
||||
if (!isset($arg->value->inferredType)) {
|
||||
if ($function_param && !$function_param->by_ref) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
$param_type = $function_param->type;
|
||||
|
||||
@ -1486,7 +1494,15 @@ class CallAnalyzer
|
||||
}
|
||||
|
||||
if ($arg_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedArgument(
|
||||
@ -2079,7 +2095,16 @@ class CallAnalyzer
|
||||
}
|
||||
|
||||
if ($input_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedArgument(
|
||||
'Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be mixed, expecting ' .
|
||||
@ -2108,7 +2133,15 @@ class CallAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
$param_type = TypeAnalyzer::simplifyUnionType(
|
||||
$codebase,
|
||||
|
@ -630,7 +630,15 @@ class ArrayFetchAnalyzer
|
||||
if ($type instanceof TString) {
|
||||
if ($in_assignment && $replacement_type) {
|
||||
if ($replacement_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedStringOffsetAssignment(
|
||||
@ -642,7 +650,15 @@ class ArrayFetchAnalyzer
|
||||
// fall through
|
||||
}
|
||||
} else {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,7 +708,15 @@ class ArrayFetchAnalyzer
|
||||
}
|
||||
|
||||
if ($type instanceof TMixed || $type instanceof TTemplateParam || $type instanceof TEmpty) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (!$context->inside_isset) {
|
||||
if ($in_assignment) {
|
||||
@ -723,7 +747,15 @@ class ArrayFetchAnalyzer
|
||||
break;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($type instanceof Type\Atomic\TFalse && $array_type->ignore_falsable_issues) {
|
||||
continue;
|
||||
@ -880,7 +912,15 @@ class ArrayFetchAnalyzer
|
||||
}
|
||||
|
||||
if ($offset_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedArrayOffset(
|
||||
@ -892,7 +932,15 @@ class ArrayFetchAnalyzer
|
||||
// fall through
|
||||
}
|
||||
} else {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($expected_offset_types) {
|
||||
$invalid_offset_type = $expected_offset_types[0];
|
||||
|
@ -88,7 +88,15 @@ class PropertyFetchAnalyzer
|
||||
// we don't need to check anything
|
||||
$stmt->inferredType = $context->vars_in_scope[$var_id];
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($codebase->store_node_types
|
||||
&& (!$context->collect_initializations
|
||||
@ -217,7 +225,15 @@ class PropertyFetchAnalyzer
|
||||
}
|
||||
|
||||
if ($stmt_var_type->hasMixed()) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedPropertyFetch(
|
||||
@ -247,7 +263,15 @@ class PropertyFetchAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getRootFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& (!(($parent_source = $statements_analyzer->getSource())
|
||||
instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer)
|
||||
|| !$parent_source->getSource() instanceof \Psalm\Internal\Analyzer\TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getRootFilePath());
|
||||
}
|
||||
|
||||
if ($stmt_var_type->isNullable() && !$stmt_var_type->ignore_nullable_issues && !$context->inside_isset) {
|
||||
if (IssueBuffer::accepts(
|
||||
|
@ -155,7 +155,13 @@ class ReturnAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& !($source->getSource() instanceof TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new MixedReturnStatement(
|
||||
@ -170,7 +176,13 @@ class ReturnAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
if (!$context->collect_initializations
|
||||
&& !$context->collect_mutations
|
||||
&& $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
|
||||
&& !($source->getSource() instanceof TraitAnalyzer)
|
||||
) {
|
||||
$codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
|
||||
}
|
||||
|
||||
if ($local_return_type->isVoid()) {
|
||||
if (IssueBuffer::accepts(
|
||||
|
@ -292,6 +292,7 @@ class Analyzer
|
||||
$scanned_files = $codebase->scanner->getScannedFiles();
|
||||
$codebase->file_reference_provider->setAnalyzedMethods($this->analyzed_methods);
|
||||
$codebase->file_reference_provider->setFileMaps($this->getFileMaps());
|
||||
$codebase->file_reference_provider->setTypeCoverage($this->mixed_counts);
|
||||
$codebase->file_reference_provider->updateReferenceCache($codebase, $scanned_files);
|
||||
|
||||
if ($codebase->diff_methods) {
|
||||
@ -332,6 +333,7 @@ class Analyzer
|
||||
$diff_map = $statements_provider->getDiffMap();
|
||||
|
||||
$all_referencing_methods = $codebase->file_reference_provider->getMethodsReferencing();
|
||||
$this->mixed_counts = $codebase->file_reference_provider->getTypeCoverage();
|
||||
|
||||
$classlikes = $codebase->classlikes;
|
||||
|
||||
@ -414,6 +416,7 @@ class Analyzer
|
||||
foreach ($this->files_to_analyze as $file_path) {
|
||||
$codebase->file_reference_provider->clearExistingIssuesForFile($file_path);
|
||||
$codebase->file_reference_provider->clearExistingFileMapsForFile($file_path);
|
||||
$this->setMixedCountsForFile($file_path, [0, 0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,7 +602,13 @@ class Analyzer
|
||||
*/
|
||||
public function getMixedCounts()
|
||||
{
|
||||
return $this->mixed_counts;
|
||||
$all_deep_scanned_files = [];
|
||||
|
||||
foreach ($this->files_to_analyze as $file_path => $_) {
|
||||
$all_deep_scanned_files[$file_path] = true;
|
||||
}
|
||||
|
||||
return array_intersect_key($this->mixed_counts, $all_deep_scanned_files);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -636,13 +645,34 @@ class Analyzer
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @return array{int, int}
|
||||
*/
|
||||
public function getTypeInferenceSummary()
|
||||
public function getTotalTypeCoverage(\Psalm\Codebase $codebase)
|
||||
{
|
||||
$mixed_count = 0;
|
||||
$nonmixed_count = 0;
|
||||
|
||||
foreach ($codebase->file_reference_provider->getTypeCoverage() as $file_path => $counts) {
|
||||
if (!$this->config->reportTypeStatsForFile($file_path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($path_mixed_count, $path_nonmixed_count) = $counts;
|
||||
|
||||
if (isset($this->mixed_counts[$file_path])) {
|
||||
$mixed_count += $path_mixed_count;
|
||||
$nonmixed_count += $path_nonmixed_count;
|
||||
}
|
||||
}
|
||||
|
||||
return [$mixed_count, $nonmixed_count];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTypeInferenceSummary(\Psalm\Codebase $codebase)
|
||||
{
|
||||
$all_deep_scanned_files = [];
|
||||
|
||||
foreach ($this->files_to_analyze as $file_path => $_) {
|
||||
@ -653,17 +683,7 @@ class Analyzer
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($all_deep_scanned_files as $file_path => $_) {
|
||||
if (!$this->config->reportTypeStatsForFile($file_path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($this->mixed_counts[$file_path])) {
|
||||
list($path_mixed_count, $path_nonmixed_count) = $this->mixed_counts[$file_path];
|
||||
$mixed_count += $path_mixed_count;
|
||||
$nonmixed_count += $path_nonmixed_count;
|
||||
}
|
||||
}
|
||||
list($mixed_count, $nonmixed_count) = $this->getTotalTypeCoverage($codebase);
|
||||
|
||||
$total = $mixed_count + $nonmixed_count;
|
||||
|
||||
@ -674,12 +694,13 @@ class Analyzer
|
||||
}
|
||||
|
||||
if (!$total) {
|
||||
return 'Psalm was unable to infer types in any of '
|
||||
. $total_files . ' file' . ($total_files > 1 ? 's' : '');
|
||||
return 'Psalm was unable to infer types in the codebase';
|
||||
}
|
||||
|
||||
return 'Psalm was able to infer types for ' . number_format(100 * $nonmixed_count / $total, 3) . '%'
|
||||
. ' of analyzed code (' . $total_files . ' file' . ($total_files > 1 ? 's' : '') . ')';
|
||||
$percentage = $nonmixed_count === $total ? '100' : number_format(100 * $nonmixed_count / $total, 4);
|
||||
|
||||
return 'Psalm was able to infer types for ' . $percentage . '%'
|
||||
. ' of the codebase';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,7 @@ class FileReferenceCacheProvider
|
||||
const CLASS_METHOD_CACHE_NAME = 'class_method_references';
|
||||
const ISSUES_CACHE_NAME = 'issues';
|
||||
const FILE_MAPS_CACHE_NAME = 'file_maps';
|
||||
const TYPE_COVERAGE_CACHE_NAME = 'type_coverage';
|
||||
const CONFIG_HASH_CACHE_NAME = 'config';
|
||||
|
||||
/**
|
||||
@ -267,6 +268,45 @@ class FileReferenceCacheProvider
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array{int, int}>|false
|
||||
*/
|
||||
public function getTypeCoverage()
|
||||
{
|
||||
$cache_directory = Config::getInstance()->getCacheDirectory();
|
||||
|
||||
$type_coverage_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME;
|
||||
|
||||
if ($cache_directory
|
||||
&& file_exists($type_coverage_cache_location)
|
||||
&& !$this->config_changed
|
||||
) {
|
||||
/** @var array<string, array{int, int}> */
|
||||
$type_coverage_cache = unserialize(file_get_contents($type_coverage_cache_location));
|
||||
return $type_coverage_cache;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array{int, int}> $mixed_counts
|
||||
* @return void
|
||||
*/
|
||||
public function setTypeCoverage(array $mixed_counts)
|
||||
{
|
||||
$cache_directory = Config::getInstance()->getCacheDirectory();
|
||||
|
||||
if ($cache_directory) {
|
||||
$type_coverage_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::TYPE_COVERAGE_CACHE_NAME;
|
||||
|
||||
file_put_contents(
|
||||
$type_coverage_cache_location,
|
||||
serialize($mixed_counts)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|false
|
||||
*/
|
||||
|
@ -88,6 +88,11 @@ class FileReferenceProvider
|
||||
*/
|
||||
private static $file_maps = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array{int, int}>
|
||||
*/
|
||||
private static $mixed_counts = [];
|
||||
|
||||
/**
|
||||
* @var ?FileReferenceCacheProvider
|
||||
*/
|
||||
@ -297,6 +302,14 @@ class FileReferenceProvider
|
||||
|
||||
self::$issues = $issues;
|
||||
|
||||
$mixed_counts = $this->cache->getTypeCoverage();
|
||||
|
||||
if ($mixed_counts === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$mixed_counts = $mixed_counts;
|
||||
|
||||
self::$file_maps = $this->cache->getFileMapCache() ?: [];
|
||||
|
||||
return true;
|
||||
@ -338,6 +351,7 @@ class FileReferenceProvider
|
||||
$this->cache->setCachedMethodReferences(self::$class_method_references);
|
||||
$this->cache->setCachedIssues(self::$issues);
|
||||
$this->cache->setFileMapCache(self::$file_maps);
|
||||
$this->cache->setTypeCoverage(self::$mixed_counts);
|
||||
$this->cache->setAnalyzedMethodCache(self::$analyzed_methods);
|
||||
}
|
||||
}
|
||||
@ -447,6 +461,23 @@ class FileReferenceProvider
|
||||
self::$file_maps = $file_maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array{int, int}>
|
||||
*/
|
||||
public function getTypeCoverage()
|
||||
{
|
||||
return self::$mixed_counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array{int, int}> $mixed_counts
|
||||
* @return void
|
||||
*/
|
||||
public function setTypeCoverage(array $mixed_counts)
|
||||
{
|
||||
self::$mixed_counts = array_merge(self::$mixed_counts, $mixed_counts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string, int>>
|
||||
*/
|
||||
|
@ -387,10 +387,8 @@ class IssueBuffer
|
||||
echo 'Checks took ' . number_format(microtime(true) - $start_time, 2) . ' seconds';
|
||||
echo ' and used ' . number_format(memory_get_peak_usage() / (1024 * 1024), 3) . 'MB of memory' . "\n";
|
||||
|
||||
if ($is_full) {
|
||||
$analysis_summary = $codebase->analyzer->getTypeInferenceSummary();
|
||||
echo $analysis_summary . "\n";
|
||||
}
|
||||
$analysis_summary = $codebase->analyzer->getTypeInferenceSummary($codebase);
|
||||
echo $analysis_summary . "\n";
|
||||
|
||||
if ($add_stats) {
|
||||
echo '-----------------' . "\n";
|
||||
|
@ -84,9 +84,15 @@ class ProjectAnalyzerTest extends TestCase
|
||||
|
||||
$this->assertSame(0, \Psalm\IssueBuffer::getErrorCount());
|
||||
|
||||
$codebase = $this->project_analyzer->getCodebase();
|
||||
|
||||
$this->assertSame([0, 4], $codebase->analyzer->getTotalTypeCoverage($codebase));
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (2 files)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$codebase->analyzer->getTypeInferenceSummary(
|
||||
$codebase
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -153,8 +159,10 @@ class ProjectAnalyzerTest extends TestCase
|
||||
\Psalm\IssueBuffer::finish($this->project_analyzer, true, microtime(true));
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (2 files)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
|
||||
$this->project_analyzer->getCodebase()->reloadFiles($this->project_analyzer, []);
|
||||
@ -165,7 +173,9 @@ class ProjectAnalyzerTest extends TestCase
|
||||
|
||||
$this->assertSame(
|
||||
'No files analyzed',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -192,8 +202,10 @@ class ProjectAnalyzerTest extends TestCase
|
||||
\Psalm\IssueBuffer::finish($this->project_analyzer, true, microtime(true));
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (2 files)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
|
||||
$bat_file_path = getcwd() . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'DummyProject' . DIRECTORY_SEPARATOR . 'Bat.php';
|
||||
@ -220,8 +232,10 @@ class Bat
|
||||
$this->assertSame(0, \Psalm\IssueBuffer::getErrorCount());
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (1 file)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -251,8 +265,10 @@ class Bat
|
||||
$this->assertSame(0, \Psalm\IssueBuffer::getErrorCount());
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (2 files)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -282,8 +298,10 @@ class Bat
|
||||
$this->assertSame(0, \Psalm\IssueBuffer::getErrorCount());
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (1 file)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -313,8 +331,10 @@ class Bat
|
||||
$this->assertSame(0, \Psalm\IssueBuffer::getErrorCount());
|
||||
|
||||
$this->assertSame(
|
||||
'Psalm was able to infer types for 100.000% of analyzed code (1 file)',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary()
|
||||
'Psalm was able to infer types for 100% of the codebase',
|
||||
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
|
||||
$this->project_analyzer->getCodebase()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user