mirror of
https://github.com/Respect/Validation.git
synced 2026-03-14 14:25:45 +01:00
Generate PrefixMap constants from Mixin attributes
- Add PrefixMapGenerator to produce COMPOSABLE/COMPOSABLE_WITH_ARGUMENT constants from #[Mixin] attributes, replacing hand-written arrays - Move Prefix transformer to reference generated PrefixMap constants - Extract NamespaceScanner from MixinGenerator for shared directory scanning - Introduce FluentBuilder subnamespace for builder-chain generators (MixinGenerator, PrefixMapGenerator, MethodBuilder, Mixin attribute) - Add CodeGenerator interface and Config class as shared CodeGen contracts
This commit is contained in:
parent
91fb70fd11
commit
25387853f3
50 changed files with 393 additions and 152 deletions
17
src-dev/CodeGen/CodeGenerator.php
Normal file
17
src-dev/CodeGen/CodeGenerator.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: (c) Respect Project Contributors
|
||||
* SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen;
|
||||
|
||||
interface CodeGenerator
|
||||
{
|
||||
/** @return array<string, string> filename => content */
|
||||
public function generate(): array;
|
||||
}
|
||||
23
src-dev/CodeGen/Config.php
Normal file
23
src-dev/CodeGen/Config.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: (c) Respect Project Contributors
|
||||
* SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen;
|
||||
|
||||
final readonly class Config
|
||||
{
|
||||
public function __construct(
|
||||
public string $sourceDir,
|
||||
public string $sourceNamespace,
|
||||
public string $outputDir,
|
||||
public string $outputNamespace,
|
||||
public OutputFormatter $outputFormatter = new OutputFormatter(),
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen;
|
||||
namespace Respect\Dev\CodeGen\FluentBuilder;
|
||||
|
||||
use Nette\PhpGenerator\Method;
|
||||
use Nette\PhpGenerator\PhpNamespace;
|
||||
|
|
@ -41,13 +41,13 @@ final class MethodBuilder
|
|||
|
||||
public function build(
|
||||
PhpNamespace $namespace,
|
||||
ReflectionClass $validatorReflection,
|
||||
ReflectionClass $nodeReflection,
|
||||
string $returnType,
|
||||
string|null $prefix = null,
|
||||
bool $static = false,
|
||||
ReflectionParameter|null $prefixParameter = null,
|
||||
): Method {
|
||||
$originalName = $validatorReflection->getShortName();
|
||||
$originalName = $nodeReflection->getShortName();
|
||||
$name = $prefix ? $prefix . ucfirst($originalName) : lcfirst($originalName);
|
||||
|
||||
$method = new Method($name);
|
||||
|
|
@ -61,7 +61,7 @@ final class MethodBuilder
|
|||
$this->addPrefixParameter($method, $prefixParameter);
|
||||
}
|
||||
|
||||
$constructor = $validatorReflection->getConstructor();
|
||||
$constructor = $nodeReflection->getConstructor();
|
||||
if ($constructor === null) {
|
||||
return $method;
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen\Attributes;
|
||||
namespace Respect\Dev\CodeGen\FluentBuilder;
|
||||
|
||||
use Attribute;
|
||||
|
||||
|
|
@ -8,42 +8,39 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen;
|
||||
namespace Respect\Dev\CodeGen\FluentBuilder;
|
||||
|
||||
use DirectoryIterator;
|
||||
use Nette\PhpGenerator\PhpNamespace;
|
||||
use Nette\PhpGenerator\Printer;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\CodeGenerator;
|
||||
use Respect\Dev\CodeGen\Config;
|
||||
use Respect\Dev\CodeGen\InterfaceConfig;
|
||||
use Respect\Dev\CodeGen\NamespaceScanner;
|
||||
|
||||
use function file_get_contents;
|
||||
use function in_array;
|
||||
use function is_file;
|
||||
use function is_readable;
|
||||
use function ksort;
|
||||
use function sprintf;
|
||||
|
||||
final class MixinGenerator
|
||||
final class MixinGenerator implements CodeGenerator
|
||||
{
|
||||
/** @param array<InterfaceConfig> $interfaces */
|
||||
public function __construct(
|
||||
private readonly string $sourceDir,
|
||||
private readonly string $sourceNamespace,
|
||||
private readonly string $outputDir,
|
||||
private readonly string $outputNamespace,
|
||||
private readonly array $interfaces,
|
||||
private readonly Config $config,
|
||||
private readonly MethodBuilder $methodBuilder = new MethodBuilder(),
|
||||
private readonly OutputFormatter $outputFormatter = new OutputFormatter(),
|
||||
private readonly array $interfaces = [],
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return array<string, string> filename => content */
|
||||
public function generate(): array
|
||||
{
|
||||
$validators = $this->scanValidators();
|
||||
$prefixes = $this->discoverPrefixes($validators);
|
||||
$filters = $this->discoverFilters($validators);
|
||||
$nodes = NamespaceScanner::scan($this->config->sourceDir, $this->config->sourceNamespace);
|
||||
$prefixes = $this->discoverPrefixes($nodes);
|
||||
$filters = $this->discoverFilters($nodes);
|
||||
|
||||
$files = [];
|
||||
|
||||
|
|
@ -52,12 +49,12 @@ final class MixinGenerator
|
|||
|
||||
foreach ($prefixes as $prefix) {
|
||||
$interfaceName = $prefix['name'] . $interfaceConfig->suffix;
|
||||
$prefixInterfaceNames[] = $this->outputNamespace . '\\' . $interfaceName;
|
||||
$prefixInterfaceNames[] = $this->config->outputNamespace . '\\' . $interfaceName;
|
||||
|
||||
$this->generateInterface(
|
||||
$interfaceName,
|
||||
$interfaceConfig,
|
||||
$validators,
|
||||
$nodes,
|
||||
$filters,
|
||||
$prefix,
|
||||
$files,
|
||||
|
|
@ -67,7 +64,7 @@ final class MixinGenerator
|
|||
$this->generateRootInterface(
|
||||
$interfaceConfig,
|
||||
$prefixInterfaceNames,
|
||||
$validators,
|
||||
$nodes,
|
||||
$filters,
|
||||
$files,
|
||||
);
|
||||
|
|
@ -76,41 +73,16 @@ final class MixinGenerator
|
|||
return $files;
|
||||
}
|
||||
|
||||
/** @return array<string, ReflectionClass> */
|
||||
private function scanValidators(): array
|
||||
{
|
||||
$validators = [];
|
||||
|
||||
foreach (new DirectoryIterator($this->sourceDir) as $file) {
|
||||
if (!$file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$className = $this->sourceNamespace . '\\' . $file->getBasename('.php');
|
||||
$reflection = new ReflectionClass($className);
|
||||
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$validators[$reflection->getShortName()] = $reflection;
|
||||
}
|
||||
|
||||
ksort($validators);
|
||||
|
||||
return $validators;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ReflectionClass> $validators
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
*
|
||||
* @return array<array{name: string, prefix: string, requireInclusion: bool, prefixParameter: ?ReflectionParameter}>
|
||||
*/
|
||||
private function discoverPrefixes(array $validators): array
|
||||
private function discoverPrefixes(array $nodes): array
|
||||
{
|
||||
$prefixes = [];
|
||||
|
||||
foreach ($validators as $reflection) {
|
||||
foreach ($nodes as $reflection) {
|
||||
$attributes = $reflection->getAttributes(Mixin::class);
|
||||
if ($attributes === []) {
|
||||
continue;
|
||||
|
|
@ -121,14 +93,13 @@ final class MixinGenerator
|
|||
continue;
|
||||
}
|
||||
|
||||
$constructor = $reflection->getConstructor();
|
||||
$prefixParameter = null;
|
||||
if ($mixin->prefixParameter) {
|
||||
$constructor = $reflection->getConstructor();
|
||||
if ($constructor !== null) {
|
||||
$params = $constructor->getParameters();
|
||||
if ($params !== []) {
|
||||
$prefixParameter = $params[0];
|
||||
}
|
||||
|
||||
if ($mixin->prefixParameter && $constructor !== null) {
|
||||
$parameters = $constructor->getParameters();
|
||||
if ($parameters !== []) {
|
||||
$prefixParameter = $parameters[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,15 +117,15 @@ final class MixinGenerator
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ReflectionClass> $validators
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
*
|
||||
* @return array<string, Mixin>
|
||||
*/
|
||||
private function discoverFilters(array $validators): array
|
||||
private function discoverFilters(array $nodes): array
|
||||
{
|
||||
$filters = [];
|
||||
|
||||
foreach ($validators as $name => $reflection) {
|
||||
foreach ($nodes as $name => $reflection) {
|
||||
$attributes = $reflection->getAttributes(Mixin::class);
|
||||
if ($attributes === []) {
|
||||
continue;
|
||||
|
|
@ -167,7 +138,7 @@ final class MixinGenerator
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ReflectionClass> $validators
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
* @param array<string, Mixin> $filters
|
||||
* @param array{name: string, prefix: string, requireInclusion: bool, prefixParameter: ?ReflectionParameter} $prefix
|
||||
* @param array<string, string> $files
|
||||
|
|
@ -175,15 +146,15 @@ final class MixinGenerator
|
|||
private function generateInterface(
|
||||
string $interfaceName,
|
||||
InterfaceConfig $config,
|
||||
array $validators,
|
||||
array $nodes,
|
||||
array $filters,
|
||||
array $prefix,
|
||||
array &$files,
|
||||
): void {
|
||||
$namespace = new PhpNamespace($this->outputNamespace);
|
||||
$namespace = new PhpNamespace($this->config->outputNamespace);
|
||||
$interface = $namespace->addInterface($interfaceName);
|
||||
|
||||
foreach ($validators as $name => $reflection) {
|
||||
foreach ($nodes as $name => $reflection) {
|
||||
$mixin = $filters[$name] ?? null;
|
||||
|
||||
if ($prefix['requireInclusion']) {
|
||||
|
|
@ -211,27 +182,29 @@ final class MixinGenerator
|
|||
|
||||
/**
|
||||
* @param array<string> $prefixInterfaceNames
|
||||
* @param array<string, ReflectionClass> $validators
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
* @param array<string, Mixin> $filters
|
||||
* @param array<string, string> $files
|
||||
*/
|
||||
private function generateRootInterface(
|
||||
InterfaceConfig $config,
|
||||
array $prefixInterfaceNames,
|
||||
array $validators,
|
||||
array $nodes,
|
||||
array $filters,
|
||||
array &$files,
|
||||
): void {
|
||||
$interfaceName = $config->suffix;
|
||||
$namespace = new PhpNamespace($this->outputNamespace);
|
||||
$namespace = new PhpNamespace($this->config->outputNamespace);
|
||||
$interface = $namespace->addInterface($interfaceName);
|
||||
|
||||
foreach ($config->rootExtends as $extend) {
|
||||
$namespace->addUse($extend);
|
||||
$interface->addExtend($extend);
|
||||
}
|
||||
|
||||
foreach ($prefixInterfaceNames as $prefixInterface) {
|
||||
$interface->addExtend($prefixInterface);
|
||||
foreach ($prefixInterfaceNames as $prefixInterfaceName) {
|
||||
$namespace->addUse($prefixInterfaceName);
|
||||
$interface->addExtend($prefixInterfaceName);
|
||||
}
|
||||
|
||||
if ($config->rootComment !== null) {
|
||||
|
|
@ -242,7 +215,7 @@ final class MixinGenerator
|
|||
$namespace->addUse($use);
|
||||
}
|
||||
|
||||
foreach ($validators as $reflection) {
|
||||
foreach ($nodes as $reflection) {
|
||||
$method = $this->methodBuilder->build(
|
||||
$namespace,
|
||||
$reflection,
|
||||
|
|
@ -260,16 +233,17 @@ final class MixinGenerator
|
|||
/** @param array<string, string> $files */
|
||||
private function addFile(string $interfaceName, PhpNamespace $namespace, array &$files): void
|
||||
{
|
||||
$filename = $this->config->outputDir . '/' . $interfaceName . '.php';
|
||||
|
||||
$printer = new Printer();
|
||||
$printer->wrapLength = 300;
|
||||
|
||||
$filename = sprintf('%s/%s.php', $this->outputDir, $interfaceName);
|
||||
$existingContent = '';
|
||||
if (is_file($filename) && is_readable($filename)) {
|
||||
$existingContent = file_get_contents($filename) ?: '';
|
||||
}
|
||||
|
||||
$formattedContent = $this->outputFormatter->format(
|
||||
$formattedContent = $this->config->outputFormatter->format(
|
||||
$printer->printNamespace($namespace),
|
||||
$existingContent,
|
||||
);
|
||||
160
src-dev/CodeGen/FluentBuilder/PrefixMapGenerator.php
Normal file
160
src-dev/CodeGen/FluentBuilder/PrefixMapGenerator.php
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: (c) Respect Project Contributors
|
||||
* SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen\FluentBuilder;
|
||||
|
||||
use Nette\PhpGenerator\PhpNamespace;
|
||||
use Nette\PhpGenerator\Printer;
|
||||
use ReflectionClass;
|
||||
use Respect\Dev\CodeGen\CodeGenerator;
|
||||
use Respect\Dev\CodeGen\Config;
|
||||
use Respect\Dev\CodeGen\NamespaceScanner;
|
||||
|
||||
use function array_keys;
|
||||
use function ctype_upper;
|
||||
use function file_get_contents;
|
||||
use function is_file;
|
||||
use function is_readable;
|
||||
use function ksort;
|
||||
use function lcfirst;
|
||||
use function str_starts_with;
|
||||
use function strlen;
|
||||
use function uksort;
|
||||
|
||||
final class PrefixMapGenerator implements CodeGenerator
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Config $config,
|
||||
private readonly string $outputClassName,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return array<string, string> filename => content */
|
||||
public function generate(): array
|
||||
{
|
||||
$nodes = NamespaceScanner::scan($this->config->sourceDir, $this->config->sourceNamespace);
|
||||
$prefixes = $this->discoverPrefixes($nodes);
|
||||
$composable = $this->buildComposable($nodes, $prefixes);
|
||||
$composableWithArgument = $this->buildComposableWithArgument($prefixes);
|
||||
|
||||
$namespace = new PhpNamespace($this->config->outputNamespace);
|
||||
$class = $namespace->addClass($this->outputClassName);
|
||||
$class->setFinal();
|
||||
|
||||
$class->addConstant('COMPOSABLE', $composable)->setPublic()->setType('array');
|
||||
$class->addConstant('COMPOSABLE_WITH_ARGUMENT', $composableWithArgument)->setPublic()->setType('array');
|
||||
|
||||
$printer = new Printer();
|
||||
$printer->wrapLength = 300;
|
||||
|
||||
$outputFile = $this->config->outputDir . '/' . $this->outputClassName . '.php';
|
||||
|
||||
$existingContent = '';
|
||||
if (is_file($outputFile) && is_readable($outputFile)) {
|
||||
$existingContent = file_get_contents($outputFile) ?: '';
|
||||
}
|
||||
|
||||
$formattedContent = $this->config->outputFormatter->format(
|
||||
$printer->printNamespace($namespace),
|
||||
$existingContent,
|
||||
);
|
||||
|
||||
return [$outputFile => $formattedContent];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
*
|
||||
* @return array<string, array{prefix: string, prefixParameter: bool}>
|
||||
*/
|
||||
private function discoverPrefixes(array $nodes): array
|
||||
{
|
||||
$prefixes = [];
|
||||
|
||||
foreach ($nodes as $reflection) {
|
||||
$attributes = $reflection->getAttributes(Mixin::class);
|
||||
if ($attributes === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mixin = $attributes[0]->newInstance();
|
||||
if ($mixin->prefix === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$prefixes[$mixin->prefix] = [
|
||||
'prefix' => $mixin->prefix,
|
||||
'prefixParameter' => $mixin->prefixParameter,
|
||||
];
|
||||
}
|
||||
|
||||
ksort($prefixes);
|
||||
|
||||
return $prefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ReflectionClass> $nodes
|
||||
* @param array<string, array{prefix: string, prefixParameter: bool}> $prefixes
|
||||
*
|
||||
* @return array<string, true>
|
||||
*/
|
||||
private function buildComposable(array $nodes, array $prefixes): array
|
||||
{
|
||||
$composable = [];
|
||||
|
||||
foreach (array_keys($prefixes) as $prefix) {
|
||||
$composable[$prefix] = true;
|
||||
|
||||
foreach (array_keys($nodes) as $name) {
|
||||
$lcName = lcfirst($name);
|
||||
if ($lcName === $prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!str_starts_with($lcName, $prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ctype_upper($lcName[strlen($prefix)])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$composable[$lcName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
uksort($composable, static fn(string $a, string $b): int => strlen($b) <=> strlen($a) ?: $a <=> $b);
|
||||
|
||||
return $composable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array{prefix: string, prefixParameter: bool}> $prefixes
|
||||
*
|
||||
* @return array<string, true>
|
||||
*/
|
||||
private function buildComposableWithArgument(array $prefixes): array
|
||||
{
|
||||
$composableWithArgument = [];
|
||||
|
||||
foreach ($prefixes as $prefix => $info) {
|
||||
if (!$info['prefixParameter']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$composableWithArgument[$prefix] = true;
|
||||
}
|
||||
|
||||
ksort($composableWithArgument);
|
||||
|
||||
return $composableWithArgument;
|
||||
}
|
||||
}
|
||||
44
src-dev/CodeGen/NamespaceScanner.php
Normal file
44
src-dev/CodeGen/NamespaceScanner.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: (c) Respect Project Contributors
|
||||
* SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Dev\CodeGen;
|
||||
|
||||
use DirectoryIterator;
|
||||
use ReflectionClass;
|
||||
|
||||
use function ksort;
|
||||
|
||||
final class NamespaceScanner
|
||||
{
|
||||
/** @return array<string, ReflectionClass> */
|
||||
public static function scan(string $directory, string $namespace): array
|
||||
{
|
||||
$nodes = [];
|
||||
|
||||
foreach (new DirectoryIterator($directory) as $file) {
|
||||
if (!$file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$className = $namespace . '\\' . $file->getBasename('.php');
|
||||
$reflection = new ReflectionClass($className);
|
||||
|
||||
if ($reflection->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nodes[$reflection->getShortName()] = $reflection;
|
||||
}
|
||||
|
||||
ksort($nodes);
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ final class OutputFormatter
|
|||
$existingHeader = $matches[0] ?? '';
|
||||
|
||||
$replacements = [
|
||||
'/\n\n\t(public|\/\*\*)/m' => PHP_EOL . ' $1',
|
||||
'/\n\n\t(public|private|\/\*\*)/m' => PHP_EOL . ' $1',
|
||||
'/\t/m' => ' ',
|
||||
'/\?([a-zA-Z]+) \$/' => '$1|null $',
|
||||
'/\/\*\*\n +\* (.+)\n +\*\//m' => '/** $1 */',
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Dev\Commands;
|
||||
|
||||
use Respect\Dev\CodeGen\Config;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\MethodBuilder;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\MixinGenerator;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\PrefixMapGenerator;
|
||||
use Respect\Dev\CodeGen\InterfaceConfig;
|
||||
use Respect\Dev\CodeGen\MethodBuilder;
|
||||
use Respect\Dev\CodeGen\MixinGenerator;
|
||||
use Respect\Dev\Differ\ConsoleDiffer;
|
||||
use Respect\Dev\Differ\Item;
|
||||
use Respect\Validation\Mixins\Chain;
|
||||
|
|
@ -58,11 +60,15 @@ final class LintMixinCommand extends Command
|
|||
{
|
||||
$srcDir = dirname(__DIR__, 2) . '/src';
|
||||
|
||||
$generator = new MixinGenerator(
|
||||
$config = new Config(
|
||||
sourceDir: $srcDir . '/Validators',
|
||||
sourceNamespace: 'Respect\\Validation\\Validators',
|
||||
outputDir: $srcDir . '/Mixins',
|
||||
outputNamespace: 'Respect\\Validation\\Mixins',
|
||||
);
|
||||
|
||||
$generator = new MixinGenerator(
|
||||
config: $config,
|
||||
methodBuilder: new MethodBuilder(
|
||||
excludedTypePrefixes: ['Sokil', 'Egulias'],
|
||||
excludedTypeNames: ['finfo'],
|
||||
|
|
@ -83,7 +89,12 @@ final class LintMixinCommand extends Command
|
|||
],
|
||||
);
|
||||
|
||||
$files = $generator->generate();
|
||||
$prefixMapGenerator = new PrefixMapGenerator(
|
||||
config: $config,
|
||||
outputClassName: 'PrefixMap',
|
||||
);
|
||||
|
||||
$files = $generator->generate() + $prefixMapGenerator->generate();
|
||||
|
||||
$updatableFiles = [];
|
||||
foreach ($files as $filename => $content) {
|
||||
|
|
|
|||
33
src/Mixins/PrefixMap.php
generated
Normal file
33
src/Mixins/PrefixMap.php
generated
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* SPDX-FileCopyrightText: (c) Respect Project Contributors
|
||||
* SPDX-FileContributor: Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Validation\Mixins;
|
||||
|
||||
final class PrefixMap
|
||||
{
|
||||
public const array COMPOSABLE = [
|
||||
'propertyOptional' => true,
|
||||
'propertyExists' => true,
|
||||
'keyOptional' => true,
|
||||
'keyExists' => true,
|
||||
'property' => true,
|
||||
'undefOr' => true,
|
||||
'keySet' => true,
|
||||
'length' => true,
|
||||
'nullOr' => true,
|
||||
'allOf' => true,
|
||||
'all' => true,
|
||||
'key' => true,
|
||||
'max' => true,
|
||||
'min' => true,
|
||||
'not' => true,
|
||||
];
|
||||
public const array COMPOSABLE_WITH_ARGUMENT = ['key' => true, 'property' => true];
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Respect\Validation\Transformers;
|
||||
|
||||
use Respect\Validation\Mixins\PrefixMap;
|
||||
|
||||
use function array_keys;
|
||||
use function array_slice;
|
||||
use function implode;
|
||||
|
|
@ -19,31 +21,6 @@ use function sprintf;
|
|||
|
||||
final class Prefix implements Transformer
|
||||
{
|
||||
private const array RULES_THAT_PREFIX_OR_STAND_ALONE = [
|
||||
'all' => true,
|
||||
'allOf' => true,
|
||||
'emoji' => true,
|
||||
'key' => true,
|
||||
'keyExists' => true,
|
||||
'keyOptional' => true,
|
||||
'keySet' => true,
|
||||
'length' => true,
|
||||
'max' => true,
|
||||
'maxAge' => true,
|
||||
'min' => true,
|
||||
'minAge' => true,
|
||||
'not' => true,
|
||||
'nullOr' => true,
|
||||
'property' => true,
|
||||
'propertyExists' => true,
|
||||
'propertyOptional' => true,
|
||||
'undefOr' => true,
|
||||
];
|
||||
private const array RULES_THAT_USE_SUFFIX_AS_ARGUMENT = [
|
||||
'key' => true,
|
||||
'property' => true,
|
||||
];
|
||||
|
||||
private static string|null $regex = null;
|
||||
|
||||
public function transform(ValidatorSpec $validatorSpec): ValidatorSpec
|
||||
|
|
@ -53,38 +30,42 @@ final class Prefix implements Transformer
|
|||
return $validatorSpec;
|
||||
}
|
||||
|
||||
if (!isset(self::RULES_THAT_USE_SUFFIX_AS_ARGUMENT[$matches['name']])) {
|
||||
if (!isset(PrefixMap::COMPOSABLE_WITH_ARGUMENT[$matches['prefix']])) {
|
||||
return new ValidatorSpec(
|
||||
$matches['rest'],
|
||||
$matches['suffix'],
|
||||
$validatorSpec->arguments,
|
||||
new ValidatorSpec($matches['name']),
|
||||
new ValidatorSpec($matches['prefix']),
|
||||
);
|
||||
}
|
||||
|
||||
return new ValidatorSpec(
|
||||
$matches['rest'],
|
||||
$matches['suffix'],
|
||||
array_slice($validatorSpec->arguments, 1),
|
||||
new ValidatorSpec($matches['name'], [$validatorSpec->arguments[0]]),
|
||||
new ValidatorSpec($matches['prefix'], [$validatorSpec->arguments[0]]),
|
||||
);
|
||||
}
|
||||
|
||||
/** @return array{}|array{name: string, rest: string} */
|
||||
/** @return array{}|array{prefix: string, suffix: string} */
|
||||
private function match(ValidatorSpec $validatorSpec): array
|
||||
{
|
||||
if ($validatorSpec->wrapper !== null || isset(self::RULES_THAT_PREFIX_OR_STAND_ALONE[$validatorSpec->name])) {
|
||||
if ($validatorSpec->wrapper !== null || isset(PrefixMap::COMPOSABLE[$validatorSpec->name])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
preg_match(self::getRegex(), $validatorSpec->name, $matches);
|
||||
|
||||
return $matches;
|
||||
if ($matches === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['prefix' => $matches['prefix'], 'suffix' => $matches['suffix']];
|
||||
}
|
||||
|
||||
private static function getRegex(): string
|
||||
{
|
||||
return self::$regex ?? self::$regex = sprintf(
|
||||
'/^(?<name>%s)(?<rest>.+)$/',
|
||||
implode('|', array_keys(self::RULES_THAT_PREFIX_OR_STAND_ALONE)),
|
||||
'/^(?<prefix>%s)(?<suffix>.+)$/',
|
||||
implode('|', array_keys(PrefixMap::COMPOSABLE)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Helpers\CanEvaluateShortCircuit;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Path;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use ReflectionAttribute;
|
|||
use ReflectionClass;
|
||||
use ReflectionObject;
|
||||
use ReflectionProperty;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Id;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Exceptions\InvalidValidatorException;
|
||||
use Respect\Validation\Helpers\CanCompareValues;
|
||||
use Respect\Validation\Message\Template;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Exceptions\InvalidValidatorException;
|
||||
use Respect\Validation\Helpers\CanCompareValues;
|
||||
use Respect\Validation\Message\Template;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Comparison;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
use SplFileInfo;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\StringFormatter\Formatter;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Comparison;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Comparison;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Path;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Respect\Validation\Validators;
|
|||
|
||||
use ArrayAccess;
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Path;
|
||||
use Respect\Validation\Result;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
use Respect\Validation\Validators\Core\KeyRelated;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Exceptions\InvalidValidatorException;
|
||||
use Respect\Validation\Helpers\CanEvaluateShortCircuit;
|
||||
use Respect\Validation\Message\Template;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Respect\Validation\Validators;
|
|||
|
||||
use Attribute;
|
||||
use Countable as PhpCountable;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Comparison;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Comparison;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validators\Core\FilteredArray;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validators\Core\FilteredArray;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Name;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Validators\Core\Simple;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Respect\Validation\Validators;
|
|||
use Attribute;
|
||||
use ReflectionClass;
|
||||
use ReflectionObject;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Path;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Respect\Validation\Validators;
|
|||
use Attribute;
|
||||
use ReflectionClass;
|
||||
use ReflectionObject;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Path;
|
||||
use Respect\Validation\Result;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Result;
|
||||
use Respect\Validation\Validator;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Helpers\CanValidateUndefined;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ declare(strict_types=1);
|
|||
namespace Respect\Validation\Validators;
|
||||
|
||||
use Attribute;
|
||||
use Respect\Dev\CodeGen\Attributes\Mixin;
|
||||
use Respect\Dev\CodeGen\FluentBuilder\Mixin;
|
||||
use Respect\Validation\Helpers\CanValidateUndefined;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Result;
|
||||
|
|
|
|||
|
|
@ -91,9 +91,7 @@ final class PrefixTest extends TestCase
|
|||
'keySet' => ['keySet'],
|
||||
'length' => ['length'],
|
||||
'max' => ['max'],
|
||||
'maxAge' => ['maxAge'],
|
||||
'min' => ['min'],
|
||||
'minAge' => ['minAge'],
|
||||
'not' => ['not'],
|
||||
'undef' => ['undef'],
|
||||
'property' => ['property'],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue