MadelineProto/src/danog/MadelineProto/AnnotationsBuilder.php

396 lines
18 KiB
PHP
Raw Normal View History

<?php
Merge alpha into master (async, huge bugfixes and more) (#546) * Implement async and lots of bugfixes * Implement more async * Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr * Apply fixes from StyleCI * Bugfixes * Apply fixes from StyleCI * Bugfixes, implement combined promises * Apply fixes from StyleCI * Support passing method arguments as callable * Starting to write async upload logic * Apply fixes from StyleCI * Start implementing async file upload * Apply fixes from StyleCI * bugfix * Apply fixes from StyleCI * Start rewriting connection module * Add PHP file docblocks for all classes * Start working on new async stream API * Finish writing stream API * More stream API fixes * Apply fixes from StyleCI * Rewrite DataCenter and Connection modules * Clean up stream API documentation * Fixes * Apply fixes from StyleCI * Add referenced parameter to get length of buffer to read in getReadBuffer API * Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar * Start fixing reads * Fix all protocol stream wrappers * Apply fixes from StyleCI * Implement disconnection, and remove end function * Working async RPC * Implement async file upload * Bugfix * Method recall bugfixes * Bugfixes * Trait bugfixes * Fix FIFO buffer * Bugfixes and speedtests * Async logging * Implement websocket streams * Implement loop API, signal API, clean closing and start changing layer * Small magna, websocket and HTTP fixes * Clean up loop API * Improved stack traces, 2FA and async * Login fixes * Added instructions for manual verification * Small fixes * More app info improvements * More app info improvements * TL and 2FA fixes * Update to layer 89 * More bugfixes * Implement broken media reporting * Remove debug comments * PHP 7.2 backwards compatibility * Bugfixes * Async key generation * Some simplifications * Transport fixes * Cleanup * async API * Performance fixes * Fixes to async API * Bugfixes * Implement one-time async loop * Authorization and logging fixes * Update to layer 91 * 7to5 fix * Null coalesce conversion * Implement socks5 proxy * Implement HTTP proxy * Fixes to HTTP proxy * MTProxy and socks5 fixes * Disable PHP 5 conversion * Proxies have higher priority * Avoid error handling in vendor * Override composer dependencies * Fix travis build * Final composer fixes * Proxy logic fixes * Fix get_updates update handling * Do not use parallel file driver if not supported * Refactor loader and implement HTTP fixes * Suppress errors in loader * HTTP and authorization fixes * HTTP fixes * Improved peer management * Use HTTP protocol on altervista * Small bugfixes * Minor fixes * Docufix * Docufix * Legacy fixes * Fix message queue * Avoid updating if using MTProxy * Improve logs and examples * Trim final newlines while converting parse mode * Reimplement noResponse flag * Async combined event handler and APIFactory fixes * Actually return config * Case-insensitive methods * Bugfix * Apply fixes from StyleCI (#545) * MTProxy fixes * PHP 5 warning * Improved PHP 5 warning * Use <br> along with newlines in web logs * Update docs
2018-12-26 20:51:14 +01:00
/**
* AnnotationsBuilder module.
*
* This file is part of MadelineProto.
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU General Public License along with MadelineProto.
* If not, see <http://www.gnu.org/licenses/>.
*
* @author Daniil Gentili <daniil@daniil.it>
2020-02-17 14:13:46 +01:00
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
Merge alpha into master (async, huge bugfixes and more) (#546) * Implement async and lots of bugfixes * Implement more async * Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr * Apply fixes from StyleCI * Bugfixes * Apply fixes from StyleCI * Bugfixes, implement combined promises * Apply fixes from StyleCI * Support passing method arguments as callable * Starting to write async upload logic * Apply fixes from StyleCI * Start implementing async file upload * Apply fixes from StyleCI * bugfix * Apply fixes from StyleCI * Start rewriting connection module * Add PHP file docblocks for all classes * Start working on new async stream API * Finish writing stream API * More stream API fixes * Apply fixes from StyleCI * Rewrite DataCenter and Connection modules * Clean up stream API documentation * Fixes * Apply fixes from StyleCI * Add referenced parameter to get length of buffer to read in getReadBuffer API * Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar * Start fixing reads * Fix all protocol stream wrappers * Apply fixes from StyleCI * Implement disconnection, and remove end function * Working async RPC * Implement async file upload * Bugfix * Method recall bugfixes * Bugfixes * Trait bugfixes * Fix FIFO buffer * Bugfixes and speedtests * Async logging * Implement websocket streams * Implement loop API, signal API, clean closing and start changing layer * Small magna, websocket and HTTP fixes * Clean up loop API * Improved stack traces, 2FA and async * Login fixes * Added instructions for manual verification * Small fixes * More app info improvements * More app info improvements * TL and 2FA fixes * Update to layer 89 * More bugfixes * Implement broken media reporting * Remove debug comments * PHP 7.2 backwards compatibility * Bugfixes * Async key generation * Some simplifications * Transport fixes * Cleanup * async API * Performance fixes * Fixes to async API * Bugfixes * Implement one-time async loop * Authorization and logging fixes * Update to layer 91 * 7to5 fix * Null coalesce conversion * Implement socks5 proxy * Implement HTTP proxy * Fixes to HTTP proxy * MTProxy and socks5 fixes * Disable PHP 5 conversion * Proxies have higher priority * Avoid error handling in vendor * Override composer dependencies * Fix travis build * Final composer fixes * Proxy logic fixes * Fix get_updates update handling * Do not use parallel file driver if not supported * Refactor loader and implement HTTP fixes * Suppress errors in loader * HTTP and authorization fixes * HTTP fixes * Improved peer management * Use HTTP protocol on altervista * Small bugfixes * Minor fixes * Docufix * Docufix * Legacy fixes * Fix message queue * Avoid updating if using MTProxy * Improve logs and examples * Trim final newlines while converting parse mode * Reimplement noResponse flag * Async combined event handler and APIFactory fixes * Actually return config * Case-insensitive methods * Bugfix * Apply fixes from StyleCI (#545) * MTProxy fixes * PHP 5 warning * Improved PHP 5 warning * Use <br> along with newlines in web logs * Update docs
2018-12-26 20:51:14 +01:00
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
*
2019-10-31 15:07:35 +01:00
* @link https://docs.madelineproto.xyz MadelineProto documentation
Merge alpha into master (async, huge bugfixes and more) (#546) * Implement async and lots of bugfixes * Implement more async * Implement async, implement bugfixes for the connection module, for the datacenter module, huge bugfixes, huge perfomance improvements, media DCs for https, advanced selecting, custom var_dump, totally rewritten IOLoop and response mechanism, promises, improvements to the TL parser, custom mb_substr * Apply fixes from StyleCI * Bugfixes * Apply fixes from StyleCI * Bugfixes, implement combined promises * Apply fixes from StyleCI * Support passing method arguments as callable * Starting to write async upload logic * Apply fixes from StyleCI * Start implementing async file upload * Apply fixes from StyleCI * bugfix * Apply fixes from StyleCI * Start rewriting connection module * Add PHP file docblocks for all classes * Start working on new async stream API * Finish writing stream API * More stream API fixes * Apply fixes from StyleCI * Rewrite DataCenter and Connection modules * Clean up stream API documentation * Fixes * Apply fixes from StyleCI * Add referenced parameter to get length of buffer to read in getReadBuffer API * Moved all MessageHandler code in the Connection module, added a PHP version warning in the phar * Start fixing reads * Fix all protocol stream wrappers * Apply fixes from StyleCI * Implement disconnection, and remove end function * Working async RPC * Implement async file upload * Bugfix * Method recall bugfixes * Bugfixes * Trait bugfixes * Fix FIFO buffer * Bugfixes and speedtests * Async logging * Implement websocket streams * Implement loop API, signal API, clean closing and start changing layer * Small magna, websocket and HTTP fixes * Clean up loop API * Improved stack traces, 2FA and async * Login fixes * Added instructions for manual verification * Small fixes * More app info improvements * More app info improvements * TL and 2FA fixes * Update to layer 89 * More bugfixes * Implement broken media reporting * Remove debug comments * PHP 7.2 backwards compatibility * Bugfixes * Async key generation * Some simplifications * Transport fixes * Cleanup * async API * Performance fixes * Fixes to async API * Bugfixes * Implement one-time async loop * Authorization and logging fixes * Update to layer 91 * 7to5 fix * Null coalesce conversion * Implement socks5 proxy * Implement HTTP proxy * Fixes to HTTP proxy * MTProxy and socks5 fixes * Disable PHP 5 conversion * Proxies have higher priority * Avoid error handling in vendor * Override composer dependencies * Fix travis build * Final composer fixes * Proxy logic fixes * Fix get_updates update handling * Do not use parallel file driver if not supported * Refactor loader and implement HTTP fixes * Suppress errors in loader * HTTP and authorization fixes * HTTP fixes * Improved peer management * Use HTTP protocol on altervista * Small bugfixes * Minor fixes * Docufix * Docufix * Legacy fixes * Fix message queue * Avoid updating if using MTProxy * Improve logs and examples * Trim final newlines while converting parse mode * Reimplement noResponse flag * Async combined event handler and APIFactory fixes * Actually return config * Case-insensitive methods * Bugfix * Apply fixes from StyleCI (#545) * MTProxy fixes * PHP 5 warning * Improved PHP 5 warning * Use <br> along with newlines in web logs * Update docs
2018-12-26 20:51:14 +01:00
*/
2018-02-24 17:54:39 +01:00
namespace danog\MadelineProto;
2019-09-18 21:49:26 +02:00
use Amp\Promise;
2020-09-24 20:49:34 +02:00
use danog\MadelineProto\Settings\TLSchema;
2019-10-31 20:48:06 +01:00
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\TL\TLCallback;
use phpDocumentor\Reflection\DocBlockFactory;
2018-02-24 17:54:39 +01:00
class AnnotationsBuilder
{
2020-10-03 12:36:08 +02:00
/**
2020-10-03 15:04:35 +02:00
* Reflection classes.
2020-10-03 12:36:08 +02:00
*/
private array $reflectionClasses = [];
/**
2020-10-03 15:04:35 +02:00
* Logger.
2020-10-03 12:36:08 +02:00
*/
private Logger $logger;
/**
2020-10-03 15:04:35 +02:00
* Namespace.
2020-10-03 12:36:08 +02:00
*/
private string $namespace;
/**
2020-10-03 15:04:35 +02:00
* TL instance.
2020-10-03 12:36:08 +02:00
*/
private TL $TL;
/**
2020-10-03 15:04:35 +02:00
* Settings.
2020-10-03 12:36:08 +02:00
*/
private array $settings;
/**
2020-10-03 15:04:35 +02:00
* Output file.
2020-10-03 12:36:08 +02:00
*/
private string $output;
2019-12-14 16:47:04 +01:00
public function __construct(Logger $logger, array $settings, string $output, array $reflectionClasses, string $namespace)
{
2019-12-14 16:47:04 +01:00
$this->reflectionClasses = $reflectionClasses;
2018-04-19 19:56:52 +02:00
$this->logger = $logger;
2019-12-14 16:47:04 +01:00
$this->namespace = $namespace;
2020-10-03 15:36:03 +02:00
/** @psalm-suppress InvalidArgument */
2019-10-31 20:48:06 +01:00
$this->TL = new TL(new class($logger) {
2020-10-04 16:35:33 +02:00
public Logger $logger;
public function __construct(Logger $logger)
2019-10-31 20:48:06 +01:00
{
$this->logger = $logger;
}
});
2020-09-24 20:49:34 +02:00
$tlSchema = new TLSchema;
$tlSchema->mergeArray($settings);
$this->TL->init($tlSchema);
$this->settings = $settings;
2019-12-14 16:47:04 +01:00
$this->output = $output;
}
2020-10-01 21:03:25 +02:00
public function mkAnnotations(): void
{
2018-03-02 01:38:10 +01:00
\danog\MadelineProto\Logger::log('Generating annotations...', \danog\MadelineProto\Logger::NOTICE);
$this->setProperties();
$this->createInternalClasses();
}
/**
* Open file of class APIFactory
* Insert properties
* save the file with new content.
2019-09-13 16:55:48 +02:00
*
* @return void
*/
private function setProperties()
{
2018-03-02 01:38:10 +01:00
\danog\MadelineProto\Logger::log('Generating properties...', \danog\MadelineProto\Logger::NOTICE);
$fixture = DocBlockFactory::createInstance();
2019-12-14 16:47:04 +01:00
$class = new \ReflectionClass($this->reflectionClasses['APIFactory']);
2019-09-02 17:08:36 +02:00
$content = \file_get_contents($filename = $class->getFileName());
foreach ($class->getProperties() as $property) {
if ($raw_docblock = $property->getDocComment()) {
$docblock = $fixture->create($raw_docblock);
if ($docblock->hasTag('internal')) {
2020-04-05 15:33:01 +02:00
$content = \str_replace("\n ".$raw_docblock."\n public \$".$property->getName().';', '', $content);
}
}
}
2019-10-31 20:48:06 +01:00
foreach ($this->TL->getMethodNamespaces() as $namespace) {
2020-04-05 15:33:01 +02:00
$content = \preg_replace('/(class( \\w+[,]?){0,}\\n{\\n)/', '${1}'." /**\n"." * @internal this is a internal property generated by build_docs.php, don't change manually\n"." *\n"." * @var {$namespace}\n"." */\n"." public \${$namespace};\n", $content);
}
2019-09-02 17:08:36 +02:00
\file_put_contents($filename, $content);
}
/**
* Create internalDoc.
*
* @return void
*/
private function createInternalClasses(): void
{
2018-03-02 01:38:10 +01:00
\danog\MadelineProto\Logger::log('Creating internal classes...', \danog\MadelineProto\Logger::NOTICE);
2019-12-14 16:47:04 +01:00
$handle = \fopen($this->output, 'w');
\fwrite($handle, "<?php namespace {$this->namespace}; class InternalDoc extends APIFactory {}");
$class = new \ReflectionClass($this->reflectionClasses['API']);
2019-09-18 21:21:34 +02:00
$methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
2019-12-28 17:34:04 +01:00
$ignoreMethods = ['fetchserializableobject'];
2019-09-18 21:21:34 +02:00
foreach ($methods as $method) {
$ignoreMethods[$method->getName()] = $method->getName();
}
$class = new \ReflectionClass(TLCallback::class);
$methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$ignoreMethods[$method->getName()] = $method->getName();
}
2019-09-18 21:21:34 +02:00
\fclose($handle);
2019-12-14 16:47:04 +01:00
$handle = \fopen($this->output, 'w');
2019-09-18 20:46:20 +02:00
$internalDoc = [];
2019-10-31 20:48:06 +01:00
foreach ($this->TL->getMethods()->by_id as $id => $data) {
2019-09-02 17:08:36 +02:00
if (!\strpos($data['method'], '.')) {
continue;
}
2019-09-02 17:08:36 +02:00
list($namespace, $method) = \explode('.', $data['method']);
2019-10-31 20:48:06 +01:00
if (!\in_array($namespace, $this->TL->getMethodNamespaces())) {
continue;
}
2020-06-16 17:52:55 +02:00
$internalDoc[$namespace][$method]['title'] = \str_replace(['](../', '.md'], ['](https://docs.madelineproto.xyz/API_docs/', '.html'], Lang::$lang['en']["method_{$data['method']}"] ?? '');
2019-12-14 16:47:04 +01:00
$type = \str_ireplace(['vector<', '>'], [' of ', '[]'], $data['type']);
2017-08-18 18:10:30 +02:00
foreach ($data['params'] as $param) {
2019-09-18 20:46:20 +02:00
if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
continue;
}
2019-09-18 20:46:20 +02:00
if ($param['name'] === 'data' && $type === 'messages.SentEncryptedMessage') {
$param['name'] = 'message';
$param['type'] = 'DecryptedMessage';
}
if ($param['name'] === 'chat_id' && $data['method'] !== 'messages.discardEncryption') {
$param['type'] = 'InputPeer';
}
if ($param['name'] === 'hash' && $param['type'] === 'int') {
$param['pow'] = 'hi';
$param['type'] = 'Vector t';
$param['subtype'] = 'int';
}
$stype = 'type';
if (isset($param['subtype'])) {
$stype = 'subtype';
}
2019-12-14 16:47:04 +01:00
$ptype = $param[$stype];
switch ($ptype) {
case 'true':
case 'false':
$ptype = 'boolean';
}
2020-01-31 19:29:43 +01:00
$ptype = $stype === 'type' ? $ptype : "[{$ptype}]";
$opt = $param['pow'] ?? false ? 'Optional: ' : '';
2020-06-16 17:52:55 +02:00
$internalDoc[$namespace][$method]['attr'][$param['name']] = ['type' => $ptype, 'description' => \str_replace(['](../', '.md'], ['](https://docs.madelineproto.xyz/API_docs/', '.html'], $opt.(Lang::$lang['en']["method_{$data['method']}_param_{$param['name']}_type_{$param['type']}"] ?? ''))];
}
if ($type === 'Bool') {
2019-09-02 17:08:36 +02:00
$type = \strtolower($type);
}
$internalDoc[$namespace][$method]['return'] = $type;
}
2019-12-14 16:47:04 +01:00
$class = new \ReflectionClass($this->reflectionClasses['MTProto']);
2019-09-18 20:46:20 +02:00
$methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
2020-04-05 14:57:33 +02:00
$class = new \ReflectionClass(Tools::class);
$methods = \array_merge($methods, $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC));
2019-09-18 21:21:34 +02:00
foreach ($methods as $key => $method) {
2019-09-18 20:46:20 +02:00
$name = $method->getName();
if ($method == 'methodCallAsyncRead') {
unset($methods[\array_search('methodCall', $methods)]);
2019-09-18 21:21:34 +02:00
} elseif (\strpos($name, '__') === 0) {
unset($methods[$key]);
2019-09-18 20:46:20 +02:00
} elseif (\stripos($name, 'async') !== false) {
if (\strpos($name, '_async') !== false) {
unset($methods[\array_search(\str_ireplace('_async', '', $method), $methods)]);
} else {
unset($methods[\array_search(\str_ireplace('async', '', $method), $methods)]);
}
}
}
2020-04-05 15:33:01 +02:00
$sortedMethods = [];
foreach ($methods as $method) {
$sortedMethods[$method->getName()] = $method;
}
\ksort($sortedMethods);
$methods = \array_values($sortedMethods);
2019-09-18 20:46:20 +02:00
foreach ($methods as $method) {
$name = $method->getName();
2019-09-18 21:21:34 +02:00
if (isset($ignoreMethods[$name])) {
continue;
}
if (\strpos($method->getDocComment() ?? '', '@internal') !== false) {
continue;
}
2019-12-28 16:45:00 +01:00
$static = $method->isStatic();
if (!$static) {
$code = \file_get_contents($method->getFileName());
$code = \implode("\n", \array_slice(\explode("\n", $code), $method->getStartLine(), $method->getEndLine() - $method->getStartLine()));
if (\strpos($code, '$this') === false) {
2020-01-31 19:29:43 +01:00
Logger::log("{$name} should be STATIC!", Logger::FATAL_ERROR);
2019-12-28 16:45:00 +01:00
}
}
if ($name == 'methodCallAsyncRead') {
$name = 'methodCall';
2019-09-18 20:46:20 +02:00
} elseif (\stripos($name, 'async') !== false) {
if (\strpos($name, '_async') !== false) {
$name = \str_ireplace('_async', '', $name);
} else {
$name = \str_ireplace('async', '', $name);
}
}
2020-06-16 17:52:55 +02:00
$name = StrTools::toCamelCase($name);
2019-09-18 21:21:34 +02:00
$name = \str_ireplace(['mtproto', 'api'], ['MTProto', 'API'], $name);
2019-09-18 20:46:20 +02:00
$doc = 'public function ';
$doc .= $name;
$doc .= '(';
$paramList = '';
2019-09-18 21:21:34 +02:00
$hasVariadic = false;
2019-09-18 20:46:20 +02:00
foreach ($method->getParameters() as $param) {
if ($param->allowsNull()) {
//$doc .= '?';
}
if ($type = $param->getType()) {
if ($type->allowsNull()) {
$doc .= '?';
}
2019-09-18 21:21:34 +02:00
if (!$type->isBuiltin()) {
$doc .= '\\';
}
2019-09-18 20:46:20 +02:00
$doc .= $type->getName();
$doc .= ' ';
2019-12-28 17:11:08 +01:00
} else {
2020-04-05 15:33:01 +02:00
Logger::log($name.'.'.$param->getName()." has no type!", Logger::WARNING);
2019-09-18 20:46:20 +02:00
}
if ($param->isVariadic()) {
$doc .= '...';
}
if ($param->isPassedByReference()) {
$doc .= '&';
}
$doc .= '$';
$doc .= $param->getName();
if ($param->isOptional() && !$param->isVariadic()) {
$doc .= ' = ';
if ($param->isDefaultValueConstant()) {
2020-04-05 15:33:01 +02:00
$doc .= '\\'.\str_replace(['NULL', 'self'], ['null', 'danog\\MadelineProto\\MTProto'], $param->getDefaultValueConstantName());
2019-09-18 20:46:20 +02:00
} else {
2019-09-18 21:21:34 +02:00
$doc .= \str_replace('NULL', 'null', \var_export($param->getDefaultValue(), true));
2019-09-18 20:46:20 +02:00
}
}
$doc .= ', ';
2019-09-18 21:21:34 +02:00
if ($param->isVariadic()) {
$hasVariadic = true;
$paramList .= '...';
}
2020-04-05 15:33:01 +02:00
$paramList .= '$'.$param->getName().', ';
2019-09-18 20:46:20 +02:00
}
2020-01-19 13:46:49 +01:00
$hasReturnValue = ($type = $method->getReturnType()) && !\in_array($type->getName(), [\Generator::class, Promise::class]);
if (!$hasVariadic && !$static && !$hasReturnValue) {
2019-09-18 21:45:08 +02:00
$paramList .= '$extra, ';
$doc .= 'array $extra = []';
}
2019-09-18 20:46:20 +02:00
$doc = \rtrim($doc, ', ');
$paramList = \rtrim($paramList, ', ');
$doc .= ")";
2019-12-28 16:45:00 +01:00
$async = true;
2020-10-06 20:37:11 +02:00
if ($hasReturnValue && $static) {
2019-09-18 20:46:20 +02:00
$doc .= ': ';
if ($type->allowsNull()) {
$doc .= '?';
}
2019-12-28 16:45:00 +01:00
if (!$type->isBuiltin()) {
$doc .= '\\';
}
2020-01-19 13:46:49 +01:00
$doc .= $type->getName() === 'self' ? $this->reflectionClasses['API'] : $type->getName();
2019-12-28 16:45:00 +01:00
$async = false;
2019-09-18 20:46:20 +02:00
}
2020-04-05 15:33:01 +02:00
if ($method->getDeclaringClass()->getName() == Tools::class) {
$async = false;
}
2020-01-31 19:29:43 +01:00
$finalParamList = $hasVariadic ? "Tools::arr({$paramList})" : "[{$paramList}]";
2020-01-19 13:46:49 +01:00
$ret = $type && \in_array($type->getName(), ['self', 'void']) ? '' : 'return';
$doc .= "\n{\n";
2020-01-19 13:46:49 +01:00
if ($async) {
2020-01-31 19:29:43 +01:00
$doc .= " {$ret} \$this->__call(__FUNCTION__, {$finalParamList});\n";
2020-01-19 13:46:49 +01:00
} elseif (!$static) {
2020-01-31 19:29:43 +01:00
$doc .= " {$ret} \$this->API->{$name}({$paramList});\n";
2019-12-28 16:45:00 +01:00
} else {
2020-04-05 15:33:01 +02:00
$doc .= " {$ret} \\".$method->getDeclaringClass()->getName()."::".$name."({$paramList});\n";
2019-12-28 16:45:00 +01:00
}
2020-01-19 13:46:49 +01:00
if (!$ret && $type->getName() === 'self') {
$doc .= " return \$this;\n";
}
$doc .= "}\n";
if (!$method->getDocComment()) {
2020-01-31 19:29:43 +01:00
Logger::log("{$name} has no PHPDOC!", Logger::FATAL_ERROR);
}
if (!$type) {
2020-01-31 19:29:43 +01:00
Logger::log("{$name} has no return type!", Logger::FATAL_ERROR);
}
2020-10-03 15:04:35 +02:00
$promise = '\\'.Promise::class;
$phpdoc = $method->getDocComment() ?? '';
$phpdoc = \str_replace("@return \\Generator", "@return $promise", $phpdoc);
2020-10-06 20:37:11 +02:00
if ($hasReturnValue && $async && \preg_match("/@return (.*)/", $phpdoc, $matches)) {
$ret = $matches[1];
$new = $ret;
if ($type && !str_contains($ret, '<')) {
$new = '';
if ($type->allowsNull()) {
$new .= '?';
}
if (!$type->isBuiltin()) {
$new .= '\\';
}
$new .= $type->getName() === 'self' ? $this->reflectionClasses['API'] : $type->getName();
}
$phpdoc = \str_replace("@return ".$ret, "@return mixed", $phpdoc);
if (!str_contains($phpdoc, '@psalm-return')) {
$phpdoc = \str_replace("@return ", "@psalm-return $new|$promise<$new>\n * @return ", $phpdoc);
}
}
2020-10-03 15:04:35 +02:00
$phpdoc = \preg_replace(
"/@psalm-return \\\\Generator<(?:[^,]+), (?:[^,]+), (?:[^,]+), (.+)>/",
"@psalm-return $promise<$1>",
$phpdoc
);
$internalDoc['InternalDoc'][$name]['method'] = $phpdoc;
2020-04-05 15:33:01 +02:00
$internalDoc['InternalDoc'][$name]['method'] .= "\n ".\implode("\n ", \explode("\n", $doc));
2019-09-18 20:46:20 +02:00
}
2019-09-02 17:08:36 +02:00
\fwrite($handle, "<?php\n");
\fwrite($handle, "/**\n");
\fwrite($handle, " * This file is automatic generated by build_docs.php file\n");
\fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
\fwrite($handle, " * don't modify manually.\n");
\fwrite($handle, " */\n\n");
2019-12-14 16:47:04 +01:00
\fwrite($handle, "namespace {$this->namespace};\n");
foreach ($internalDoc as $namespace => $methods) {
2019-09-18 20:46:20 +02:00
if ($namespace === 'InternalDoc') {
\fwrite($handle, "\nclass {$namespace} extends APIFactory\n{\n");
} else {
\fwrite($handle, "\ninterface {$namespace}\n{");
}
foreach ($methods as $method => $properties) {
2019-09-18 20:46:20 +02:00
if (isset($properties['method'])) {
\fwrite($handle, $properties['method']);
continue;
}
2019-12-28 16:45:00 +01:00
$title = \implode("\n * ", \explode("\n", $properties['title']));
2019-09-02 17:08:36 +02:00
\fwrite($handle, "\n /**\n");
2019-12-28 16:45:00 +01:00
\fwrite($handle, " * {$title}\n");
2019-09-18 20:46:20 +02:00
\fwrite($handle, " *\n");
if (isset($properties['attr'])) {
2019-09-18 20:46:20 +02:00
\fwrite($handle, " * Parameters: \n");
$longest = [0, 0, 0];
foreach ($properties['attr'] as $name => $param) {
$longest[0] = \max($longest[0], \strlen($param['type']));
$longest[1] = \max($longest[1], \strlen($name));
$longest[2] = \max($longest[2], \strlen($param['description']));
}
foreach ($properties['attr'] as $name => $param) {
2020-04-05 15:33:01 +02:00
$param['type'] = \str_pad('`'.$param['type'].'`', $longest[0] + 2);
$name = \str_pad('**'.$name.'**', $longest[1] + 4);
2019-09-18 20:46:20 +02:00
$param['description'] = \str_pad($param['description'], $longest[2]);
\fwrite($handle, " * * {$param['type']} {$name} - {$param['description']}\n");
}
2019-09-18 20:46:20 +02:00
\fwrite($handle, " * \n");
\fwrite($handle, " * @param array \$params Parameters\n");
2019-09-02 17:08:36 +02:00
\fwrite($handle, " *\n");
}
2019-09-02 17:08:36 +02:00
\fwrite($handle, " * @return {$properties['return']}\n");
\fwrite($handle, " */\n");
\fwrite($handle, " public function {$method}(");
if (isset($properties['attr'])) {
2019-09-18 20:46:20 +02:00
\fwrite($handle, '$params');
}
2019-09-02 17:08:36 +02:00
\fwrite($handle, ");\n");
}
2019-09-02 17:08:36 +02:00
\fwrite($handle, "}\n");
}
2019-09-02 17:08:36 +02:00
\fclose($handle);
}
2018-02-24 17:54:39 +01:00
}