1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

remove support for allowPhpstormGenerics

This commit is contained in:
orklah 2021-10-20 20:41:22 +02:00 committed by Bruce Weirdan
parent 0f2ae281ae
commit 4f7c1d05c1
No known key found for this signature in database
GPG Key ID: CFC3AAB181751B0D
6 changed files with 1 additions and 289 deletions

View File

@ -51,14 +51,6 @@
</xs:attribute> </xs:attribute>
<xs:attribute name="allowFileIncludes" type="xs:boolean" default="true" /> <xs:attribute name="allowFileIncludes" type="xs:boolean" default="true" />
<xs:attribute name="allowPhpStormGenerics" type="xs:boolean" default="false">
<xs:annotation>
<!-- note: for PHPStorm to mark the attribute as deprecated the doc entry has to be *single line* and start with the word `deprecated` -->
<xs:documentation xml:lang="en">
Deprecated. PHPStorm now supports generics for the most part and @psalm- annotations can be used
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="allowStringToStandInForClass" type="xs:boolean" default="false" /> <xs:attribute name="allowStringToStandInForClass" type="xs:boolean" default="false" />
<xs:attribute name="checkForThrowsDocblock" type="xs:boolean" default="false" /> <xs:attribute name="checkForThrowsDocblock" type="xs:boolean" default="false" />
<xs:attribute name="checkForThrowsInGlobalScope" type="xs:boolean" default="false" /> <xs:attribute name="checkForThrowsInGlobalScope" type="xs:boolean" default="false" />

View File

@ -134,17 +134,6 @@ If true we force strict typing on numerical and string operations (see https://g
``` ```
Setting this to `false` means that any function calls will cause Psalm to forget anything it knew about object properties within the scope of the function it's currently analysing. This duplicates functionality that Hack has. Defaults to `true`. Setting this to `false` means that any function calls will cause Psalm to forget anything it knew about object properties within the scope of the function it's currently analysing. This duplicates functionality that Hack has. Defaults to `true`.
#### allowPhpStormGenerics
```xml
<psalm
allowPhpStormGenerics="[bool]"
>
```
Allows you to specify whether or not to use the typed iterator docblock format supported by PHP Storm e.g. `ArrayIterator|string[]`, which Psalm transforms to `ArrayIterator<string>`. Defaults to `false`.
This flag is deprecated and will be removed in Psalm 5
#### allowStringToStandInForClass #### allowStringToStandInForClass
```xml ```xml

View File

@ -315,11 +315,6 @@ class Config
/** @var bool */ /** @var bool */
public $use_igbinary = false; public $use_igbinary = false;
/**
* @var bool
*/
public $allow_phpstorm_generics = false;
/** /**
* @var bool * @var bool
*/ */
@ -887,7 +882,6 @@ class Config
'allowFileIncludes' => 'allow_includes', 'allowFileIncludes' => 'allow_includes',
'strictBinaryOperands' => 'strict_binary_operands', 'strictBinaryOperands' => 'strict_binary_operands',
'rememberPropertyAssignmentsAfterCall' => 'remember_property_assignments_after_call', 'rememberPropertyAssignmentsAfterCall' => 'remember_property_assignments_after_call',
'allowPhpStormGenerics' => 'allow_phpstorm_generics',
'allowStringToStandInForClass' => 'allow_string_standin_for_class', 'allowStringToStandInForClass' => 'allow_string_standin_for_class',
'usePhpDocMethodsWithoutMagicCall' => 'use_phpdoc_method_without_magic_or_parent', 'usePhpDocMethodsWithoutMagicCall' => 'use_phpdoc_method_without_magic_or_parent',
'usePhpDocPropertiesWithoutMagicCall' => 'use_phpdoc_property_without_magic_or_parent', 'usePhpDocPropertiesWithoutMagicCall' => 'use_phpdoc_property_without_magic_or_parent',

View File

@ -14,11 +14,6 @@ use Psalm\IssueBuffer;
use Psalm\Progress\Progress; use Psalm\Progress\Progress;
use Psalm\Storage\ClassLikeStorage; use Psalm\Storage\ClassLikeStorage;
use Psalm\Storage\FileStorage; use Psalm\Storage\FileStorage;
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TGenericObject;
use Psalm\Type\Atomic\TIterable;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TTemplateParam; use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Union; use Psalm\Type\Union;
@ -110,26 +105,6 @@ class Populator
} }
foreach ($this->classlike_storage_provider->getNew() as $class_storage) { foreach ($this->classlike_storage_provider->getNew() as $class_storage) {
if ($this->config->allow_phpstorm_generics) {
foreach ($class_storage->properties as $property_storage) {
if ($property_storage->type) {
$this->convertPhpStormGenericToPsalmGeneric($property_storage->type, true);
}
}
foreach ($class_storage->methods as $method_storage) {
if ($method_storage->return_type) {
$this->convertPhpStormGenericToPsalmGeneric($method_storage->return_type);
}
foreach ($method_storage->params as $param_storage) {
if ($param_storage->type) {
$this->convertPhpStormGenericToPsalmGeneric($param_storage->type);
}
}
}
}
foreach ($class_storage->dependent_classlikes as $dependent_classlike_lc => $_) { foreach ($class_storage->dependent_classlikes as $dependent_classlike_lc => $_) {
try { try {
$dependee_storage = $this->classlike_storage_provider->get($dependent_classlike_lc); $dependee_storage = $this->classlike_storage_provider->get($dependent_classlike_lc);
@ -141,22 +116,6 @@ class Populator
} }
} }
if ($this->config->allow_phpstorm_generics) {
foreach ($all_file_storage as $file_storage) {
foreach ($file_storage->functions as $function_storage) {
if ($function_storage->return_type) {
$this->convertPhpStormGenericToPsalmGeneric($function_storage->return_type);
}
foreach ($function_storage->params as $param_storage) {
if ($param_storage->type) {
$this->convertPhpStormGenericToPsalmGeneric($param_storage->type);
}
}
}
}
}
$this->progress->debug('FileStorage is populated' . "\n"); $this->progress->debug('FileStorage is populated' . "\n");
ClassLikeStorageProvider::populated(); ClassLikeStorageProvider::populated();
@ -991,65 +950,6 @@ class Populator
$storage->populated = true; $storage->populated = true;
} }
private function convertPhpStormGenericToPsalmGeneric(Union $candidate, bool $is_property = false): void
{
if (!$candidate->from_docblock) {
//never convert a type that comes from a signature
return;
}
$atomic_types = $candidate->getAtomicTypes();
if (isset($atomic_types['array']) && count($atomic_types) > 1 && !isset($atomic_types['null'])) {
$iterator_name = null;
$generic_params = null;
$iterator_key = null;
try {
foreach ($atomic_types as $type_key => $type) {
if ($type instanceof TIterable
|| ($type instanceof TNamedObject
&& (!$type->from_docblock || $is_property)
&& (
strtolower($type->value) === 'traversable'
|| $this->classlikes->interfaceExtends(
$type->value,
'Traversable'
)
|| $this->classlikes->classImplements(
$type->value,
'Traversable'
)
))
) {
$iterator_name = $type->value;
$iterator_key = $type_key;
} elseif ($type instanceof TArray) {
$generic_params = $type->type_params;
}
}
} catch (InvalidArgumentException $e) {
// ignore class-not-found issues
}
if ($iterator_name && $iterator_key && $generic_params) {
if ($iterator_name === 'iterable') {
$generic_iterator = new TIterable($generic_params);
} else {
if (strtolower($iterator_name) === 'generator') {
$generic_params[] = Type::getMixed();
$generic_params[] = Type::getMixed();
}
$generic_iterator = new TGenericObject($iterator_name, $generic_params);
}
$candidate->removeType('array');
$candidate->removeType($iterator_key);
$candidate->addType($generic_iterator);
}
}
}
protected function inheritMethodsFromParent( protected function inheritMethodsFromParent(
ClassLikeStorage $storage, ClassLikeStorage $storage,
ClassLikeStorage $parent_storage ClassLikeStorage $parent_storage

View File

@ -180,8 +180,7 @@ class TypeCombiner
&& (isset($combination->named_object_types['Traversable']) && (isset($combination->named_object_types['Traversable'])
|| isset($combination->builtin_type_params['Traversable'])) || isset($combination->builtin_type_params['Traversable']))
&& ( && (
($codebase && $codebase->config->allow_phpstorm_generics) isset($combination->builtin_type_params['Traversable'])
|| isset($combination->builtin_type_params['Traversable'])
|| (isset($combination->named_object_types['Traversable']) || (isset($combination->named_object_types['Traversable'])
&& $combination->named_object_types['Traversable']->from_docblock) && $combination->named_object_types['Traversable']->from_docblock)
) )

View File

@ -22,149 +22,6 @@ class AnnotationTest extends TestCase
$codebase->reportUnusedVariables(); $codebase->reportUnusedVariables();
} }
public function testPhpStormGenericsWithValidArrayIteratorArgument(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
function takesString(string $_s): void {}
/** @param ArrayIterator|string[] $i */
function takesArrayIteratorOfString(ArrayIterator $i): void {
$s = $i->offsetGet("a");
takesString($s);
foreach ($i as $s2) {
takesString($s2);
}
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsWithTypeInSignature(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
function a(array|\ArrayObject $_meta = []): void {}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsWithValidTraversableArgument(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
function takesString(string $_s): void {}
/** @param Traversable|string[] $i */
function takesTraversableOfString(Traversable $i): void {
foreach ($i as $s2) {
takesString($s2);
}
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsWithClassProperty(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
/** @psalm-suppress MissingConstructor */
class Foo {
/** @var \stdClass[]|\ArrayObject */
public $bar;
/**
* @return \stdClass[]|\ArrayObject
*/
public function getBar(): \ArrayObject {
return $this->bar;
}
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsWithGeneratorArray(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
class A {
/**
* @return stdClass[]|Generator
*/
function getCollection(): Generator
{
yield new stdClass;
}
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsWithValidIterableArgument(): void
{
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
function takesString(string $_s): void {}
/** @param iterable|string[] $i */
function takesArrayIteratorOfString(iterable $i): void {
foreach ($i as $s2) {
takesString($s2);
}
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testPhpStormGenericsInvalidArgument(): void
{
$this->expectException(CodeException::class);
$this->expectExceptionMessage('InvalidScalarArgument');
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
function takesInt(int $_s): void {}
/** @param ArrayIterator|string[] $i */
function takesArrayIteratorOfString(ArrayIterator $i): void {
$s = $i->offsetGet("a");
takesInt($s);
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testLessSpecificImplementedReturnTypeWithDocblockOnMultipleLines(): void public function testLessSpecificImplementedReturnTypeWithDocblockOnMultipleLines(): void
{ {
$this->expectException(CodeException::class); $this->expectException(CodeException::class);
@ -236,25 +93,6 @@ class AnnotationTest extends TestCase
$this->analyzeFile('somefile.php', new Context()); $this->analyzeFile('somefile.php', new Context());
} }
public function testPhpStormGenericsNoTypehint(): void
{
$this->expectException(CodeException::class);
$this->expectExceptionMessage('PossiblyInvalidMethodCall');
Config::getInstance()->allow_phpstorm_generics = true;
$this->addFile(
'somefile.php',
'<?php
/** @param ArrayIterator|string[] $i */
function takesArrayIteratorOfString($i): void {
$s = $i->offsetGet("a");
}'
);
$this->analyzeFile('somefile.php', new Context());
}
public function testInvalidParamDefault(): void public function testInvalidParamDefault(): void
{ {
$this->expectException(CodeException::class); $this->expectException(CodeException::class);