Skip to content

Commit

Permalink
Merge pull request #14 from kynx/max-string-length
Browse files Browse the repository at this point in the history
Creating `LiteralString`s  respects `max-string-length` (thanks Rector 😄  )
  • Loading branch information
kynx authored Feb 17, 2024
2 parents a4bfeb9 + cf97a47 commit 5366199
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 103 deletions.
7 changes: 1 addition & 6 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,6 @@
<code><![CDATA[addNotEmptyProvider]]></code>
</PossiblyUnusedMethod>
</file>
<file src="test/Psalm/ConfigLoaderTrait.php">
<PossiblyUnusedMethod>
<code><![CDATA[reloadConfig]]></code>
</PossiblyUnusedMethod>
</file>
<file src="test/Psalm/TypeComparatorTest.php">
<PossiblyUnusedMethod>
<code><![CDATA[isContainedByFalseProvider]]></code>
Expand All @@ -112,7 +107,7 @@
<code><![CDATA[filterProvider]]></code>
<code><![CDATA[narrowProvider]]></code>
<code><![CDATA[replaceTypeProvider]]></code>
<code><![CDATA[toLaxUnion]]></code>
<code><![CDATA[toLooseUnionProvider]]></code>
<code><![CDATA[toStrictUnionProvider]]></code>
<code><![CDATA[widenProvider]]></code>
</PossiblyUnusedMethod>
Expand Down
9 changes: 4 additions & 5 deletions src/Filter/BooleanVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Union;

Expand All @@ -32,8 +31,8 @@ public function visit(FilterInterface $filter, Union $previous): Union
$remove = [];

if ($type & Boolean::TYPE_FALSE_STRING) {
$remove[] = TLiteralString::make('false');
$remove[] = TLiteralString::make('true');
$remove[] = TypeUtil::getAtomicStringFromLiteral('false');
$remove[] = TypeUtil::getAtomicStringFromLiteral('true');
}

if ($type & Boolean::TYPE_NULL) {
Expand All @@ -45,8 +44,8 @@ public function visit(FilterInterface $filter, Union $previous): Union
}

if ($type & Boolean::TYPE_ZERO_STRING) {
$remove[] = TLiteralString::make('0');
$remove[] = TLiteralString::make('1');
$remove[] = TypeUtil::getAtomicStringFromLiteral('0');
$remove[] = TypeUtil::getAtomicStringFromLiteral('1');
}

if ($type & Boolean::TYPE_FLOAT) {
Expand Down
31 changes: 25 additions & 6 deletions src/Filter/ToNullVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNonEmptyArray;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNull;
Expand All @@ -39,15 +38,27 @@ public function visit(FilterInterface $filter, Union $previous): Union
$visited = $previous;

if ($type & ToNull::TYPE_FLOAT) {
$visited = TypeUtil::replaceType($visited, new TLiteralFloat(0.0), new Union([new TFloat()]));
$visited = TypeUtil::replaceType(
$visited,
new TLiteralFloat(0.0),
new Union([new TFloat()])
);
}

if ($type & ToNull::TYPE_ZERO_STRING) {
$visited = TypeUtil::replaceType($visited, TLiteralString::make('0'), new Union([new TString()]));
$visited = TypeUtil::replaceType(
$visited,
TypeUtil::getAtomicStringFromLiteral('0'),
new Union([new TString()])
);
}

if ($type & ToNull::TYPE_STRING) {
$visited = TypeUtil::replaceType($visited, new TString(), new Union([new TNonEmptyString()]));
$visited = TypeUtil::replaceType(
$visited,
new TString(),
new Union([new TNonEmptyString()])
);
}

if ($type & ToNull::TYPE_EMPTY_ARRAY) {
Expand All @@ -59,11 +70,19 @@ public function visit(FilterInterface $filter, Union $previous): Union
}

if ($type & ToNull::TYPE_INTEGER) {
$visited = TypeUtil::replaceType($visited, new TLiteralInt(0), new Union([new TInt()]));
$visited = TypeUtil::replaceType(
$visited,
new TLiteralInt(0),
new Union([new TInt()])
);
}

if ($type & ToNull::TYPE_BOOLEAN) {
$visited = TypeUtil::replaceType($visited, new TBool(), new Union([new TTrue()]));
$visited = TypeUtil::replaceType(
$visited,
new TBool(),
new Union([new TTrue()])
);
}

return $visited === $previous ? $previous : TypeUtil::widen($visited, new Union([new TNull()]));
Expand Down
19 changes: 10 additions & 9 deletions src/Psalm/ConfigLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,35 @@

final class ConfigLoader
{
public const DEFAULT_STRING_LENGTH = 1000;

private static bool $loaded = false;

public static function load(?int $maxStringLength = null): void
{
if (self::$loaded) {
return;
}
$config = Config::getInstance();
} else {
self::hackPsalmCli();
self::setPsalmVersion();

self::hackPsalmCli();
self::setPsalmVersion();
$config = Config::getConfigForPath(__DIR__, getcwd());
self::$loaded = true;
}

$config = Config::getConfigForPath(__DIR__, getcwd());
if ($maxStringLength !== null) {
$config->max_string_length = $maxStringLength;
}

self::$loaded = true;
}

/**
* Prevent Psalm's `CliUtils::getRawCliArguments()` from trying to parse script arguments
*/
private static function hackPsalmCli(): void
{
// phpcs:disable Squiz.PHP.GlobalKeyword.NotAllowed
// phpcs:ignore Squiz.PHP.GlobalKeyword.NotAllowed
global $argv;
$argv = [];
// phpcs:enable
}

private static function setPsalmVersion(): void
Expand Down
31 changes: 26 additions & 5 deletions src/Psalm/TypeUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Kynx\Laminas\FormShape\Psalm;

use Psalm\Config;
use Psalm\Type;
use Psalm\Type\Atomic;
use Psalm\Type\Atomic\TArray;
Expand All @@ -19,6 +20,7 @@
use Psalm\Type\Atomic\TMixed;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNonFalsyString;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TNumeric;
use Psalm\Type\Atomic\TResource;
Expand All @@ -41,6 +43,7 @@
use function is_resource;
use function is_string;
use function str_contains;
use function strlen;

final readonly class TypeUtil
{
Expand Down Expand Up @@ -157,7 +160,7 @@ public static function toStrictUnion(mixed $value): Union
is_float($value) => new Union([new TLiteralFloat($value)]),
is_int($value) => new Union([new TLiteralInt($value)]),
is_object($value) => new Union([new TNamedObject($value::class)]),
is_string($value) => new Union([TLiteralString::make($value)]),
is_string($value) => new Union([self::getAtomicStringFromLiteral($value)]),
is_resource($value) => new Union([new TResource()]),
$value === null => new Union([new TNull()]),
default => new Union([new TMixed()]),
Expand Down Expand Up @@ -189,6 +192,24 @@ public static function getEmptyUnion(): Union
return $builder->freeze();
}

/**
* Safely return a string atomic
*
* @see Type::getAtomicStringFromLiteral() - does the same but without involving (internal) ProjectAnalyzer
*/
public static function getAtomicStringFromLiteral(string $value, bool $fromDocblock = false): TString
{
$config = Config::getInstance();

if ($value === '' || strlen($value) < $config->max_string_length) {
return TLiteralString::make($value, $fromDocblock);
} elseif ($value === '0') {
return new TNonEmptyString($fromDocblock);
}

return new TNonFalsyString($fromDocblock);
}

/**
* @param array<string, Atomic> $narrowest
*/
Expand Down Expand Up @@ -280,7 +301,7 @@ private static function toLooseBool(bool $value): Union

return Type::combineUnionTypes(self::toStrictUnion($value), new Union([
new TEmptyNumeric(),
TLiteralString::make(""),
self::getAtomicStringFromLiteral(""),
new TNull(),
]));
}
Expand All @@ -293,7 +314,7 @@ private static function toLooseFloat(float $value): Union

$types = [
new TLiteralFloat($value),
TLiteralString::make("$value"),
self::getAtomicStringFromLiteral("$value"),
];
if ((string) $value === (int) $value . "") {
$types[] = new TLiteralInt((int) $value);
Expand All @@ -311,7 +332,7 @@ private static function toLooseInt(int $value): Union
return new Union([
new TLiteralInt($value),
// new TLiteralFloat($value), // this would output 'float'
TLiteralString::make("$value"),
self::getAtomicStringFromLiteral("$value"),
]);
}

Expand All @@ -322,7 +343,7 @@ private static function toLooseString(string $value): Union
}

$types = [
TLiteralString::make($value),
self::getAtomicStringFromLiteral($value),
];
if ($value === (int) $value . "") {
$types[] = new TLiteralInt((int) $value);
Expand Down
5 changes: 2 additions & 3 deletions src/Validator/NotEmptyVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Psalm\Type\Atomic\TIntRange;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TNonEmptyArray;
use Psalm\Type\Atomic\TNonEmptyString;
Expand Down Expand Up @@ -54,7 +53,7 @@ public function visit(ValidatorInterface $validator, Union $previous): Union
$remove[] = new TObject();
}
if ($type & NotEmpty::SPACE) {
$remove[] = TLiteralString::make(' ');
$remove[] = TypeUtil::getAtomicStringFromLiteral(' ');
}
if ($type & NotEmpty::NULL) {
$remove[] = new TNull();
Expand All @@ -63,7 +62,7 @@ public function visit(ValidatorInterface $validator, Union $previous): Union
$narrow[] = new TNonEmptyArray([Type::getArrayKey(), Type::getMixed()]);
}
if ($type & NotEmpty::ZERO) {
$remove[] = TLiteralString::make('0');
$remove[] = TypeUtil::getAtomicStringFromLiteral('0');
}
if ($type & NotEmpty::STRING) {
$narrow[] = new TNonEmptyString();
Expand Down
11 changes: 5 additions & 6 deletions test/Decorator/PrettyPrinterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
use Psalm\Type\Atomic\TKeyedArray;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNull;
Expand Down Expand Up @@ -127,8 +126,8 @@ public function testDecorateSortsTypes(): void
new TNull(),
new TLiteralFloat(1.23),
new TLiteralInt(1),
TLiteralString::make('b'),
TLiteralString::make('1'),
TypeUtil::getAtomicStringFromLiteral('b'),
TypeUtil::getAtomicStringFromLiteral('1'),
]);

$actual = $this->decorator->decorate($union);
Expand Down Expand Up @@ -184,8 +183,8 @@ public static function combineTypesProvider(): array
'int, int range' => [[new TInt(), new TIntRange(1, null)], 'int'],
'literal float, float' => [[new TLiteralFloat(1.23), new TFloat()], 'float'],
'float, literal float' => [[new TFloat(), new TLiteralFloat(1.23)], 'float'],
'literal string, string' => [[TLiteralString::make('foo'), new TString()], 'string'],
'string, literal string' => [[new TString(), TLiteralString::make('foo')], 'string'],
'literal string, string' => [[TypeUtil::getAtomicStringFromLiteral('foo'), new TString()], 'string'],
'string, literal string' => [[new TString(), TypeUtil::getAtomicStringFromLiteral('foo')], 'string'],
'numeric-string, string' => [[new TNumericString(), new TString()], 'string'],
'string, numeric-string' => [[new TString(), new TNumericString()], 'string'],

Expand All @@ -200,7 +199,7 @@ public function testDecorateLimitsLiterals(): void
{
$expected = 'string';
$types = array_map(
static fn (int $i): TLiteralString => TLiteralString::make((string) $i),
static fn (int $i): TString => TypeUtil::getAtomicStringFromLiteral((string) $i),
range(1, 4)
);
$union = new Union($types);
Expand Down
4 changes: 2 additions & 2 deletions test/Filter/AllowListVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

use Kynx\Laminas\FormShape\Filter\AllowListVisitor;
use Kynx\Laminas\FormShape\Psalm\ConfigLoader;
use Kynx\Laminas\FormShape\Psalm\TypeUtil;
use Laminas\Filter\AllowList;
use Laminas\Filter\Boolean;
use PHPUnit\Framework\Attributes\CoversClass;
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TNumericString;
Expand Down Expand Up @@ -46,7 +46,7 @@ public static function visitProvider(): array
'lax list' => [
new AllowList(['list' => [123], 'strict' => false]),
[new TString()],
[TLiteralString::make('123'), new TNull()],
[TypeUtil::getAtomicStringFromLiteral('123'), new TNull()],
],
'strict narrows previous' => [
new AllowList(['list' => ['foo', 123], 'strict' => true]),
Expand Down
6 changes: 3 additions & 3 deletions test/Filter/BooleanVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Kynx\Laminas\FormShape\Filter\BooleanVisitor;
use Kynx\Laminas\FormShape\Psalm\ConfigLoader;
use Kynx\Laminas\FormShape\Psalm\TypeUtil;
use Laminas\Filter\AllowList;
use Laminas\Filter\Boolean;
use PHPUnit\Framework\Attributes\CoversClass;
Expand All @@ -14,7 +15,6 @@
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TString;

Expand All @@ -38,7 +38,7 @@ public static function visitProvider(): array
],
'false string' => [
new Boolean(['casting' => false, 'type' => Boolean::TYPE_FALSE_STRING]),
[TLiteralString::make('false'), TLiteralString::make('true')],
[TypeUtil::getAtomicStringFromLiteral('false'), TypeUtil::getAtomicStringFromLiteral('true')],
[new TBool()],
],
'null' => [
Expand All @@ -53,7 +53,7 @@ public static function visitProvider(): array
],
'zero string' => [
new Boolean(['casting' => false, 'type' => Boolean::TYPE_ZERO_STRING]),
[TLiteralString::make('0'), TLiteralString::make('1')],
[TypeUtil::getAtomicStringFromLiteral('0'), TypeUtil::getAtomicStringFromLiteral('1')],
[new TBool()],
],
'float' => [
Expand Down
4 changes: 2 additions & 2 deletions test/Filter/ToNullVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Kynx\Laminas\FormShape\Filter\ToNullVisitor;
use Kynx\Laminas\FormShape\Psalm\ConfigLoader;
use Kynx\Laminas\FormShape\Psalm\TypeUtil;
use Laminas\Filter\Boolean;
use Laminas\Filter\ToNull;
use PHPUnit\Framework\Attributes\CoversClass;
Expand All @@ -15,7 +16,6 @@
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TLiteralFloat;
use Psalm\Type\Atomic\TLiteralInt;
use Psalm\Type\Atomic\TLiteralString;
use Psalm\Type\Atomic\TNonEmptyArray;
use Psalm\Type\Atomic\TNonEmptyString;
use Psalm\Type\Atomic\TNull;
Expand Down Expand Up @@ -52,7 +52,7 @@ public static function visitProvider(): array
],
'zero string' => [
new ToNull(['type' => ToNull::TYPE_ZERO_STRING]),
[TLiteralString::make('0')],
[TypeUtil::getAtomicStringFromLiteral('0')],
[new TString(), new TNull()],
],
'string' => [
Expand Down
Loading

0 comments on commit 5366199

Please sign in to comment.