mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 12:24:49 +01:00
parent
aaa912374f
commit
5da816f160
@ -1219,7 +1219,7 @@ class AssertionFinder
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)->getId();
|
||||
)->getAssertionString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1284,7 +1284,7 @@ class AssertionFinder
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)->getId();
|
||||
)->getAssertionString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3696,7 +3696,7 @@ class AssertionFinder
|
||||
$literal_assertions = [];
|
||||
|
||||
foreach ($array_literal_types as $array_literal_type) {
|
||||
$literal_assertions[] = '=' . $array_literal_type->getId();
|
||||
$literal_assertions[] = '=' . $array_literal_type->getAssertionString();
|
||||
}
|
||||
|
||||
if ($value_type->isFalsable()) {
|
||||
@ -3766,11 +3766,11 @@ class AssertionFinder
|
||||
|
||||
if ($key_type->allStringLiterals() && !$key_type->possibly_undefined) {
|
||||
foreach ($key_type->getLiteralStrings() as $array_literal_type) {
|
||||
$literal_assertions[] = '=' . $array_literal_type->getId();
|
||||
$literal_assertions[] = '=' . $array_literal_type->getAssertionString();
|
||||
}
|
||||
} elseif ($key_type->allIntLiterals() && !$key_type->possibly_undefined) {
|
||||
foreach ($key_type->getLiteralInts() as $array_literal_type) {
|
||||
$literal_assertions[] = '=' . $array_literal_type->getId();
|
||||
$literal_assertions[] = '=' . $array_literal_type->getAssertionString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -557,6 +557,7 @@ class FunctionLikeDocblockScanner
|
||||
|
||||
foreach ($namespaced_type->getAtomicTypes() as $namespaced_type_part) {
|
||||
if ($namespaced_type_part instanceof Type\Atomic\TAssertionFalsy
|
||||
|| $namespaced_type_part instanceof Type\Atomic\TScalarClassConstant
|
||||
|| ($namespaced_type_part instanceof Type\Atomic\TList
|
||||
&& $namespaced_type_part->type_param->isMixed())
|
||||
|| ($namespaced_type_part instanceof Type\Atomic\TArray
|
||||
|
@ -31,7 +31,13 @@ class TIntMask extends TInt
|
||||
|
||||
public function getId(bool $nested = false): string
|
||||
{
|
||||
return $this->getKey();
|
||||
$s = '';
|
||||
|
||||
foreach ($this->values as $value) {
|
||||
$s .= $value->getId() . ', ';
|
||||
}
|
||||
|
||||
return 'int-mask<' . substr($s, 0, -2) . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,11 @@ class TLiteralInt extends TInt
|
||||
}
|
||||
|
||||
public function getId(bool $nested = false): string
|
||||
{
|
||||
return (string) $this->value;
|
||||
}
|
||||
|
||||
public function getAssertionString(bool $exact = false): string
|
||||
{
|
||||
return 'int(' . $this->value . ')';
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class TLiteralString extends TString
|
||||
|
||||
public function getKey(bool $include_extra = true) : string
|
||||
{
|
||||
return $this->getId();
|
||||
return 'string(' . $this->value . ')';
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
@ -32,10 +32,15 @@ class TLiteralString extends TString
|
||||
{
|
||||
$no_newline_value = preg_replace("/\n/m", '\n', $this->value);
|
||||
if (strlen($this->value) > 80) {
|
||||
return 'string(' . substr($no_newline_value, 0, 80) . '...' . ')';
|
||||
return '"' . substr($no_newline_value, 0, 80) . '...' . '"';
|
||||
}
|
||||
|
||||
return 'string(' . $no_newline_value . ')';
|
||||
return '"' . $no_newline_value . '"';
|
||||
}
|
||||
|
||||
public function getAssertionString(bool $exact = false): string
|
||||
{
|
||||
return 'string(' . $this->value . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,12 @@ class TScalarClassConstant extends Scalar
|
||||
|
||||
public function getId(bool $nested = false): string
|
||||
{
|
||||
return $this->getKey();
|
||||
return $this->fq_classlike_name . '::' . $this->const_name;
|
||||
}
|
||||
|
||||
public function getAssertionString(bool $exact = false): string
|
||||
{
|
||||
return 'scalar-class-constant(' . $this->fq_classlike_name . '::' . $this->const_name . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,9 +74,4 @@ class TScalarClassConstant extends Scalar
|
||||
. '::'
|
||||
. $this->const_name;
|
||||
}
|
||||
|
||||
public function getAssertionString(bool $exact = false): string
|
||||
{
|
||||
return 'mixed';
|
||||
}
|
||||
}
|
||||
|
@ -688,7 +688,7 @@ class ArrayFunctionCallTest extends TestCase
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);',
|
||||
'assertions' => [
|
||||
'$foo' => 'array<string, pure-Closure():string(baz)>',
|
||||
'$foo' => 'array<string, pure-Closure():"baz">',
|
||||
],
|
||||
],
|
||||
'ignoreFalsableCurrent' => [
|
||||
|
@ -1244,7 +1244,7 @@ class AssertAnnotationTest extends TestCase
|
||||
'convertConstStringType' => [
|
||||
'<?php
|
||||
class A {
|
||||
const T1 = 1;
|
||||
const T1 = 1;
|
||||
const T2 = 2;
|
||||
|
||||
/**
|
||||
@ -1260,7 +1260,6 @@ class AssertAnnotationTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function takesA(int $a) : void {
|
||||
if (A::isValid($a)) {
|
||||
A::bar($a);
|
||||
|
@ -340,7 +340,7 @@ class ClosureTest extends TestCase
|
||||
$a = function() : Closure { return function() : string { return "hello"; }; };
|
||||
$b = $a()();',
|
||||
'assertions' => [
|
||||
'$a' => 'pure-Closure():pure-Closure():string(hello)',
|
||||
'$a' => 'pure-Closure():pure-Closure():"hello"',
|
||||
'$b' => 'string',
|
||||
],
|
||||
],
|
||||
|
@ -98,7 +98,7 @@ class JsonOutputTest extends TestCase
|
||||
function fooFoo() {
|
||||
return "hello";
|
||||
}',
|
||||
'message' => 'Method fooFoo does not have a return type, expecting string(hello)',
|
||||
'message' => 'Method fooFoo does not have a return type, expecting "hello"',
|
||||
'line' => 2,
|
||||
'error' => 'fooFoo',
|
||||
],
|
||||
@ -110,7 +110,7 @@ class JsonOutputTest extends TestCase
|
||||
function fooFoo() {
|
||||
return "hello";
|
||||
}',
|
||||
'message' => "The inferred type 'string(hello)' does not match the declared return type 'int' for fooFoo",
|
||||
'message' => "The inferred type '\"hello\"' does not match the declared return type 'int' for fooFoo",
|
||||
'line' => 6,
|
||||
'error' => '"hello"',
|
||||
],
|
||||
|
@ -216,13 +216,13 @@ class SymbolLookupTest extends \Psalm\Tests\TestCase
|
||||
|
||||
$this->assertNotNull($symbol_at_position);
|
||||
|
||||
$this->assertSame('213-214:int(1)', $symbol_at_position[0]);
|
||||
$this->assertSame('213-214:1', $symbol_at_position[0]);
|
||||
|
||||
$symbol_at_position = $codebase->getReferenceAtPosition('somefile.php', new Position(17, 30));
|
||||
|
||||
$this->assertNotNull($symbol_at_position);
|
||||
|
||||
$this->assertSame('425-426:int(2)', $symbol_at_position[0]);
|
||||
$this->assertSame('425-426:2', $symbol_at_position[0]);
|
||||
}
|
||||
|
||||
public function testGetSymbolPositionMissingArg(): void
|
||||
|
@ -59,8 +59,8 @@ class Php56Test extends TestCase
|
||||
$bitxor = C::BITXOR;',
|
||||
'assertions' => [
|
||||
'$c1' => 'int',
|
||||
'$c2===' => 'int(2)',
|
||||
'$c3===' => 'int(3)',
|
||||
'$c2===' => '2',
|
||||
'$c3===' => '3',
|
||||
'$c1_3rd' => 'float|int',
|
||||
'$c_sentence' => 'string',
|
||||
'$cf' => 'int',
|
||||
|
@ -1288,7 +1288,7 @@ class ReturnTypeTest extends TestCase
|
||||
return 1;
|
||||
};
|
||||
}',
|
||||
'error_message' => 'InvalidReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:9:28 - The inferred type \'pure-Closure(iterable<int, T:fn-map as mixed>):int(1)\' does not match the declared return type \'callable(iterable<int, T:fn-map as mixed>):iterable<int, U:fn-map as mixed>\' for map',
|
||||
'error_message' => 'InvalidReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:9:28 - The inferred type \'pure-Closure(iterable<int, T:fn-map as mixed>):1\' does not match the declared return type \'callable(iterable<int, T:fn-map as mixed>):iterable<int, U:fn-map as mixed>\' for map',
|
||||
],
|
||||
'cannotInferReturnClosureWithDifferentTypes' => [
|
||||
'<?php
|
||||
|
@ -1045,7 +1045,7 @@ class ClassTemplateTest extends TestCase
|
||||
|
||||
$c = new C();',
|
||||
'assertions' => [
|
||||
'$c===' => 'C<string(hello)>',
|
||||
'$c===' => 'C<"hello">',
|
||||
],
|
||||
],
|
||||
'SKIPPED-templateDefaultConstant' => [
|
||||
@ -3601,7 +3601,7 @@ class ClassTemplateTest extends TestCase
|
||||
$mario = new CharacterRow(["id" => 5, "name" => "Mario", "height" => 3.5]);
|
||||
|
||||
$mario->ame = "Luigi";',
|
||||
'error_message' => 'InvalidArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:47:29 - Argument 1 of CharacterRow::__set expects string(height)|string(id)|string(name), string(ame) provided',
|
||||
'error_message' => 'InvalidArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:47:29 - Argument 1 of CharacterRow::__set expects "height"|"id"|"name", "ame" provided',
|
||||
],
|
||||
'specialiseTypeBeforeReturning' => [
|
||||
'<?php
|
||||
|
@ -339,28 +339,28 @@ class TypeCombinationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'combineObjectTypeWithIntKeyedArray' => [
|
||||
'array<int|string(a), int|string>',
|
||||
'array<"a"|int, int|string>',
|
||||
[
|
||||
'array{a: int}',
|
||||
'array<int, string>',
|
||||
],
|
||||
],
|
||||
'combineNestedObjectTypeWithTKeyedArrayIntKeyedArray' => [
|
||||
'array{a: array<int|string(a), int|string>}',
|
||||
'array{a: array<"a"|int, int|string>}',
|
||||
[
|
||||
'array{a: array{a: int}}',
|
||||
'array{a: array<int, string>}',
|
||||
],
|
||||
],
|
||||
'combineIntKeyedObjectTypeWithNestedIntKeyedArray' => [
|
||||
'array<int, array<int|string(a), int|string>>',
|
||||
'array<int, array<"a"|int, int|string>>',
|
||||
[
|
||||
'array<int, array{a:int}>',
|
||||
'array<int, array<int, string>>',
|
||||
],
|
||||
],
|
||||
'combineNestedObjectTypeWithNestedIntKeyedArray' => [
|
||||
'array<int|string(a), array<int|string(a), int|string>>',
|
||||
'array<"a"|int, array<"a"|int, int|string>>',
|
||||
[
|
||||
'array{a: array{a: int}}',
|
||||
'array<int, array<int, string>>',
|
||||
@ -431,7 +431,7 @@ class TypeCombinationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'objectLikePlusArrayEqualsArray' => [
|
||||
'array<string(a)|string(b)|string(c), int(1)|int(2)|int(3)>',
|
||||
'array<"a"|"b"|"c", 1|2|3>',
|
||||
[
|
||||
'array<"a"|"b"|"c", 1|2|3>',
|
||||
'array{a: 1|2, b: 2|3, c: 1|3}',
|
||||
@ -571,14 +571,14 @@ class TypeCombinationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'combineZeroAndPositiveInt' => [
|
||||
'int(0)|positive-int',
|
||||
'0|positive-int',
|
||||
[
|
||||
'0',
|
||||
'positive-int',
|
||||
],
|
||||
],
|
||||
'combinePositiveIntAndZero' => [
|
||||
'int(0)|positive-int',
|
||||
'0|positive-int',
|
||||
[
|
||||
'positive-int',
|
||||
'0',
|
||||
@ -615,7 +615,7 @@ class TypeCombinationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'combineZeroOneAndPositiveInt' => [
|
||||
'int(0)|positive-int',
|
||||
'0|positive-int',
|
||||
[
|
||||
'0',
|
||||
'1',
|
||||
@ -623,7 +623,7 @@ class TypeCombinationTest extends TestCase
|
||||
],
|
||||
],
|
||||
'combinePositiveIntOneAndZero' => [
|
||||
'int(0)|positive-int',
|
||||
'0|positive-int',
|
||||
[
|
||||
'positive-int',
|
||||
'1',
|
||||
|
@ -717,7 +717,7 @@ class TypeParseTest extends TestCase
|
||||
public function testCombineLiteralStringWithClassString(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
'class-string|string(array)',
|
||||
'"array"|class-string',
|
||||
Type::parseString('"array"|class-string')->getId()
|
||||
);
|
||||
}
|
||||
@ -902,26 +902,26 @@ class TypeParseTest extends TestCase
|
||||
{
|
||||
$docblock_type = Type::parseString('int-mask<0, 1, 2, 4>');
|
||||
|
||||
$this->assertSame('int(0)|int(1)|int(2)|int(3)|int(4)|int(5)|int(6)|int(7)', $docblock_type->getId());
|
||||
$this->assertSame('0|1|2|3|4|5|6|7', $docblock_type->getId());
|
||||
|
||||
$docblock_type = Type::parseString('int-mask<1, 2, 4>');
|
||||
|
||||
$this->assertSame('int(1)|int(2)|int(3)|int(4)|int(5)|int(6)|int(7)', $docblock_type->getId());
|
||||
$this->assertSame('1|2|3|4|5|6|7', $docblock_type->getId());
|
||||
|
||||
$docblock_type = Type::parseString('int-mask<1, 4>');
|
||||
|
||||
$this->assertSame('int(1)|int(4)|int(5)', $docblock_type->getId());
|
||||
$this->assertSame('1|4|5', $docblock_type->getId());
|
||||
|
||||
$docblock_type = Type::parseString('int-mask<PREG_PATTERN_ORDER, PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL>');
|
||||
|
||||
$this->assertSame('int(1)|int(256)|int(257)|int(512)|int(513)|int(768)|int(769)', $docblock_type->getId());
|
||||
$this->assertSame('1|256|257|512|513|768|769', $docblock_type->getId());
|
||||
}
|
||||
|
||||
public function testIntMaskWithClassConstant(): void
|
||||
{
|
||||
$docblock_type = Type::parseString('int-mask<0, A::FOO, A::BAR>');
|
||||
|
||||
$this->assertSame('int-mask<int(0), scalar-class-constant(A::FOO), scalar-class-constant(A::BAR)>', $docblock_type->getId());
|
||||
$this->assertSame('int-mask<0, A::FOO, A::BAR>', $docblock_type->getId());
|
||||
}
|
||||
|
||||
public function testIntMaskWithInvalidClassConstant(): void
|
||||
|
@ -101,7 +101,7 @@ class ReconcilerTest extends \Psalm\Tests\TestCase
|
||||
'falsyWithMyObjectPipeBool' => ['false', 'falsy', 'MyObject|bool'],
|
||||
'falsyWithMixed' => ['empty-mixed', 'falsy', 'mixed'],
|
||||
'falsyWithBool' => ['false', 'falsy', 'bool'],
|
||||
'falsyWithStringOrNull' => ['null|string()|string(0)', 'falsy', 'string|null'],
|
||||
'falsyWithStringOrNull' => ['""|"0"|null', 'falsy', 'string|null'],
|
||||
'falsyWithScalarOrNull' => ['empty-scalar', 'falsy', 'scalar'],
|
||||
|
||||
'notMyObjectWithMyObjectPipeBool' => ['bool', '!MyObject', 'MyObject|bool'],
|
||||
|
Loading…
Reference in New Issue
Block a user