Skip to content

Commit

Permalink
Make storage immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed Jun 20, 2022
1 parent 80e5914 commit d0c7465
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/Psalm/Codebase.php
Expand Up @@ -508,6 +508,17 @@ public function scanFiles(int $threads = 1): void
}
}

/**
* Consolidates storage, making all Unions immutable.
*
* @return void
*/
public function consolidateStorage(): void {
$this->functions->consolidate();
$this->classlikes->consolidate();
$this->file_storage_provider->consolidate();
}

public function getFileContents(string $file_path): string
{
return $this->file_provider->getContents($file_path);
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Analyzer/ProjectAnalyzer.php
Expand Up @@ -680,6 +680,8 @@ public function check(string $base_dir, bool $is_diff = false): void
$this->config->eventDispatcher->dispatchAfterCodebasePopulated($event);
}

$this->codebase->consolidateStorage();

$this->progress->startAnalyzingFiles();

$this->codebase->analyzer->analyzeFiles(
Expand Down
3 changes: 3 additions & 0 deletions src/Psalm/Internal/Codebase/ClassLikes.php
Expand Up @@ -178,6 +178,9 @@ public function __construct(
$this->collectPredefinedClassLikes();
}

public function consolidate(): void {
$this->classlike_storage_provider->consolidate();
}
private function collectPredefinedClassLikes(): void
{
/** @var array<int, string> */
Expand Down
5 changes: 5 additions & 0 deletions src/Psalm/Internal/Codebase/Functions.php
Expand Up @@ -76,6 +76,11 @@ public function __construct(FileStorageProvider $storage_provider, Reflection $r
self::$stubbed_functions = [];
}

public function consolidate(): void {
foreach (self::$stubbed_functions as $func) {
$func->consolidate();
}
}
/**
* @param non-empty-lowercase-string $function_id
*/
Expand Down
8 changes: 8 additions & 0 deletions src/Psalm/Internal/Provider/ClassLikeStorageProvider.php
Expand Up @@ -36,6 +36,14 @@ public function __construct(?ClassLikeStorageCacheProvider $cache = null)
$this->cache = $cache;
}

public function consolidate(): void {
foreach ($this->getAll() as $class) {
$class->consolidate();
}
foreach ($this->getNew() as $class) {
$class->consolidate();
}
}
/**
* @throws InvalidArgumentException when class does not exist
*/
Expand Down
8 changes: 8 additions & 0 deletions src/Psalm/Internal/Provider/FileStorageProvider.php
Expand Up @@ -39,6 +39,14 @@ public function __construct(?FileStorageCacheProvider $cache = null)
$this->cache = $cache;
}

public function consolidate(): void {
foreach ($this->getAll() as $storage) {
$storage->consolidate();
}
foreach ($this->getNew() as $storage) {
$storage->consolidate();
}
}
public function get(string $file_path): FileStorage
{
$file_path = strtolower($file_path);
Expand Down
6 changes: 6 additions & 0 deletions src/Psalm/Storage/AttributeArg.php
Expand Up @@ -37,4 +37,10 @@ public function __construct(
$this->type = $type;
$this->location = $location;
}

public function consolidate(): void {
if ($this->type instanceof Union) {
$this->type->makeImmutable();
}
}
}
6 changes: 6 additions & 0 deletions src/Psalm/Storage/AttributeStorage.php
Expand Up @@ -44,4 +44,10 @@ public function __construct(
$this->location = $location;
$this->name_location = $name_location;
}

public function consolidate(): void {
foreach ($this->args as $arg) {
$arg->consolidate();
}
}
}
12 changes: 12 additions & 0 deletions src/Psalm/Storage/ClassConstantStorage.php
Expand Up @@ -88,4 +88,16 @@ public function __construct(?Union $type, ?Union $inferred_type, int $visibility
$this->type = $type;
$this->inferred_type = $inferred_type;
}

public function consolidate(): void {
foreach ($this->attributes as $attribute) {
$attribute->consolidate();
}
if ($this->type) {
$this->type->makeImmutable();
}
if ($this->inferred_type) {
$this->inferred_type->makeImmutable();
}
}
}
42 changes: 42 additions & 0 deletions src/Psalm/Storage/ClassLikeStorage.php
Expand Up @@ -470,4 +470,46 @@ public function getAttributeStorages(): array
{
return $this->attributes;
}

public function consolidate(): void {
foreach ($this->constants as $constant) {
$constant->consolidate();
}
foreach ($this->properties as $property) {
$property->consolidate();
}
foreach ($this->methods as $method) {
$method->consolidate();
}
foreach ($this->pseudo_methods as $method) {
$method->consolidate();
}
foreach ($this->attributes as $attribute) {
$attribute->consolidate();
}
if ($this->yield) {
$this->yield->makeImmutable();
}
foreach ($this->pseudo_property_get_types as $union) {
$union->makeImmutable();
}
foreach ($this->pseudo_property_set_types as $union) {
$union->makeImmutable();
}
foreach ($this->template_types ?? [] as $unions) {
foreach ($unions as $union) {
$union->makeImmutable();
}
}
foreach ($this->template_extended_offsets ?? [] as $unions) {
foreach ($unions as $union) {
$union->makeImmutable();
}
}
foreach ($this->template_extended_params ?? [] as $unions) {
foreach ($unions as $union) {
$union->makeImmutable();
}
}
}
}
9 changes: 9 additions & 0 deletions src/Psalm/Storage/FileStorage.php
Expand Up @@ -100,4 +100,13 @@ public function __construct(string $file_path)
{
$this->file_path = $file_path;
}

public function consolidate(): void {
foreach ($this->functions as $function) {
$function->consolidate();
}
foreach ($this->constants as $constant) {
$constant->makeImmutable();
}
}
}
18 changes: 18 additions & 0 deletions src/Psalm/Storage/FunctionLikeParameter.php
Expand Up @@ -158,4 +158,22 @@ public function getAttributeStorages(): array
{
return $this->attributes;
}

public function consolidate(): void {
foreach ($this->attributes as $attribute) {
$attribute->consolidate();
}
if ($this->type) {
$this->type->makeImmutable();
}
if ($this->signature_type) {
$this->signature_type->makeImmutable();
}
if ($this->out_type) {
$this->out_type->makeImmutable();
}
if ($this->default_type instanceof Union) {
$this->default_type->makeImmutable();
}
}
}
25 changes: 25 additions & 0 deletions src/Psalm/Storage/FunctionLikeStorage.php
Expand Up @@ -307,4 +307,29 @@ public function getAttributeStorages(): array
{
return $this->attributes;
}
public function consolidate(): void {
foreach ($this->attributes as $attribute) {
$attribute->consolidate();
}
foreach ($this->params as $param) {
$param->consolidate();
}
if ($this->return_type) {
$this->return_type->makeImmutable();
}
if ($this->signature_return_type) {
$this->signature_return_type->makeImmutable();
}
foreach ($this->defined_constants as $union) {
$union->makeImmutable();
}
foreach ($this->global_types as $union) {
$union->makeImmutable();
}
foreach ($this->template_types ?? [] as $unions) {
foreach ($unions as $union) {
$union->makeImmutable();
}
}
}
}
11 changes: 11 additions & 0 deletions src/Psalm/Storage/MethodStorage.php
Expand Up @@ -104,4 +104,15 @@ final class MethodStorage extends FunctionLikeStorage
* @var bool
*/
public $probably_fluent = false;

public function consolidate(): void
{
parent::consolidate();
if ($this->self_out_type) {
$this->self_out_type->makeImmutable();
}
if ($this->if_this_is_type) {
$this->if_this_is_type->makeImmutable();
}
}
}
14 changes: 14 additions & 0 deletions src/Psalm/Storage/PropertyStorage.php
Expand Up @@ -132,4 +132,18 @@ public function getAttributeStorages(): array
{
return $this->attributes;
}
public function consolidate(): void {
foreach ($this->attributes as $attribute) {
$attribute->consolidate();
}
if ($this->type) {
$this->type->makeImmutable();
}
if ($this->suggested_type) {
$this->suggested_type->makeImmutable();
}
if ($this->signature_type) {
$this->signature_type->makeImmutable();
}
}
}
28 changes: 28 additions & 0 deletions src/Psalm/Type/Union.php
Expand Up @@ -61,6 +61,13 @@ final class Union implements TypeNode
*/
private $types;

/**
* Whether the type is immutable
*
* @var bool
*/
private $immutable = false;

/**
* Whether the type originated in a docblock
*
Expand Down Expand Up @@ -271,11 +278,19 @@ public function __construct(array $types)
$this->from_docblock = $from_docblock;
}

public function makeImmutable(): void
{
$this->immutable = true;
}

/**
* @param non-empty-array<string, Atomic> $types
*/
public function replaceTypes(array $types): void
{
if ($this->immutable) {
throw new \RuntimeException("Cannot replace types in immutable type!");
}
$this->types = $types;
}

Expand All @@ -289,6 +304,9 @@ public function getAtomicTypes(): array

public function addType(Atomic $type): void
{
if ($this->immutable) {
throw new \RuntimeException("Cannot add type to immutable type!");
}
$this->types[$type->getKey()] = $type;

if ($type instanceof TLiteralString) {
Expand Down Expand Up @@ -327,6 +345,7 @@ public function addType(Atomic $type): void

public function __clone()
{
$this->immutable = false;
$this->literal_string_types = [];
$this->literal_int_types = [];
$this->literal_float_types = [];
Expand Down Expand Up @@ -604,6 +623,9 @@ public function canBeFullyExpressedInPhp(int $analysis_php_version_id): bool

public function removeType(string $type_string): bool
{
if ($this->immutable) {
throw new \RuntimeException("Cannot remove type from immutable type!");
}
if (isset($this->types[$type_string])) {
unset($this->types[$type_string]);

Expand Down Expand Up @@ -1026,6 +1048,9 @@ public function isGenerator(): bool

public function substitute(Union $old_type, ?Union $new_type = null): void
{
if ($this->immutable) {
throw new \RuntimeException("Cannot substitute types in immutable type!");
}
if ($this->hasMixed() && !$this->isEmptyMixed()) {
return;
}
Expand Down Expand Up @@ -1423,6 +1448,9 @@ public function setFromDocblock(): void

public function replaceClassLike(string $old, string $new): void
{
if ($this->immutable) {
throw new \RuntimeException("Cannot replace classlikes in immutable type!");
}
foreach ($this->types as $key => $atomic_type) {
$atomic_type->replaceClassLike($old, $new);

Expand Down

0 comments on commit d0c7465

Please sign in to comment.