mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 11:48:08 +08:00
Merge branch 'master' into pr/1488
This commit is contained in:
commit
06044f40de
@ -38,6 +38,10 @@
|
||||
|
||||
- [#1452](https://github.com/hyperf/hyperf/pull/1452) Encourage the use of `\Hyperf\Redis\Redis` instead of `\Redis` because of [#938](https://github.com/hyperf/hyperf/issues/938).
|
||||
|
||||
## Added
|
||||
|
||||
- [#1480](https://github.com/hyperf/hyperf/pull/1480) RPC client will generate the methods of inherited interface automatically now.
|
||||
|
||||
# v1.1.21 - 2020-03-19
|
||||
|
||||
## Added
|
||||
|
@ -22,7 +22,8 @@
|
||||
"psr/container": "^1.0",
|
||||
"hyperf/rpc": "~1.1.0",
|
||||
"hyperf/load-balancer": "~1.1.0",
|
||||
"hyperf/utils": "~1.1.0"
|
||||
"hyperf/utils": "~1.1.0",
|
||||
"roave/better-reflection": "^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"malukenho/docheader": "^0.1.6",
|
||||
|
@ -12,7 +12,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Hyperf\RpcClient\Proxy;
|
||||
|
||||
use Hyperf\Utils\Composer;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
@ -23,18 +22,24 @@ class Ast
|
||||
/**
|
||||
* @var \PhpParser\Parser
|
||||
*/
|
||||
private $astParser;
|
||||
protected $astParser;
|
||||
|
||||
/**
|
||||
* @var PrettyPrinterAbstract
|
||||
*/
|
||||
private $printer;
|
||||
protected $printer;
|
||||
|
||||
/**
|
||||
* @var CodeLoader
|
||||
*/
|
||||
protected $codeLoader;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$parserFactory = new ParserFactory();
|
||||
$this->astParser = $parserFactory->create(ParserFactory::ONLY_PHP7);
|
||||
$this->printer = new Standard();
|
||||
$this->codeLoader = new CodeLoader();
|
||||
}
|
||||
|
||||
public function proxy(string $className, string $proxyClassName)
|
||||
@ -47,20 +52,11 @@ class Ast
|
||||
$proxyClassName = end($exploded);
|
||||
}
|
||||
|
||||
$code = $this->getCodeByClassName($className);
|
||||
$code = $this->codeLoader->getCodeByClassName($className);
|
||||
$stmts = $this->astParser->parse($code);
|
||||
$traverser = new NodeTraverser();
|
||||
$traverser->addVisitor(new ProxyCallVisitor($proxyClassName));
|
||||
$modifiedStmts = $traverser->traverse($stmts);
|
||||
return $this->printer->prettyPrintFile($modifiedStmts);
|
||||
}
|
||||
|
||||
public function getCodeByClassName(string $className): string
|
||||
{
|
||||
$file = Composer::getLoader()->findFile($className);
|
||||
if (! $file) {
|
||||
return '';
|
||||
}
|
||||
return file_get_contents($file);
|
||||
}
|
||||
}
|
||||
|
27
src/rpc-client/src/Proxy/CodeLoader.php
Normal file
27
src/rpc-client/src/Proxy/CodeLoader.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace Hyperf\RpcClient\Proxy;
|
||||
|
||||
use Hyperf\Utils\Composer;
|
||||
|
||||
class CodeLoader
|
||||
{
|
||||
public function getCodeByClassName(string $className): string
|
||||
{
|
||||
$file = Composer::getLoader()->findFile($className);
|
||||
if (! $file) {
|
||||
return '';
|
||||
}
|
||||
return file_get_contents($file);
|
||||
}
|
||||
}
|
@ -15,22 +15,43 @@ namespace Hyperf\RpcClient\Proxy;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use ReflectionMethod;
|
||||
use Roave\BetterReflection\Reflection\ReflectionClass;
|
||||
|
||||
class ProxyCallVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $classname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $constants = [];
|
||||
|
||||
public function __construct(string $classname)
|
||||
{
|
||||
$this->classname = $classname;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof Node\Stmt\Namespace_) {
|
||||
$this->namespace = $node->name->toCodeString();
|
||||
}
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
if ($node instanceof Interface_) {
|
||||
$node->stmts = $this->generateStmts($node);
|
||||
return new Node\Stmt\Class_($this->classname, [
|
||||
'stmts' => $node->stmts,
|
||||
'extends' => new Node\Name\FullyQualified(AbstractProxyService::class),
|
||||
@ -39,19 +60,37 @@ class ProxyCallVisitor extends NodeVisitorAbstract
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($node instanceof Node\Stmt\ClassMethod) {
|
||||
$node->stmts = [
|
||||
new Node\Stmt\Return_(new Node\Expr\MethodCall(
|
||||
new Node\Expr\PropertyFetch(new Node\Expr\Variable('this'), new Node\Identifier('client')),
|
||||
new Node\Identifier('__call'),
|
||||
[
|
||||
new Node\Scalar\MagicConst\Function_(),
|
||||
new Node\Expr\FuncCall(new Node\Name('func_get_args')),
|
||||
]
|
||||
)),
|
||||
];
|
||||
return $node;
|
||||
}
|
||||
return parent::leaveNode($node); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
public function generateStmts(Interface_ $node): array
|
||||
{
|
||||
$betterReflectionInterface = ReflectionClass::createFromName($this->namespace . '\\' . $node->name);
|
||||
$reflectionMethods = $betterReflectionInterface->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
$stmts = [];
|
||||
foreach ($reflectionMethods as $method) {
|
||||
$stmts[] = $this->overrideMethod($method->getAst());
|
||||
}
|
||||
return $stmts;
|
||||
}
|
||||
|
||||
protected function overrideMethod(Node\Stmt\ClassMethod $stmt): Node\Stmt\ClassMethod
|
||||
{
|
||||
$stmt->stmts = value(function () use ($stmt) {
|
||||
$methodCall = new Node\Expr\MethodCall(
|
||||
new Node\Expr\PropertyFetch(new Node\Expr\Variable('this'), new Node\Identifier('client')),
|
||||
new Node\Identifier('__call'),
|
||||
[
|
||||
new Node\Scalar\MagicConst\Function_(),
|
||||
new Node\Expr\FuncCall(new Node\Name('func_get_args')),
|
||||
]
|
||||
);
|
||||
if (((string) $stmt->getReturnType()) !== 'void') {
|
||||
return [new Node\Stmt\Return_($methodCall)];
|
||||
} else {
|
||||
return [new Node\Stmt\Expression($methodCall)];
|
||||
}
|
||||
});
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
namespace Hyperf\RpcClient;
|
||||
|
||||
use Hyperf\RpcClient\Proxy\Ast;
|
||||
use Hyperf\RpcClient\Proxy\CodeLoader;
|
||||
use Hyperf\Utils\Coroutine\Locker;
|
||||
use Hyperf\Utils\Traits\Container;
|
||||
|
||||
@ -23,11 +24,17 @@ class ProxyFactory
|
||||
/**
|
||||
* @var Ast
|
||||
*/
|
||||
private $ast;
|
||||
protected $ast;
|
||||
|
||||
/**
|
||||
* @var \Hyperf\RpcClient\Proxy\CodeLoader
|
||||
*/
|
||||
protected $codeLoader;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ast = new Ast();
|
||||
$this->codeLoader = new CodeLoader();
|
||||
}
|
||||
|
||||
public function createProxy($serviceClass): string
|
||||
@ -41,7 +48,7 @@ class ProxyFactory
|
||||
}
|
||||
|
||||
$proxyFileName = str_replace('\\', '_', $serviceClass);
|
||||
$proxyClassName = $serviceClass . '_' . md5($this->ast->getCodeByClassName($serviceClass));
|
||||
$proxyClassName = $serviceClass . '_' . md5($this->codeLoader->getCodeByClassName($serviceClass));
|
||||
$path = $dir . $proxyFileName . '.proxy.php';
|
||||
|
||||
$key = md5($path);
|
||||
|
Loading…
Reference in New Issue
Block a user