Skip to content

Commit

Permalink
Nicer type descriptions usable in PHPDocs
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 12, 2021
1 parent f7d232a commit 03341cc
Show file tree
Hide file tree
Showing 52 changed files with 333 additions and 284 deletions.
2 changes: 1 addition & 1 deletion build/baseline-8.0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ parameters:
path: ../src/Type/Php/MbFunctionsReturnTypeExtension.php

-
message: "#^Strict comparison using \\=\\=\\= between array<int, string>&nonEmpty and false will always evaluate to false\\.$#"
message: "#^Strict comparison using \\=\\=\\= between non-empty-array<int, string> and false will always evaluate to false\\.$#"
count: 1
path: ../src/Type/Php/StrSplitFunctionReturnTypeExtension.php

Expand Down
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ parameters:
count: 1
path: src/Testing/PHPStanTestCase.php

-
message: "#^Call to function in_array\\(\\) with arguments 'array', array\\<int, 'array'\\|'string'\\> and true will always evaluate to true\\.$#"
count: 1
path: src/Type/IntersectionType.php

-
message:
"""
Expand Down
2 changes: 1 addition & 1 deletion src/Type/Accessory/AccessoryNumericStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function equals(Type $type): bool

public function describe(\PHPStan\Type\VerbosityLevel $level): string
{
return 'numeric';
return 'numeric-string';
}

public function isOffsetAccessible(): TrinaryLogic
Expand Down
2 changes: 1 addition & 1 deletion src/Type/Accessory/NonEmptyArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function equals(Type $type): bool

public function describe(\PHPStan\Type\VerbosityLevel $level): string
{
return 'nonEmpty';
return 'non-empty-array';
}

public function isOffsetAccessible(): TrinaryLogic
Expand Down
94 changes: 62 additions & 32 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,45 +149,75 @@ function () use ($level): string {
return implode('&', $typeNames);
},
function () use ($level): string {
$typeNames = [];
$accessoryTypes = [];
foreach ($this->types as $type) {
if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType) {
$accessoryTypes[] = $type;
}
if ($type instanceof AccessoryType && !$type instanceof AccessoryNumericStringType && !$type instanceof NonEmptyArrayType && !$type instanceof AccessoryNonEmptyStringType) {
continue;
}
$typeNames[] = $type->describe($level);
}

if (count($accessoryTypes) > 0) {
return implode('&', array_map(static function (Type $type) use ($level): string {
return $type->describe($level);
}, $accessoryTypes));
}

return implode('&', $typeNames);
return $this->describeItself($level, true);
},
function () use ($level): string {
$typeNames = [];
$accessoryTypes = [];
foreach ($this->types as $type) {
if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType) {
$accessoryTypes[] = $type;
return $this->describeItself($level, false);
}
);
}

private function describeItself(VerbosityLevel $level, bool $skipAccessoryTypes): string
{
$typesToDescribe = [];
$skipTypeNames = [];
foreach ($this->types as $type) {
if ($type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType || $type instanceof AccessoryNumericStringType) {
$typesToDescribe[] = $type;
$skipTypeNames[] = 'string';
continue;
}
if ($type instanceof NonEmptyArrayType) {
$typesToDescribe[] = $type;
$skipTypeNames[] = 'array';
continue;
}

if ($skipAccessoryTypes) {
continue;
}

if (!$type instanceof AccessoryType) {
continue;
}

$typesToDescribe[] = $type;
}

$describedTypes = [];
foreach ($this->types as $type) {
if ($type instanceof AccessoryType) {
continue;
}
$typeDescription = $type->describe($level);
if (
substr($typeDescription, 0, strlen('array<')) === 'array<'
&& in_array('array', $skipTypeNames, true)
) {
foreach ($typesToDescribe as $j => $typeToDescribe) {
if (!$typeToDescribe instanceof NonEmptyArrayType) {
continue;
}
$typeNames[] = $type->describe($level);
}

if (count($accessoryTypes) > 0) {
return implode('&', array_map(static function (Type $type) use ($level): string {
return $type->describe($level);
}, $accessoryTypes));
unset($typesToDescribe[$j]);
}

return implode('&', $typeNames);
$describedTypes[] = 'non-empty-array<' . substr($typeDescription, strlen('array<'));
continue;
}
);

if (in_array($typeDescription, $skipTypeNames, true)) {
continue;
}

$describedTypes[] = $type->describe($level);
}

foreach ($typesToDescribe as $typeToDescribe) {
$describedTypes[] = $typeToDescribe->describe($level);
}

return implode('&', $describedTypes);
}

public function canAccessProperties(): TrinaryLogic
Expand Down
12 changes: 7 additions & 5 deletions src/Type/VerbosityLevel.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ public static function getRecommendedLevelByType(Type $acceptingType, ?Type $acc
$moreVerbose = true;
return $type;
}
if ($type instanceof AccessoryNumericStringType || $type instanceof AccessoryNonEmptyStringType || $type instanceof AccessoryLiteralStringType) {
$moreVerbose = true;
return $type;
}
if ($type instanceof NonEmptyArrayType) {
if (
// synced with IntersectionType::describe()
$type instanceof AccessoryNonEmptyStringType
|| $type instanceof AccessoryLiteralStringType
|| $type instanceof AccessoryNumericStringType
|| $type instanceof NonEmptyArrayType
) {
$moreVerbose = true;
return $type;
}
Expand Down
Loading

2 comments on commit 03341cc

@staabm
Copy link
Contributor

@staabm staabm commented on 03341cc Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i love it!! <3

@ondrejmirtes
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I still need to update ConstantArrayType (array shapes), but I need to fix 300+ test assertions :)

Please sign in to comment.