mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix #5810 - detect properties that are never read
This commit is contained in:
parent
4f9067f5c8
commit
6a61298074
@ -95,6 +95,12 @@
|
||||
|
||||
<MissingThrowsDocblock errorLevel="info"/>
|
||||
|
||||
<PossiblyUnusedProperty>
|
||||
<errorLevel type="suppress">
|
||||
<file name="src/Psalm/Report.php"/>
|
||||
</errorLevel>
|
||||
</PossiblyUnusedProperty>
|
||||
|
||||
<PossiblyUnusedMethod>
|
||||
<errorLevel type="info">
|
||||
<file name="src/Psalm/Internal/Provider/FileReferenceProvider.php" />
|
||||
|
@ -2,7 +2,6 @@
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression\Call\Method;
|
||||
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Provider\NodeDataProvider;
|
||||
use PhpParser;
|
||||
|
||||
class AtomicCallContext
|
||||
|
@ -46,12 +46,14 @@ use function implode;
|
||||
* nonmethod_references_to_classes: array<string, array<string,bool>>,
|
||||
* method_references_to_classes: array<string, array<string,bool>>,
|
||||
* file_references_to_class_members: array<string, array<string,bool>>,
|
||||
* file_references_to_class_properties: array<string, array<string,bool>>,
|
||||
* file_references_to_missing_class_members: array<string, array<string,bool>>,
|
||||
* mixed_counts: array<string, array{0: int, 1: int}>,
|
||||
* mixed_member_names: array<string, array<string, bool>>,
|
||||
* function_timings: array<string, float>,
|
||||
* file_manipulations: array<string, FileManipulation[]>,
|
||||
* method_references_to_class_members: array<string, array<string,bool>>,
|
||||
* method_references_to_class_properties: array<string, array<string,bool>>,
|
||||
* method_references_to_missing_class_members: array<string, array<string,bool>>,
|
||||
* method_param_uses: array<string, array<int, array<string, bool>>>,
|
||||
* analyzed_methods: array<string, array<string, int>>,
|
||||
@ -417,7 +419,9 @@ class Analyzer
|
||||
|
||||
$file_reference_provider->setNonMethodReferencesToClasses([]);
|
||||
$file_reference_provider->setCallingMethodReferencesToClassMembers([]);
|
||||
$file_reference_provider->setCallingMethodReferencesToClassProperties([]);
|
||||
$file_reference_provider->setFileReferencesToClassMembers([]);
|
||||
$file_reference_provider->setFileReferencesToClassProperties([]);
|
||||
$file_reference_provider->setCallingMethodReferencesToMissingClassMembers([]);
|
||||
$file_reference_provider->setFileReferencesToMissingClassMembers([]);
|
||||
$file_reference_provider->setReferencesToMixedMemberNames([]);
|
||||
@ -441,6 +445,8 @@ class Analyzer
|
||||
'method_references_to_classes' => $file_reference_provider->getAllMethodReferencesToClasses(),
|
||||
'file_references_to_class_members' => $file_reference_provider->getAllFileReferencesToClassMembers(),
|
||||
'method_references_to_class_members' => $file_reference_provider->getAllMethodReferencesToClassMembers(),
|
||||
'file_references_to_class_properties' => $file_reference_provider->getAllFileReferencesToClassProperties(),
|
||||
'method_references_to_class_properties' => $file_reference_provider->getAllMethodReferencesToClassProperties(),
|
||||
'file_references_to_missing_class_members' => $file_reference_provider->getAllFileReferencesToMissingClassMembers(),
|
||||
'method_references_to_missing_class_members' => $file_reference_provider->getAllMethodReferencesToMissingClassMembers(),
|
||||
'method_param_uses' => $file_reference_provider->getAllMethodParamUses(),
|
||||
@ -497,9 +503,15 @@ class Analyzer
|
||||
$codebase->file_reference_provider->addFileReferencesToClassMembers(
|
||||
$pool_data['file_references_to_class_members']
|
||||
);
|
||||
$codebase->file_reference_provider->addFileReferencesToClassProperties(
|
||||
$pool_data['file_references_to_class_properties']
|
||||
);
|
||||
$codebase->file_reference_provider->addMethodReferencesToClassMembers(
|
||||
$pool_data['method_references_to_class_members']
|
||||
);
|
||||
$codebase->file_reference_provider->addMethodReferencesToClassProperties(
|
||||
$pool_data['method_references_to_class_properties']
|
||||
);
|
||||
$codebase->file_reference_provider->addFileReferencesToMissingClassMembers(
|
||||
$pool_data['file_references_to_missing_class_members']
|
||||
);
|
||||
@ -612,8 +624,10 @@ class Analyzer
|
||||
$diff_map = $statements_provider->getDiffMap();
|
||||
$deletion_ranges = $statements_provider->getDeletionRanges();
|
||||
|
||||
$method_references_to_class_members
|
||||
= $file_reference_provider->getAllMethodReferencesToClassMembers();
|
||||
$method_references_to_class_members = $file_reference_provider->getAllMethodReferencesToClassMembers();
|
||||
|
||||
$method_references_to_class_properties = $file_reference_provider->getAllMethodReferencesToClassProperties();
|
||||
|
||||
$method_references_to_missing_class_members =
|
||||
$file_reference_provider->getAllMethodReferencesToMissingClassMembers();
|
||||
|
||||
@ -625,8 +639,10 @@ class Analyzer
|
||||
|
||||
$method_param_uses = $file_reference_provider->getAllMethodParamUses();
|
||||
|
||||
$file_references_to_class_members
|
||||
= $file_reference_provider->getAllFileReferencesToClassMembers();
|
||||
$file_references_to_class_members = $file_reference_provider->getAllFileReferencesToClassMembers();
|
||||
|
||||
$file_references_to_class_properties = $file_reference_provider->getAllFileReferencesToClassProperties();
|
||||
|
||||
$file_references_to_missing_class_members
|
||||
= $file_reference_provider->getAllFileReferencesToMissingClassMembers();
|
||||
|
||||
@ -707,7 +723,9 @@ class Analyzer
|
||||
|
||||
unset(
|
||||
$method_references_to_class_members[$member_id],
|
||||
$method_references_to_class_properties[$member_id],
|
||||
$file_references_to_class_members[$member_id],
|
||||
$file_references_to_class_properties[$member_id],
|
||||
$method_references_to_missing_class_members[$member_id],
|
||||
$file_references_to_missing_class_members[$member_id],
|
||||
$references_to_mixed_member_names[$member_id],
|
||||
@ -730,6 +748,10 @@ class Analyzer
|
||||
unset($method_references_to_class_members[$i][$method_id]);
|
||||
}
|
||||
|
||||
foreach ($method_references_to_class_properties as $i => $_) {
|
||||
unset($method_references_to_class_properties[$i][$method_id]);
|
||||
}
|
||||
|
||||
foreach ($method_references_to_classes as $i => $_) {
|
||||
unset($method_references_to_classes[$i][$method_id]);
|
||||
}
|
||||
@ -783,6 +805,10 @@ class Analyzer
|
||||
unset($file_references_to_class_members[$i][$file_path]);
|
||||
}
|
||||
|
||||
foreach ($file_references_to_class_properties as $i => $_) {
|
||||
unset($file_references_to_class_properties[$i][$file_path]);
|
||||
}
|
||||
|
||||
foreach ($nonmethod_references_to_classes as $i => $_) {
|
||||
unset($nonmethod_references_to_classes[$i][$file_path]);
|
||||
}
|
||||
@ -810,6 +836,10 @@ class Analyzer
|
||||
$method_references_to_class_members
|
||||
);
|
||||
|
||||
$method_references_to_class_properties = array_filter(
|
||||
$method_references_to_class_properties
|
||||
);
|
||||
|
||||
$method_references_to_missing_class_members = array_filter(
|
||||
$method_references_to_missing_class_members
|
||||
);
|
||||
@ -818,6 +848,10 @@ class Analyzer
|
||||
$file_references_to_class_members
|
||||
);
|
||||
|
||||
$file_references_to_class_properties = array_filter(
|
||||
$file_references_to_class_properties
|
||||
);
|
||||
|
||||
$file_references_to_missing_class_members = array_filter(
|
||||
$file_references_to_missing_class_members
|
||||
);
|
||||
@ -842,10 +876,18 @@ class Analyzer
|
||||
$method_references_to_class_members
|
||||
);
|
||||
|
||||
$file_reference_provider->setCallingMethodReferencesToClassProperties(
|
||||
$method_references_to_class_properties
|
||||
);
|
||||
|
||||
$file_reference_provider->setFileReferencesToClassMembers(
|
||||
$file_references_to_class_members
|
||||
);
|
||||
|
||||
$file_reference_provider->setFileReferencesToClassProperties(
|
||||
$file_references_to_class_properties
|
||||
);
|
||||
|
||||
$file_reference_provider->setCallingMethodReferencesToMissingClassMembers(
|
||||
$method_references_to_missing_class_members
|
||||
);
|
||||
|
@ -2044,7 +2044,7 @@ class ClassLikes
|
||||
|
||||
$property_constructor_referenced = false;
|
||||
if ($property_referenced && $property_storage->visibility === ClassLikeAnalyzer::VISIBILITY_PRIVATE) {
|
||||
$all_method_references = $this->file_reference_provider->getAllMethodReferencesToClassMembers();
|
||||
$all_method_references = $this->file_reference_provider->getAllMethodReferencesToClassProperties();
|
||||
|
||||
if (isset($all_method_references[$referenced_property_name])
|
||||
&& count($all_method_references[$referenced_property_name]) === 1) {
|
||||
|
@ -133,11 +133,25 @@ class Properties
|
||||
$context->calling_method_id,
|
||||
strtolower($declaring_property_class) . '::$' . $property_name
|
||||
);
|
||||
|
||||
if ($read_mode) {
|
||||
$this->file_reference_provider->addMethodReferenceToClassProperty(
|
||||
$context->calling_method_id,
|
||||
strtolower($declaring_property_class) . '::$' . $property_name
|
||||
);
|
||||
}
|
||||
} elseif ($source) {
|
||||
$this->file_reference_provider->addFileReferenceToClassMember(
|
||||
$source->getFilePath(),
|
||||
strtolower($declaring_property_class) . '::$' . $property_name
|
||||
);
|
||||
|
||||
if ($read_mode) {
|
||||
$this->file_reference_provider->addFileReferenceToClassProperty(
|
||||
$source->getFilePath(),
|
||||
strtolower($declaring_property_class) . '::$' . $property_name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->collect_locations && $code_location) {
|
||||
|
@ -25,7 +25,9 @@ class FileReferenceCacheProvider
|
||||
private const METHOD_CLASS_REFERENCE_CACHE_NAME = 'method_class_references';
|
||||
private const ANALYZED_METHODS_CACHE_NAME = 'analyzed_methods';
|
||||
private const CLASS_METHOD_CACHE_NAME = 'class_method_references';
|
||||
private const CLASS_PROPERTY_CACHE_NAME = 'class_property_references';
|
||||
private const FILE_CLASS_MEMBER_CACHE_NAME = 'file_class_member_references';
|
||||
private const FILE_CLASS_PROPERTY_CACHE_NAME = 'file_class_property_references';
|
||||
private const ISSUES_CACHE_NAME = 'issues';
|
||||
private const FILE_MAPS_CACHE_NAME = 'file_maps';
|
||||
private const TYPE_COVERAGE_CACHE_NAME = 'type_coverage';
|
||||
@ -182,6 +184,32 @@ class FileReferenceCacheProvider
|
||||
return $class_member_reference_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public function getCachedMethodPropertyReferences(): ?array
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
|
||||
if (!$cache_directory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class_member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_PROPERTY_CACHE_NAME;
|
||||
|
||||
if (!is_readable($class_member_cache_location)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class_member_reference_cache = unserialize((string) file_get_contents($class_member_cache_location));
|
||||
|
||||
if (!is_array($class_member_reference_cache)) {
|
||||
throw new \UnexpectedValueException('The reference cache must be an array');
|
||||
}
|
||||
|
||||
return $class_member_reference_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
@ -234,6 +262,34 @@ class FileReferenceCacheProvider
|
||||
return $file_class_member_reference_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
public function getCachedFilePropertyReferences(): ?array
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
|
||||
if (!$cache_directory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file_class_member_cache_location = $cache_directory
|
||||
. DIRECTORY_SEPARATOR
|
||||
. self::FILE_CLASS_PROPERTY_CACHE_NAME;
|
||||
|
||||
if (!is_readable($file_class_member_cache_location)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file_class_member_reference_cache = unserialize((string) file_get_contents($file_class_member_cache_location));
|
||||
|
||||
if (!is_array($file_class_member_reference_cache)) {
|
||||
throw new \UnexpectedValueException('The reference cache must be an array');
|
||||
}
|
||||
|
||||
return $file_class_member_reference_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedAssignment
|
||||
*/
|
||||
@ -404,6 +460,19 @@ class FileReferenceCacheProvider
|
||||
file_put_contents($member_cache_location, serialize($member_references));
|
||||
}
|
||||
|
||||
public function setCachedMethodPropertyReferences(array $property_references): void
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
|
||||
if (!$cache_directory) {
|
||||
return;
|
||||
}
|
||||
|
||||
$member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::CLASS_PROPERTY_CACHE_NAME;
|
||||
|
||||
file_put_contents($member_cache_location, serialize($property_references));
|
||||
}
|
||||
|
||||
public function setCachedMethodMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
@ -430,6 +499,19 @@ class FileReferenceCacheProvider
|
||||
file_put_contents($member_cache_location, serialize($member_references));
|
||||
}
|
||||
|
||||
public function setCachedFilePropertyReferences(array $property_references): void
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
|
||||
if (!$cache_directory) {
|
||||
return;
|
||||
}
|
||||
|
||||
$member_cache_location = $cache_directory . DIRECTORY_SEPARATOR . self::FILE_CLASS_PROPERTY_CACHE_NAME;
|
||||
|
||||
file_put_contents($member_cache_location, serialize($property_references));
|
||||
}
|
||||
|
||||
public function setCachedFileMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$cache_directory = $this->config->getCacheDirectory();
|
||||
|
@ -46,6 +46,13 @@ class FileReferenceProvider
|
||||
*/
|
||||
private static $file_references_to_class_members = [];
|
||||
|
||||
/**
|
||||
* A lookup table used for getting all the files that reference a class property
|
||||
*
|
||||
* @var array<string, array<string,bool>>
|
||||
*/
|
||||
private static $file_references_to_class_properties = [];
|
||||
|
||||
/**
|
||||
* A lookup table used for getting all the files that reference a missing class member
|
||||
*
|
||||
@ -77,6 +84,11 @@ class FileReferenceProvider
|
||||
*/
|
||||
private static $method_references_to_class_members = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool>>
|
||||
*/
|
||||
private static $method_references_to_class_properties = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool>>
|
||||
*/
|
||||
@ -206,6 +218,11 @@ class FileReferenceProvider
|
||||
self::$file_references_to_class_members[$referenced_member_id][$source_file] = true;
|
||||
}
|
||||
|
||||
public function addFileReferenceToClassProperty(string $source_file, string $referenced_property_id): void
|
||||
{
|
||||
self::$file_references_to_class_properties[$referenced_property_id][$source_file] = true;
|
||||
}
|
||||
|
||||
public function addFileReferenceToMissingClassMember(string $source_file, string $referenced_member_id): void
|
||||
{
|
||||
self::$file_references_to_missing_class_members[$referenced_member_id][$source_file] = true;
|
||||
@ -219,6 +236,14 @@ class FileReferenceProvider
|
||||
return self::$file_references_to_class_members;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string,bool>>
|
||||
*/
|
||||
public function getAllFileReferencesToClassProperties(): array
|
||||
{
|
||||
return self::$file_references_to_class_properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string,bool>>
|
||||
*/
|
||||
@ -245,6 +270,24 @@ class FileReferenceProvider
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
*/
|
||||
public function addFileReferencesToClassProperties(array $references): void
|
||||
{
|
||||
foreach ($references as $key => $reference) {
|
||||
if (isset(self::$file_references_to_class_properties[$key])) {
|
||||
self::$file_references_to_class_properties[$key] = array_merge(
|
||||
$reference,
|
||||
self::$file_references_to_class_properties[$key]
|
||||
);
|
||||
} else {
|
||||
self::$file_references_to_class_properties[$key] = $reference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
@ -372,6 +415,14 @@ class FileReferenceProvider
|
||||
return self::$method_references_to_class_members;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string, bool>>
|
||||
*/
|
||||
public function getAllMethodReferencesToClassProperties(): array
|
||||
{
|
||||
return self::$method_references_to_class_properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string, bool>>
|
||||
*/
|
||||
@ -444,6 +495,14 @@ class FileReferenceProvider
|
||||
|
||||
self::$method_references_to_class_members = $method_references_to_class_members;
|
||||
|
||||
$method_references_to_class_properties = $this->cache->getCachedMethodPropertyReferences();
|
||||
|
||||
if ($method_references_to_class_properties === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$method_references_to_class_properties = $method_references_to_class_properties;
|
||||
|
||||
$method_references_to_missing_class_members = $this->cache->getCachedMethodMissingMemberReferences();
|
||||
|
||||
if ($method_references_to_missing_class_members === null) {
|
||||
@ -460,6 +519,14 @@ class FileReferenceProvider
|
||||
|
||||
self::$file_references_to_class_members = $file_references_to_class_members;
|
||||
|
||||
$file_references_to_class_properties = $this->cache->getCachedFilePropertyReferences();
|
||||
|
||||
if ($file_references_to_class_properties === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$file_references_to_class_properties = $file_references_to_class_properties;
|
||||
|
||||
$file_references_to_missing_class_members = $this->cache->getCachedFileMissingMemberReferences();
|
||||
|
||||
if ($file_references_to_missing_class_members === null) {
|
||||
@ -556,7 +623,9 @@ class FileReferenceProvider
|
||||
$this->cache->setCachedMethodClassReferences(self::$method_references_to_classes);
|
||||
$this->cache->setCachedNonMethodClassReferences(self::$nonmethod_references_to_classes);
|
||||
$this->cache->setCachedMethodMemberReferences(self::$method_references_to_class_members);
|
||||
$this->cache->setCachedMethodPropertyReferences(self::$method_references_to_class_properties);
|
||||
$this->cache->setCachedFileMemberReferences(self::$file_references_to_class_members);
|
||||
$this->cache->setCachedFilePropertyReferences(self::$file_references_to_class_properties);
|
||||
$this->cache->setCachedMethodMissingMemberReferences(self::$method_references_to_missing_class_members);
|
||||
$this->cache->setCachedFileMissingMemberReferences(self::$file_references_to_missing_class_members);
|
||||
$this->cache->setCachedMixedMemberNameReferences(self::$references_to_mixed_member_names);
|
||||
@ -590,6 +659,15 @@ class FileReferenceProvider
|
||||
}
|
||||
}
|
||||
|
||||
public function addMethodReferenceToClassProperty(string $calling_function_id, string $referenced_property_id): void
|
||||
{
|
||||
if (!isset(self::$method_references_to_class_properties[$referenced_property_id])) {
|
||||
self::$method_references_to_class_properties[$referenced_property_id] = [$calling_function_id => true];
|
||||
} else {
|
||||
self::$method_references_to_class_properties[$referenced_property_id][$calling_function_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function addMethodReferenceToMissingClassMember(
|
||||
string $calling_function_id,
|
||||
string $referenced_member_id
|
||||
@ -638,8 +716,8 @@ class FileReferenceProvider
|
||||
|
||||
public function isClassPropertyReferenced(string $property_id) : bool
|
||||
{
|
||||
return !empty(self::$file_references_to_class_members[$property_id])
|
||||
|| !empty(self::$method_references_to_class_members[$property_id]);
|
||||
return !empty(self::$file_references_to_class_properties[$property_id])
|
||||
|| !empty(self::$method_references_to_class_properties[$property_id]);
|
||||
}
|
||||
|
||||
public function isClassReferenced(string $fq_class_name_lc) : bool
|
||||
@ -728,6 +806,24 @@ class FileReferenceProvider
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
*/
|
||||
public function addMethodReferencesToClassProperties(array $references): void
|
||||
{
|
||||
foreach ($references as $key => $reference) {
|
||||
if (isset(self::$method_references_to_class_properties[$key])) {
|
||||
self::$method_references_to_class_properties[$key] = array_merge(
|
||||
$reference,
|
||||
self::$method_references_to_class_properties[$key]
|
||||
);
|
||||
} else {
|
||||
self::$method_references_to_class_properties[$key] = $reference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
@ -806,6 +902,15 @@ class FileReferenceProvider
|
||||
self::$method_references_to_class_members = $references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
*/
|
||||
public function setCallingMethodReferencesToClassProperties(array $references): void
|
||||
{
|
||||
self::$method_references_to_class_properties = $references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
@ -824,6 +929,15 @@ class FileReferenceProvider
|
||||
self::$file_references_to_class_members = $references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
*/
|
||||
public function setFileReferencesToClassProperties(array $references): void
|
||||
{
|
||||
self::$file_references_to_class_properties = $references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string,bool>> $references
|
||||
*
|
||||
@ -993,7 +1107,9 @@ class FileReferenceProvider
|
||||
self::$deleted_files = null;
|
||||
self::$file_references = [];
|
||||
self::$file_references_to_class_members = [];
|
||||
self::$file_references_to_class_properties = [];
|
||||
self::$method_references_to_class_members = [];
|
||||
self::$method_references_to_class_properties = [];
|
||||
self::$method_references_to_classes = [];
|
||||
self::$nonmethod_references_to_classes = [];
|
||||
self::$file_references_to_missing_class_members = [];
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace Psalm\Storage;
|
||||
|
||||
use Psalm\CodeLocation;
|
||||
|
||||
class EnumCaseStorage
|
||||
{
|
||||
/**
|
||||
|
@ -22,9 +22,15 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
/** @var ?array */
|
||||
private $cached_method_member_references;
|
||||
|
||||
/** @var ?array */
|
||||
private $cached_method_property_references;
|
||||
|
||||
/** @var ?array */
|
||||
private $cached_file_member_references;
|
||||
|
||||
/** @var ?array */
|
||||
private $cached_file_property_references;
|
||||
|
||||
/** @var ?array */
|
||||
private $cached_method_missing_member_references;
|
||||
|
||||
@ -77,7 +83,7 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
|
||||
public function getCachedNonMethodClassReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_class_references;
|
||||
return $this->cached_nonmethod_class_references;
|
||||
}
|
||||
|
||||
public function getCachedFileMemberReferences(): ?array
|
||||
@ -85,11 +91,21 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
return $this->cached_file_member_references;
|
||||
}
|
||||
|
||||
public function getCachedFilePropertyReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_property_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_member_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodPropertyReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_property_references;
|
||||
}
|
||||
|
||||
public function getCachedFileMissingMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_missing_member_references;
|
||||
@ -107,7 +123,7 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
|
||||
public function getCachedMethodParamUses(): ?array
|
||||
{
|
||||
return $this->cached_method_missing_member_references;
|
||||
return $this->cached_method_param_uses;
|
||||
}
|
||||
|
||||
public function getCachedIssues(): ?array
|
||||
@ -140,6 +156,11 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
$this->cached_method_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodPropertyReferences(array $property_references): void
|
||||
{
|
||||
$this->cached_method_property_references = $property_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_method_missing_member_references = $member_references;
|
||||
@ -150,6 +171,11 @@ class FakeFileReferenceCacheProvider extends \Psalm\Internal\Provider\FileRefere
|
||||
$this->cached_file_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedFilePropertyReferences(array $property_references): void
|
||||
{
|
||||
$this->cached_file_property_references = $property_references;
|
||||
}
|
||||
|
||||
public function setCachedFileMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_file_missing_member_references = $member_references;
|
||||
|
@ -374,18 +374,22 @@ class UnusedCodeTest extends TestCase
|
||||
'<?php
|
||||
|
||||
class C {
|
||||
/** @var int */
|
||||
protected $foo = 1;
|
||||
protected int $foo = 1;
|
||||
public function bar() : void {
|
||||
$this->foo = 5;
|
||||
}
|
||||
|
||||
public function getFoo(): void {
|
||||
echo $this->foo;
|
||||
}
|
||||
}
|
||||
|
||||
class D extends C {
|
||||
protected $foo = 2;
|
||||
protected int $foo = 2;
|
||||
}
|
||||
|
||||
(new D)->bar();',
|
||||
(new D)->bar();
|
||||
(new D)->getFoo();',
|
||||
],
|
||||
'usedClassAfterExtensionLoaded' => [
|
||||
'<?php
|
||||
@ -934,6 +938,49 @@ class UnusedCodeTest extends TestCase
|
||||
|
||||
throw ($exception->getPrevious() ?? $exception);'
|
||||
],
|
||||
'publicPropertyReadInFile' => [
|
||||
'<?php
|
||||
class A {
|
||||
public string $a;
|
||||
|
||||
public function __construct() {
|
||||
$this->a = "hello";
|
||||
}
|
||||
}
|
||||
|
||||
$foo = new A();
|
||||
echo $foo->a;',
|
||||
],
|
||||
'publicPropertyReadInMethod' => [
|
||||
'<?php
|
||||
class A {
|
||||
public string $a = "hello";
|
||||
}
|
||||
|
||||
class B {
|
||||
public function foo(A $a): void {
|
||||
if ($a->a === "goodbye") {}
|
||||
}
|
||||
}
|
||||
|
||||
(new B)->foo(new A());',
|
||||
],
|
||||
'privatePropertyReadInMethod' => [
|
||||
'<?php
|
||||
class A {
|
||||
private string $a;
|
||||
|
||||
public function __construct() {
|
||||
$this->a = "hello";
|
||||
}
|
||||
|
||||
public function emitA(): void {
|
||||
echo $this->a;
|
||||
}
|
||||
}
|
||||
|
||||
(new A())->emitA();',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@ -1296,6 +1343,22 @@ class UnusedCodeTest extends TestCase
|
||||
}',
|
||||
'error_message' => 'UnusedFunctionCall',
|
||||
],
|
||||
'propertyWrittenButNotRead' => [
|
||||
'<?php
|
||||
class A {
|
||||
public string $a = "hello";
|
||||
public string $b = "world";
|
||||
|
||||
public function __construct() {
|
||||
$this->a = "hello";
|
||||
$this->b = "world";
|
||||
}
|
||||
}
|
||||
|
||||
$foo = new A();
|
||||
echo $foo->a;',
|
||||
'error_message' => 'PossiblyUnusedProperty',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user