[Schema] Support PHPStan/Psalm integer ranges (#422)

This commit is contained in:
wWzZb 2026-08-16 15:31:28 +08:00 • committed by GitHub
commit 76778a4d9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 2 deletions

View file

@ -677,7 +677,12 @@ final class SchemaGenerator implements SchemaGeneratorInterface
return ['array']; return ['array'];
} }
// PRIORITY 3: Handle unions (recursive) // PRIORITY 3: Treat PHPStan/Psalm integer ranges as their base type
if (preg_match('/^int\s*<\s*[^<>]+\s*>$/i', $normalizedType)) {
return ['integer'];
}
// PRIORITY 4: Handle unions (recursive)
if (str_contains($normalizedType, '|')) { if (str_contains($normalizedType, '|')) {
$types = explode('|', $normalizedType); $types = explode('|', $normalizedType);
$jsonTypes = []; $jsonTypes = [];
@ -689,7 +694,7 @@ final class SchemaGenerator implements SchemaGeneratorInterface
return array_values(array_unique($jsonTypes)); return array_values(array_unique($jsonTypes));
} }
// PRIORITY 4: Handle simple built-in types // PRIORITY 5: Handle simple built-in types
return match ($normalizedType) { return match ($normalizedType) {
'string', 'scalar' => ['string'], 'string', 'scalar' => ['string'],
'?string' => ['null', 'string'], '?string' => ['null', 'string'],

View file

@ -226,6 +226,21 @@ class SchemaGeneratorFixture
): void { ): void {
} }
/**
* PHPStan/Psalm integer ranges should keep their base integer type.
*
* @param int<0, max> $offset Positive offset
* @param int<min, -1> $negative Negative value
* @param int<-5, 10> $bounded Bounded value
*/
public function integerRangeTypes(
#[Schema(minimum: 0)]
int $offset,
int $negative,
int $bounded,
): void {
}
// ===== ENUM SCENARIOS ===== // ===== ENUM SCENARIOS =====
/** /**

View file

@ -190,6 +190,16 @@ final class SchemaGeneratorTest extends TestCase
$this->assertEqualsCanonicalizing(['username', 'priority'], $schema['required']); $this->assertEqualsCanonicalizing(['username', 'priority'], $schema['required']);
} }
public function testMapsPhpStanAndPsalmIntegerRangesToBaseIntegerType(): void
{
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'integerRangeTypes');
$schema = $this->schemaGenerator->generate($method);
$this->assertEquals(['type' => 'integer', 'description' => 'Positive offset', 'minimum' => 0], $schema['properties']['offset']);
$this->assertEquals(['type' => 'integer', 'description' => 'Negative value'], $schema['properties']['negative']);
$this->assertEquals(['type' => 'integer', 'description' => 'Bounded value'], $schema['properties']['bounded']);
}
public function testGeneratesCorrectSchemaForEnumParameters(): void public function testGeneratesCorrectSchemaForEnumParameters(): void
{ {
$method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'enumParameters'); $method = new \ReflectionMethod(SchemaGeneratorFixture::class, 'enumParameters');