TypePHP 编译器 https://swoole.com/aot/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

136 lines
6.0 KiB

<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace TypePhp\Transform;
final class CompileTimeAttributeRegistry
{
public const TARGET_CLASS = 'class';
public const TARGET_NAMED_CLASS = 'named_class';
public const TARGET_CLASS_LIKE = 'class_like';
public const TARGET_FUNCTION = 'function';
public const TARGET_METHOD = 'method';
public const TARGET_PROPERTY_HOOK = 'property_hook';
public const TARGET_PROPERTY = 'property';
public const TARGET_DECLARED_PROPERTY = 'declared_property';
public const TARGET_PARAMETER = 'parameter';
public const ARGUMENTS_NONE = 'none';
public const ARGUMENTS_METHODS_FOR = 'methods_for';
public const ARGUMENTS_FIELDS = 'fields';
public const ARGUMENTS_VALIDATE = 'validate';
public const ARGUMENTS_WASM_EXPORT = 'wasm_export';
public const ARGUMENTS_ARRAY_DEF = 'array_def';
public const PHASE_PREPROCESS = 'preprocess';
public const PHASE_ENTER = 'enter';
public const PHASE_FUNCTION_LEAVE = 'function_leave';
public const PHASE_CLASS_LEAVE = 'class_leave';
/**
* @return array<string, array{
* name: string,
* targets: list<string>,
* target_error: string,
* repeatable: bool,
* argument_parser: string,
* conflicts: list<string>,
* phase: string,
* preserve_in_library_stub: bool
* }>
*/
public static function all(): array
{
static $definitions = null;
if ($definitions !== null) {
return $definitions;
}
$definitions = [];
$add = static function (
string $name,
array $targets,
string $targetError,
string $argumentParser,
string $phase,
bool $preserveInLibraryStub = true,
array $conflicts = [],
bool $repeatable = false,
) use (&$definitions): void {
$definitions[strtolower($name)] = [
'name' => $name,
'targets' => $targets,
'target_error' => $targetError,
'repeatable' => $repeatable,
'argument_parser' => $argumentParser,
'conflicts' => $conflicts,
'phase' => $phase,
'preserve_in_library_stub' => $preserveInLibraryStub,
];
};
$add('Native', [self::TARGET_NAMED_CLASS], 'Native can only be applied to named classes', self::ARGUMENTS_NONE, self::PHASE_PREPROCESS, false);
$add('MethodsFor', [self::TARGET_NAMED_CLASS], 'MethodsFor can only be applied to classes', self::ARGUMENTS_METHODS_FOR, self::PHASE_PREPROCESS);
$add('NoExport', [self::TARGET_CLASS_LIKE, self::TARGET_FUNCTION, self::TARGET_METHOD], 'NoExport can only be applied to classes, functions, or methods', self::ARGUMENTS_NONE, self::PHASE_PREPROCESS, false);
$add('WasmExport', [self::TARGET_FUNCTION], 'WasmExport can only be applied to named functions', self::ARGUMENTS_WASM_EXPORT, self::PHASE_PREPROCESS, false);
foreach (['Getter', 'Setter', 'With'] as $name) {
$add($name, [self::TARGET_PROPERTY], $name . ' can only be applied to instance properties', self::ARGUMENTS_NONE, self::PHASE_CLASS_LEAVE);
}
foreach (['Printer', 'Arrayable'] as $name) {
$add($name, [self::TARGET_NAMED_CLASS], $name . ' can only be applied to named classes', self::ARGUMENTS_FIELDS, self::PHASE_CLASS_LEAVE);
}
foreach (['NotNull', 'NotEmpty'] as $name) {
$add($name, [self::TARGET_PARAMETER], $name . ' can only be applied to function or method parameters', self::ARGUMENTS_NONE, self::PHASE_FUNCTION_LEAVE);
}
$add('Validate', [self::TARGET_PARAMETER], 'Validate can only be applied to function or method parameters', self::ARGUMENTS_VALIDATE, self::PHASE_FUNCTION_LEAVE);
$add(
'Override',
[self::TARGET_METHOD, self::TARGET_PROPERTY],
'Override can only be applied to methods or properties',
self::ARGUMENTS_NONE,
self::PHASE_ENTER,
);
$add('MustUse', [self::TARGET_FUNCTION, self::TARGET_METHOD], 'MustUse can only be applied to functions or methods', self::ARGUMENTS_NONE, self::PHASE_ENTER);
$add('Immutable', [self::TARGET_METHOD, self::TARGET_PROPERTY_HOOK, self::TARGET_PARAMETER], 'Immutable can only be applied to methods, property hooks, or function parameters', self::ARGUMENTS_NONE, self::PHASE_ENTER);
$add('Hot', [self::TARGET_FUNCTION, self::TARGET_METHOD], 'Hot can only be applied to functions or methods', self::ARGUMENTS_NONE, self::PHASE_ENTER, true, ['Cold']);
$add('Cold', [self::TARGET_FUNCTION, self::TARGET_METHOD], 'Cold can only be applied to functions or methods', self::ARGUMENTS_NONE, self::PHASE_ENTER, true, ['Hot']);
$add('Constructor', [self::TARGET_DECLARED_PROPERTY], 'Constructor can only be applied to instance properties', self::ARGUMENTS_NONE, self::PHASE_CLASS_LEAVE);
$add('ArrayDef', [self::TARGET_PROPERTY], 'ArrayDef can only be applied to properties', self::ARGUMENTS_ARRAY_DEF, self::PHASE_PREPROCESS);
return $definitions;
}
public static function get(string $name): ?array
{
return self::all()[strtolower(ltrim($name, '\\'))] ?? null;
}
/** @return list<string> */
public static function names(bool $preservedInLibraryStubOnly = false): array
{
$names = [];
foreach (self::all() as $definition) {
if (!$preservedInLibraryStubOnly || $definition['preserve_in_library_stub']) {
$names[] = $definition['name'];
}
}
return $names;
}
/** @return list<string> */
public static function namesForPhase(string $phase): array
{
$names = [];
foreach (self::all() as $definition) {
if ($definition['phase'] === $phase) {
$names[] = $definition['name'];
}
}
return $names;
}
}