1
0
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:
Matthew Brown 2019-03-23 09:50:47 -04:00
parent 07768cf505
commit ee56419fd6
14 changed files with 374 additions and 65 deletions

View File

@ -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);
}
/**

View File

@ -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(

View File

@ -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])

View File

@ -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(

View File

@ -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;

View File

@ -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,

View File

@ -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];

View File

@ -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(

View File

@ -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(

View File

@ -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';
}
/**

View File

@ -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
*/

View File

@ -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>>
*/

View File

@ -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";

View File

@ -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()
)
);
}
}