update some strict parameters and separate easter eggs

This commit is contained in:
crazywhalecc
2022-12-18 00:17:28 +08:00
parent 58d4b4427d
commit ed4537e5d5
13 changed files with 196 additions and 199 deletions

View File

@@ -21,8 +21,7 @@ class AnnotationHandler
public const STATUS_RULE_FAILED = 4; // 判断事件执行的规则函数判定为false所以不执行此方法
/** @var AnnotationBase|string */
private $annotation_class;
private string|AnnotationBase $annotation_class;
/** @var callable */
private $rule_callback;
@@ -30,11 +29,9 @@ class AnnotationHandler
/** @var callable */
private $return_callback;
/** @var int */
private $status = self::STATUS_NORMAL;
private int $status = self::STATUS_NORMAL;
/** @var mixed */
private $return_val;
private mixed $return_val;
/**
* 注解调用器构造函数
@@ -50,10 +47,10 @@ class AnnotationHandler
/**
* 立刻中断注解调用器执行
*
* @param mixed $return_var 中断执行返回值传入null则代表无返回值
* @param null|mixed $return_var 中断执行返回值传入null则代表无返回值
* @throws InterruptException
*/
public static function interrupt($return_var = null)
public static function interrupt(mixed $return_var = null)
{
throw new InterruptException($return_var);
}

View File

@@ -15,7 +15,7 @@ class AnnotationMap
* @var array<string, array<AnnotationBase>>
* @internal
*/
public static $_list = [];
public static array $_list = [];
/**
* 存取注解对象的三维列表key1是注解所在的类名key2是注解所在的方法名value是该方法标注的注解们数组
@@ -23,14 +23,14 @@ class AnnotationMap
* @var array<string, array<string, array<AnnotationBase>>>
* @internal
*/
public static $_map = [];
public static array $_map = [];
/**
* 将Parser解析后的注解注册到全局的 AnnotationMap
*
* @param AnnotationParser $parser 注解解析器
*/
public static function loadAnnotationByParser(AnnotationParser $parser)
public static function loadAnnotationByParser(AnnotationParser $parser): void
{
// 生成后加入到全局list中
self::$_list = array_merge(self::$_list, $parser->generateAnnotationList());

View File

@@ -7,13 +7,11 @@ namespace ZM\Annotation;
use Doctrine\Common\Annotations\AnnotationReader;
use Koriym\Attributes\AttributeReader;
use Koriym\Attributes\DualReader;
use ReflectionMethod;
use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\Route;
use ZM\Annotation\Interfaces\ErgodicAnnotation;
use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Middleware\Middleware;
use ZM\Exception\ConfigException;
use ZM\Store\FileSystem;
use ZM\Utils\HttpUtil;
@@ -25,27 +23,27 @@ class AnnotationParser
/**
* @var array 要解析的路径列表
*/
private $path_list = [];
private array $path_list = [];
/**
* @var float 用于计算解析时间用的
*/
private $start_time;
private float $start_time;
/**
* @var array 用于解析的注解解析树,格式见下方的注释
*/
private $annotation_tree = [];
private array $annotation_tree = [];
/**
* @var array 用于生成"类-方法"对应"注解列表"的数组
*/
private $annotation_map = [];
private array $annotation_map = [];
/**
* @var array 特殊的注解解析器回调列表
*/
private $special_parsers = [];
private array $special_parsers = [];
/**
* AnnotationParser constructor.
@@ -54,6 +52,7 @@ class AnnotationParser
{
$this->start_time = microtime(true);
// 如果需要,添加内置的注解解析器
if ($with_internal_parsers) {
$this->special_parsers = [
Middleware::class => [function (Middleware $middleware) { \middleware()->bindMiddleware([resolve($middleware->class), $middleware->method], $middleware->name, $middleware->params); }],
@@ -73,103 +72,127 @@ class AnnotationParser
$this->special_parsers[$class_name][] = $callback;
}
/**
* 注册各个模块类的注解和模块level的排序
*
* @throws \ReflectionException
* @throws ConfigException
*/
public function parseAll()
public function parse(array $path): void
{
// 对每个设置的路径依次解析
foreach ($this->path_list as $path) {
logger()->debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
// 写日志
logger()->debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
// 首先获取路径下所有的类(通过 PSR-4 标准解析)
$all_class = FileSystem::getClassesPsr4($path[0], $path[1]);
// 首先获取路径下所有的类(通过 PSR-4 标准解析)
$all_class = FileSystem::getClassesPsr4($path[0], $path[1]);
// 读取配置文件中配置的忽略解析的注解名,防止误解析一些别的地方需要的注解,比如@mixin
$conf = config('global.runtime.annotation_reader_ignore');
// 有两种方式,第一种是通过名称,第二种是通过命名空间
if (isset($conf['name']) && is_array($conf['name'])) {
foreach ($conf['name'] as $v) {
AnnotationReader::addGlobalIgnoredName($v);
}
// 读取配置文件中配置的忽略解析的注解名,防止误解析一些别的地方需要的注解,比如@mixin
$conf = config('global.runtime.annotation_reader_ignore');
// 有两种方式,第一种是通过名称,第二种是通过命名空间
if (isset($conf['name']) && is_array($conf['name'])) {
foreach ($conf['name'] as $v) {
AnnotationReader::addGlobalIgnoredName($v);
}
if (isset($conf['namespace']) && is_array($conf['namespace'])) {
foreach ($conf['namespace'] as $v) {
AnnotationReader::addGlobalIgnoredNamespace($v);
}
}
if (isset($conf['namespace']) && is_array($conf['namespace'])) {
foreach ($conf['namespace'] as $v) {
AnnotationReader::addGlobalIgnoredNamespace($v);
}
// 因为mixin常用且框架默认不需要解析则全局忽略
AnnotationReader::addGlobalIgnoredName('mixin');
}
// 因为mixin常用且框架默认不需要解析则全局忽略
AnnotationReader::addGlobalIgnoredName('mixin');
// 声明一个既可以解析注解又可以解析Attribute的双reader来读取注解和Attribute
$reader = new DualReader(new AnnotationReader(), new AttributeReader());
foreach ($all_class as $v) {
logger()->debug('正在检索 ' . $v);
// 声明一个既可以解析注解又可以解析Attribute的双reader来读取注解和Attribute
$reader = new DualReader(new AnnotationReader(), new AttributeReader());
foreach ($all_class as $v) {
logger()->debug('正在检索 ' . $v);
// 通过反射实现注解读取
$reflection_class = new \ReflectionClass($v);
$methods = $reflection_class->getMethods(\ReflectionMethod::IS_PUBLIC);
$class_annotations = $reader->getClassAnnotations($reflection_class);
// 这段为新加的:start
// 这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
/*
$annotation_map: {
Module\Example\Hello: {
class_annotations: [
注解对象1, 注解对象2, ...
],
methods: [
ReflectionMethod, ReflectionMethod, ...
],
methods_annotations: {
foo: [ 注解对象1, 注解对象2, ... ],
bar: [ 注解对象1, 注解对象2, ... ],
}
// 通过反射实现注解读取
$reflection_class = new \ReflectionClass($v);
$methods = $reflection_class->getMethods(\ReflectionMethod::IS_PUBLIC);
$class_annotations = $reader->getClassAnnotations($reflection_class);
// 这段为新加的:start
// 这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
/*
$annotation_map: {
Module\Example\Hello: {
class_annotations: [
注解对象1, 注解对象2, ...
],
methods: [
ReflectionMethod, ReflectionMethod, ...
],
methods_annotations: {
foo: [ 注解对象1, 注解对象2, ... ],
bar: [ 注解对象1, 注解对象2, ... ],
}
}
*/
}
*/
// 保存对class的注解
$this->annotation_tree[$v]['class_annotations'] = $class_annotations;
// 保存类成员的方法的对应反射对象们
$this->annotation_tree[$v]['methods'] = $methods;
// 保存对每个方法获取到的注解们
foreach ($methods as $method) {
$this->annotation_tree[$v]['methods_annotations'][$method->getName()] = $reader->getMethodAnnotations($method);
// 保存对class的注解
$this->annotation_tree[$v]['class_annotations'] = $class_annotations;
// 保存类成员的方法的对应反射对象们
$this->annotation_tree[$v]['methods'] = $methods;
// 保存对每个方法获取到的注解们
foreach ($methods as $method) {
$this->annotation_tree[$v]['methods_annotations'][$method->getName()] = $reader->getMethodAnnotations($method);
}
// 因为适用于类的注解有一些比较特殊,比如有向下注入的,有控制行为的,所以需要遍历一下下放到方法里
foreach ($this->annotation_tree[$v]['class_annotations'] as $vs) {
$vs->class = $v;
// 预处理0排除所有非继承于 AnnotationBase 的注解
if (!$vs instanceof AnnotationBase) {
logger()->notice(get_class($vs) . ' is not extended from ' . AnnotationBase::class);
continue;
}
// 因为适用于类的注解有一些比较特殊,比如有向下注入的,有控制行为的,所以需要遍历一下下放到方法里
foreach ($this->annotation_tree[$v]['class_annotations'] as $vs) {
$vs->class = $v;
// 预处理1如果类包含了@Closed注解则跳过这个类
if ($vs instanceof Closed) {
unset($this->annotation_tree[$v]);
continue 2;
}
// 预处理0排除所有非继承于 AnnotationBase 的注解
if (!$vs instanceof AnnotationBase) {
logger()->notice(get_class($vs) . ' is not extended from ' . AnnotationBase::class);
// 预处理2将适用于每一个函数的注解到类注解重新注解到每个函数下面
if ($vs instanceof ErgodicAnnotation) {
foreach (($this->annotation_tree[$v]['methods'] ?? []) as $method) {
// 用 clone 的目的是生成个独立的对象,避免和 class 以及方法之间互相冲突
$copy = clone $vs;
$copy->method = $method->getName();
$this->annotation_tree[$v]['methods_annotations'][$method->getName()][] = $copy;
}
}
// 预处理3调用自定义解析器
foreach (($this->special_parsers[get_class($vs)] ?? []) as $parser) {
$result = $parser($vs);
if ($result === true) {
continue 2;
}
if ($result === false) {
continue 3;
}
}
}
// 预处理3处理每个函数上面的特殊注解就是需要操作一些东西的
foreach (($this->annotation_tree[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
foreach ($methods_annotations as $method_anno) {
// 预处理3.0:排除所有非继承于 AnnotationBase 的注解
if (!$method_anno instanceof AnnotationBase) {
logger()->notice('Binding annotation ' . get_class($method_anno) . ' to ' . $v . '::' . $method_name . ' is not extended from ' . AnnotationBase::class);
continue;
}
// 预处理1如果类包含了@Closed注解则跳过这个类
if ($vs instanceof Closed) {
unset($this->annotation_tree[$v]);
// 预处理3.1:给所有注解对象绑定当前的类名和方法名
$method_anno->class = $v;
$method_anno->method = $method_name;
// 预处理3.2:如果包含了@Closed注解则跳过这个方法的注解解析
if ($method_anno instanceof Closed) {
unset($this->annotation_tree[$v]['methods_annotations'][$method_name]);
continue 2;
}
// 预处理2将适用于每一个函数的注解到类注解重新注解到每个函数下面
if ($vs instanceof ErgodicAnnotation) {
foreach (($this->annotation_tree[$v]['methods'] ?? []) as $method) {
// 用 clone 的目的是生成个独立的对象,避免和 class 以及方法之间互相冲突
$copy = clone $vs;
$copy->method = $method->getName();
$this->annotation_tree[$v]['methods_annotations'][$method->getName()][] = $copy;
}
}
// 预处理3调用自定义解析器
foreach (($this->special_parsers[get_class($vs)] ?? []) as $parser) {
$result = $parser($vs);
// 预处理3.3:调用自定义解析器
foreach (($this->special_parsers[get_class($method_anno)] ?? []) as $parser) {
$result = $parser($method_anno);
if ($result === true) {
continue 2;
}
@@ -177,44 +200,23 @@ class AnnotationParser
continue 3;
}
}
}
// 预处理3处理每个函数上面的特殊注解就是需要操作一些东西的
foreach (($this->annotation_tree[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
foreach ($methods_annotations as $method_anno) {
// 预处理3.0:排除所有非继承于 AnnotationBase 的注解
if (!$method_anno instanceof AnnotationBase) {
logger()->notice('Binding annotation ' . get_class($method_anno) . ' to ' . $v . '::' . $method_name . ' is not extended from ' . AnnotationBase::class);
continue;
}
// 预处理3.1:给所有注解对象绑定当前的类名和方法名
$method_anno->class = $v;
$method_anno->method = $method_name;
// 预处理3.2:如果包含了@Closed注解则跳过这个方法的注解解析
if ($method_anno instanceof Closed) {
unset($this->annotation_tree[$v]['methods_annotations'][$method_name]);
continue 2;
}
// 预处理3.3:调用自定义解析器
foreach (($this->special_parsers[get_class($method_anno)] ?? []) as $parser) {
$result = $parser($method_anno);
if ($result === true) {
continue 2;
}
if ($result === false) {
continue 3;
}
}
// 如果上方没有解析或返回了 true则添加到注解解析列表中
$this->annotation_map[$v][$method_name][] = $method_anno;
}
// 如果上方没有解析或返回了 true则添加到注解解析列表中
$this->annotation_map[$v][$method_name][] = $method_anno;
}
}
}
}
/**
* 注册各个模块类的注解和模块level的排序
*/
public function parseAll(): void
{
// 对每个设置的路径依次解析
foreach ($this->path_list as $path) {
$this->parse($path);
}
logger()->debug('解析注解完毕!');
}
@@ -295,7 +297,7 @@ class AnnotationParser
/**
* 添加注解路由
*/
private function addRouteAnnotation(Route $vss)
private function addRouteAnnotation(Route $vss): void
{
// 拿到所属方法的类上面有没有控制器的注解
$prefix = '';

View File

@@ -24,13 +24,11 @@ use ZM\Annotation\Interfaces\Level;
class BindEvent extends AnnotationBase implements Level
{
/**
* @var string
* @Required()
*/
public $event_class;
public string $event_class;
/** @var int */
public $level = 800;
public int $level = 800;
/**
* @param string $event_class 绑定事件的类型

View File

@@ -19,8 +19,7 @@ use ZM\Annotation\AnnotationBase;
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Init extends AnnotationBase
{
/** @var int */
public $worker = 0;
public int $worker = 0;
public function __construct(int $worker = 0)
{

View File

@@ -21,10 +21,9 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
class Controller extends AnnotationBase implements ErgodicAnnotation
{
/**
* @var string
* @Required()
*/
public $prefix = '';
public string $prefix = '';
public function __construct(string $prefix)
{

View File

@@ -20,26 +20,18 @@ use ZM\Annotation\AnnotationBase;
class Route extends AnnotationBase
{
/**
* @var string
* @Required()
*/
public $route = '';
public string $route = '';
/**
* @var string
*/
public $name = '';
public string $name = '';
/**
* @var array
*/
public $request_method = ['GET', 'POST'];
public array $request_method = ['GET', 'POST'];
/**
* Routing path params binding. eg. {"id"="\d+"}
* @var array
*/
public $params = [];
public array $params = [];
public function __construct($route, $name = '', $request_method = ['GET', 'POST'], $params = [])
{
@@ -49,7 +41,7 @@ class Route extends AnnotationBase
$this->params = $params;
}
public static function make($route, $name = '', $request_method = ['GET', 'POST'], $params = [])
public static function make($route, $name = '', $request_method = ['GET', 'POST'], $params = []): static
{
return new static($route, $name, $request_method, $params);
}

View File

@@ -21,15 +21,14 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
class Middleware extends AnnotationBase implements ErgodicAnnotation
{
/**
* @var string
* @Required()
*/
public $name;
public string $name;
/**
* @var string[]
*/
public $params = [];
public array $params = [];
public function __construct($name, $params = [])
{

View File

@@ -23,41 +23,30 @@ use ZM\Exception\ZMKnownException;
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class BotCommand extends AnnotationBase implements Level
{
/** @var string */
public $name = '';
public string $name = '';
/** @var string */
public $match = '';
public string $match = '';
/** @var string */
public $pattern = '';
public string $pattern = '';
/** @var string */
public $regex = '';
public string $regex = '';
/** @var string */
public $start_with = '';
public string $start_with = '';
/** @var string */
public $end_with = '';
public string $end_with = '';
/** @var string */
public $keyword = '';
public string $keyword = '';
/** @var string[] */
public $alias = [];
public array $alias = [];
/** @var string */
public $message_type = '';
public string $message_type = '';
/** @var string */
public $user_id = '';
public string $user_id = '';
/** @var string */
public $group_id = '';
public string $group_id = '';
/** @var int */
public $level = 20;
public int $level = 20;
private array $arguments = [];