diff --git a/composer.json b/composer.json index f8879a71..7d68653b 100644 --- a/composer.json +++ b/composer.json @@ -57,7 +57,8 @@ "danog/7to5": "^1", "vimeo/psalm": "dev-master", "phpstan/phpstan": "^0.12.14", - "friendsofphp/php-cs-fixer": "^2" + "friendsofphp/php-cs-fixer": "dev-master", + "danog/phpdoc": "^0.1" }, "suggest": { "ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)" @@ -97,9 +98,14 @@ ], "build": [ "@docs", + "@phpdocs", "@cs-fix", "@psalm" ], + "phpdocs": [ + "@phpdocsInternal", + "@phpdocsMain" + ], "check": [ "@cs", "@test" @@ -109,6 +115,8 @@ "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run", "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff", "psalm": "psalm", + "phpdocsMain": "php tools/phpdoc.php", + "phpdocsInternal": "phpdoc docs/docs/PHPInternal", "docs": "php tools/build_docs.php", "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text --config tests/phpunit.xml" } diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php index de5ea867..53503b33 100644 --- a/src/danog/MadelineProto/API.php +++ b/src/danog/MadelineProto/API.php @@ -31,6 +31,60 @@ use danog\MadelineProto\Settings\Logger as SettingsLogger; */ class API extends InternalDoc { + /** + * Release version. + * + * @var string + */ + const RELEASE = MTProto::RELEASE; + /** + * We're not logged in. + * + * @var int + */ + const NOT_LOGGED_IN = MTProto::NOT_LOGGED_IN; + /** + * We're waiting for the login code. + * + * @var int + */ + const WAITING_CODE = MTProto::WAITING_CODE; + /** + * We're waiting for parameters to sign up. + * + * @var int + */ + const WAITING_SIGNUP = MTProto::WAITING_SIGNUP; + /** + * We're waiting for the 2FA password. + * + * @var int + */ + const WAITING_PASSWORD = MTProto::WAITING_PASSWORD; + /** + * We're logged in. + * + * @var int + */ + const LOGGED_IN = MTProto::LOGGED_IN; + /** + * Secret chat was not found. + * + * @var int + */ + const SECRET_EMPTY = MTProto::SECRET_EMPTY; + /** + * Secret chat was requested. + * + * @var int + */ + const SECRET_REQUESTED = MTProto::SECRET_REQUESTED; + /** + * Secret chat was found. + * + * @var int + */ + const SECRET_READY = MTProto::SECRET_READY; use \danog\Serializable; use \danog\MadelineProto\ApiWrappers\Start; use \danog\MadelineProto\ApiWrappers\Templates; diff --git a/src/danog/MadelineProto/AnnotationsBuilder.php b/src/danog/MadelineProto/AnnotationsBuilder.php index 12f7968e..88c8736b 100644 --- a/src/danog/MadelineProto/AnnotationsBuilder.php +++ b/src/danog/MadelineProto/AnnotationsBuilder.php @@ -314,6 +314,8 @@ class AnnotationsBuilder $promise = '\\'.Promise::class; $phpdoc = $method->getDocComment() ?? ''; $phpdoc = \str_replace("@return \\Generator", "@return $promise", $phpdoc); + $phpdoc = \str_replace("@return \\Promise", "@return $promise", $phpdoc); + $phpdoc = \str_replace("@return Promise", "@return $promise", $phpdoc); if ($hasReturnValue && $async && \preg_match("/@return (.*)/", $phpdoc, $matches)) { $ret = $matches[1]; $new = $ret; diff --git a/src/danog/MadelineProto/Db/DbArray.php b/src/danog/MadelineProto/Db/DbArray.php index 6e0a3b2c..b5e8249b 100644 --- a/src/danog/MadelineProto/Db/DbArray.php +++ b/src/danog/MadelineProto/Db/DbArray.php @@ -15,7 +15,7 @@ interface DbArray extends DbType, \ArrayAccess, \Countable /** * Get Array copy. * - * @psalm-return Promise> $value + * @psalm-return Promise> * * @return Promise */ diff --git a/src/danog/MadelineProto/InternalDoc.php b/src/danog/MadelineProto/InternalDoc.php index 501cf2c7..f4a3a629 100644 --- a/src/danog/MadelineProto/InternalDoc.php +++ b/src/danog/MadelineProto/InternalDoc.php @@ -4529,7 +4529,7 @@ class InternalDoc extends APIFactory * * @psalm-suppress InvalidScope * - * @return Promise + * @return \Amp\Promise */ public function after($a, $b) { @@ -4541,7 +4541,7 @@ class InternalDoc extends APIFactory * * @param array<\Generator|Promise> $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function all(array $promises) { @@ -4552,7 +4552,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function any(array $promises) { @@ -4621,7 +4621,7 @@ class InternalDoc extends APIFactory * @template TReturn * @psalm-param \Generator|Promise|TReturn $promise * - * @return Promise + * @return \Amp\Promise * @psalm-return Promise */ public function call($promise) @@ -4637,7 +4637,7 @@ class InternalDoc extends APIFactory * * @psalm-suppress InvalidScope * - * @return Promise|mixed + * @return \Amp\Promise|mixed */ public function callFork($promise, $actual = null, $file = '') { @@ -4904,7 +4904,7 @@ class InternalDoc extends APIFactory * * @param string $string Message to echo * - * @return Promise + * @return \Amp\Promise */ public function echo(string $string) { @@ -4961,7 +4961,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function first(array $promises) { @@ -4977,7 +4977,7 @@ class InternalDoc extends APIFactory * @param ?Promise $token Cancellation token * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails. * - * @return Promise + * @return \Amp\Promise */ public function flock(string $file, int $operation, float $polling = 0.1, ?\Amp\Promise $token = null, $failureCb = null) { @@ -5284,8 +5284,8 @@ class InternalDoc extends APIFactory * user_id?: int, * chat_id?: int, * channel_id?: int, - * InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool}, - * InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool}, + * InputUser?: array{_: string, user_id?: int, access_hash?: mixed, min?: bool}, + * InputChannel?: array{_: string, channel_id: int, access_hash: mixed, min: bool}, * type: string * }> */ @@ -5624,7 +5624,7 @@ class InternalDoc extends APIFactory /** * Start MadelineProto's update handling loop in background. * - * @return Promise + * @return \Amp\Promise */ public function loopFork(array $extra = []) { @@ -5835,7 +5835,7 @@ class InternalDoc extends APIFactory * * @param string $prompt Prompt * - * @return Promise + * @return \Amp\Promise */ public function readLine(string $prompt = '') { @@ -6076,7 +6076,7 @@ class InternalDoc extends APIFactory * * @param int|float $time Number of seconds to sleep for * - * @return Promise + * @return \Amp\Promise */ public function sleep($time) { @@ -6088,7 +6088,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function some(array $promises) { @@ -6153,7 +6153,7 @@ class InternalDoc extends APIFactory * @param \Generator|Promise $promise * @param integer $timeout * - * @return Promise + * @return \Amp\Promise */ public function timeout($promise, int $timeout) { @@ -6177,7 +6177,7 @@ class InternalDoc extends APIFactory * @psalm-param Promise|TGenerator $promise Promise to which the timeout is applied. * @psalm-param TReturnAlt $default * - * @return Promise|Promise + * @return \Amp\Promise|Promise * * @throws \TypeError If $promise is not an instance of \Amp\Promise, \Generator or \React\Promise\PromiseInterface. */ diff --git a/src/danog/MadelineProto/Logger.php b/src/danog/MadelineProto/Logger.php index 890d767f..72725e04 100644 --- a/src/danog/MadelineProto/Logger.php +++ b/src/danog/MadelineProto/Logger.php @@ -33,9 +33,21 @@ use function Amp\ByteStream\getStdout; */ class Logger { + /** + * @internal ANSI foreground color escapes + */ const FOREGROUND = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97]; + /** + * @internal ANSI background color escapes + */ const BACKGROUND = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107]; + /** + * @internal ANSI modifier escapes + */ const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6]; + /** + * @internal ANSI reset modifier escapes + */ const RESET = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28]; /** * Logging mode. @@ -101,61 +113,115 @@ class Logger private PsrLogger $psr; /** * Ultra verbose logging. + * + * @internal */ const ULTRA_VERBOSE = 5; /** * Verbose logging. + * + * @internal */ const VERBOSE = 4; /** * Notice logging. + * + * @internal */ const NOTICE = 3; /** * Warning logging. + * + * @internal */ const WARNING = 2; /** * Error logging. + * + * @internal */ const ERROR = 1; /** * Log only fatal errors. + * + * @internal */ const FATAL_ERROR = 0; /** * Disable logger (DEPRECATED). + * + * @internal + * @deprecated */ const NO_LOGGER = 0; /** * Default logger (syslog). + * + * @internal */ const DEFAULT_LOGGER = 1; /** * File logger. + * + * @internal */ const FILE_LOGGER = 2; /** * Echo logger. + * + * @internal */ const ECHO_LOGGER = 3; /** * Callable logger. + * + * @internal */ const CALLABLE_LOGGER = 4; + /** + * Ultra verbose level. + */ const LEVEL_ULTRA_VERBOSE = self::ULTRA_VERBOSE; + /** + * Verbose level. + */ const LEVEL_VERBOSE = self::VERBOSE; + /** + * Notice level. + */ const LEVEL_NOTICE = self::NOTICE; + /** + * Warning level. + */ const LEVEL_WARNING = self::WARNING; + /** + * Error level. + */ const LEVEL_ERROR = self::ERROR; + /** + * Fatal error level. + */ const LEVEL_FATAL = self::FATAL_ERROR; + /** + * Default logger (syslog). + */ const LOGGER_DEFAULT = self::DEFAULT_LOGGER; + /** + * Echo logger. + */ const LOGGER_ECHO = self::ECHO_LOGGER; + /** + * File logger. + */ const LOGGER_FILE = self::FILE_LOGGER; + /** + * Callable logger. + */ const LOGGER_CALLABLE = self::CALLABLE_LOGGER; + /** * Construct global static logger from MadelineProto settings. * diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 986374db..ad680587 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -95,6 +95,8 @@ class MTProto extends AsyncConstruct implements TLCallback * * Increased every time the default settings array or something big changes * + * @internal + * * @var int */ const V = 147; diff --git a/src/danog/MadelineProto/MTProtoTools/MinDatabase.php b/src/danog/MadelineProto/MTProtoTools/MinDatabase.php index 31576128..d636633b 100644 --- a/src/danog/MadelineProto/MTProtoTools/MinDatabase.php +++ b/src/danog/MadelineProto/MTProtoTools/MinDatabase.php @@ -202,7 +202,8 @@ class MinDatabase implements TLCallback * * @param float|int $id Peer ID * - * @return boolean + * @return Promise + * @psalm-return Promise */ public function hasPeer($id): Promise { diff --git a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php index b1ee3d83..eb708660 100644 --- a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php @@ -489,8 +489,8 @@ trait PeerHandler * user_id?: int, * chat_id?: int, * channel_id?: int, - * InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool}, - * InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool}, + * InputUser?: array{_: string, user_id?: int, access_hash?: mixed, min?: bool}, + * InputChannel?: array{_: string, channel_id: int, access_hash: mixed, min: bool}, * type: string * }> */ diff --git a/src/danog/MadelineProto/PhpDoc/ClassDoc.php b/src/danog/MadelineProto/PhpDoc/ClassDoc.php deleted file mode 100644 index d39b01f5..00000000 --- a/src/danog/MadelineProto/PhpDoc/ClassDoc.php +++ /dev/null @@ -1,137 +0,0 @@ - - */ - private array $properties = []; - /** - * Methods. - * - * @var array - */ - private array $methods = []; - /** - * Constants. - */ - private array $constants = []; - public function __construct(PhpDocBuilder $builder, ReflectionClass $reflectionClass) - { - $this->builder = $builder; - $this->name = $reflectionClass->getName(); - $doc = $reflectionClass->getDocComment(); - if (!$doc) { - Logger::log($reflectionClass->getName()." has no PHPDOC"); - $this->ignore = true; - return; - } - $doc = $this->builder->getFactory()->create($doc); - - parent::__construct($doc, $reflectionClass); - - $tags = $doc->getTags(); - foreach ($tags as $tag) { - if ($tag instanceof Property) { - $this->properties[$tag->getVariableName()] = [ - $tag->getType(), - $tag->getDescription() - ]; - } - if ($tag instanceof InvalidTag && $tag->getName() === 'property') { - [$type, $description] = \explode(" $", $tag->render(), 2); - $description .= ' '; - [$varName, $description] = \explode(" ", $description, 2); - $type = \str_replace('@property ', '', $type); - $description ??= ''; - $this->properties[$varName] = [ - $type, - $description - ]; - } - } - foreach ($reflectionClass->getConstants() as $key => $value) { - $refl = new ReflectionClassConstant($reflectionClass->getName(), $key); - if (!$refl->isPublic()) { - continue; - } - $description = ''; - if ($refl->getDocComment()) { - $docConst = $this->builder->getFactory()->create($refl->getDocComment()); - if ($this->builder->shouldIgnore($refl->getDeclaringClass()->getName())) { - continue; - } - $description .= $docConst->getSummary(); - if ($docConst->getDescription()) { - $description .= "\n\n"; - $description .= $docConst->getDescription(); - } - if ($docConst->getTagsByName('internal')) { - continue; - } - } - $description = \trim($description); - $this->constants[$key] = [ - $value, - $description - ]; - } - - - foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - if (str_starts_with($method->getName(), '__') && $method !== '__construct') { - continue; - } - $this->methods[$method->getName()] = new MethodDoc($this->builder, $method); - } - - $this->methods = \array_filter($this->methods, fn (MethodDoc $doc): bool => !$doc->shouldIgnore()); - } - - public function format(): string - { - $init = parent::format(); - if ($this->constants) { - $init .= "\n"; - $init .= "## Constants\n"; - foreach ($this->constants as $name => [, $description]) { - $description = \trim($description); - $description = \str_replace("\n", "\n ", $description); - $init .= "* {$this->className}::$name: $description\n"; - $init .= "\n"; - } - } - if ($this->methods) { - $init .= "\n"; - $init .= "## Method list:\n"; - foreach ($this->methods as $method) { - $init .= "* `".$method->getSignature()."`\n"; - } - $init .= "\n"; - $init .= "## Methods:\n"; - foreach ($this->methods as $method) { - $init .= $method->format(); - $init .= "\n"; - } - } - if ($this->properties) { - $init .= "## Properties\n"; - foreach ($this->properties as $name => [$type, $description]) { - $init .= "* `\$$name`: `$type` $description"; - } - } - return $init; - } -} diff --git a/src/danog/MadelineProto/PhpDoc/FunctionDoc.php b/src/danog/MadelineProto/PhpDoc/FunctionDoc.php deleted file mode 100644 index a3abacdc..00000000 --- a/src/danog/MadelineProto/PhpDoc/FunctionDoc.php +++ /dev/null @@ -1,25 +0,0 @@ -builder = $builder; - $this->nameGenericDoc = $reflectionClass->getName(); - $doc = $reflectionClass->getDocComment(); - if (!$doc) { - Logger::log($reflectionClass->getName()." has no PHPDOC"); - $this->ignore = true; - return; - } - $doc = $this->builder->getFactory()->create($doc); - - parent::__construct($builder, $reflectionClass); - } -} diff --git a/src/danog/MadelineProto/PhpDoc/GenericDoc.php b/src/danog/MadelineProto/PhpDoc/GenericDoc.php deleted file mode 100644 index 28fc381b..00000000 --- a/src/danog/MadelineProto/PhpDoc/GenericDoc.php +++ /dev/null @@ -1,148 +0,0 @@ - - */ - protected array $seeAlso = []; - /** - * Authors. - * - * @var Author[] - */ - protected array $authors; - /** - * Ignore this class. - */ - protected bool $ignore = false; - /** - * Class name. - */ - protected string $className; - /** - * Class namespace. - */ - protected string $namespace; - public function __construct(DocBlock $doc, $reflectionClass) - { - $this->className = $reflectionClass->getName(); - $this->namespace = \str_replace('/', '\\', \dirname(\str_replace('\\', '/', $this->className))); - $this->title = $doc->getSummary(); - $this->description = $doc->getDescription(); - $tags = $doc->getTags(); - - $this->authors = $this->builder->getAuthors(); - foreach ($tags as $tag) { - if ($tag instanceof Author) { - $this->authors []= $tag; - } - if ($tag instanceof Deprecated) { - $this->ignore = true; - break; - } - if ($tag instanceof Generic && $tag->getName() === 'internal') { - $this->ignore = true; - break; - } - if ($tag instanceof See) { - $this->seeAlso[$tag->getReference()->__toString()] = $tag; - } - } - } - - public function seeAlso(): string - { - $seeAlso = ''; - foreach ($this->seeAlso as $see) { - $ref = $see->getReference(); - if ($ref instanceof Fqsen) { - $ref = (string) $ref; - $ref = $this->builder->resolveTypeAlias($this->className, $ref); - $refExpl = \explode("\\", $ref); - $name = \array_pop($refExpl); - $namespace = \explode('/', $this->namespace); - $count = \count($refExpl); - foreach ($namespace as $k => $name) { - if (isset($refExpl[$k]) && $refExpl[$k] === $name) { - $count--; - } else { - break; - } - } - - $ref = \str_repeat('../', $count) - .\implode('/', \array_slice($refExpl, $count)) - ."/$name.md"; - - $desc = $see->getDescription() ?: $ref; - $seeAlso .= "* [$desc]($ref)\n"; - } - if ($ref instanceof Url) { - $desc = $see->getDescription() ?: $ref; - $seeAlso .= "* [$desc]($ref)\n"; - } - } - if ($seeAlso) { - $seeAlso = "\n#### See also: \n$seeAlso\n\n"; - } - return $seeAlso; - } - public function format(): string - { - $authors = ''; - foreach ($this->authors as $author) { - $authors .= "> Author: $author \n"; - } - $seeAlso = $this->seeAlso(); - return <<name: $this->title - description: $this->description - image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png - --- - # `$this->name`: $this->title - [Back to API index](index.md) - - $authors - - $this->description - $seeAlso - EOF; - } - - public function shouldIgnore(): bool - { - return $this->ignore; - } -} diff --git a/src/danog/MadelineProto/PhpDoc/MethodDoc.php b/src/danog/MadelineProto/PhpDoc/MethodDoc.php deleted file mode 100644 index 9df51993..00000000 --- a/src/danog/MadelineProto/PhpDoc/MethodDoc.php +++ /dev/null @@ -1,119 +0,0 @@ -builder = $phpDocBuilder; - $this->name = $method->getName(); - $doc = $method->getDocComment(); - if (!$doc) { - $this->ignore = true; - if ($method instanceof ReflectionMethod) { - Logger::log($method->getDeclaringClass()->getName().'::'.$method->getName().' has no PHPDOC!'); - } else { - Logger::log($method->getName().' has no PHPDOC!'); - } - return; - } - $doc = $this->builder->getFactory()->create($doc); - - parent::__construct($doc, $method instanceof ReflectionMethod ? $method->getDeclaringClass() : $method); - - foreach ($doc->getTags() as $tag) { - if ($tag instanceof Param && !isset($this->params[$tag->getVariableName()])) { - $this->params[$tag->getVariableName()] = [ - $tag->getType(), - $tag->getDescription() - ]; - } elseif ($tag instanceof Return_ && !isset($this->return)) { - $this->return = $tag; - } elseif ($tag instanceof Generic && $tag->getName() === 'psalm-return') { - $this->psalmReturn = $tag; - } elseif ($tag instanceof Generic && $tag->getName() === 'psalm-param') { - [$type, $description] = \explode(" $", $tag->getDescription(), 2); - $description .= ' '; - [$varName, $description] = \explode(" ", $description, 2); - if (!$description && isset($this->params[$varName])) { - $description = (string) $this->params[$varName][1]; - } else { - $description = new Description($description); - } - $this->psalmParams[$varName] = [ - $type, - $description - ]; - } - } - } - - public function getSignature(): string - { - $sig = $this->name; - $sig .= "("; - foreach ($this->params as $var => [$type, $description]) { - $sig .= $type.' '; - $sig .= "$".$var; - $sig .= ', '; - } - $sig = \trim($sig, ', '); - $sig .= ')'; - if (isset($this->return)) { - $sig .= ': '; - $sig .= $this->builder->resolveTypeAlias($this->className, $this->return); - } - return $sig; - } - public function format(): string - { - $sig = '### `'.$this->getSignature()."`"; - $sig .= "\n\n"; - $sig .= $this->title; - $sig .= "\n"; - $sig .= $this->description; - $sig .= "\n"; - if ($this->psalmParams || $this->params) { - $sig .= "\nParameters:\n"; - foreach ($this->params as $name => [$type, $description]) { - if ($type) { - $type = $this->builder->resolveTypeAlias($this->className, $type); - } - $sig .= "* `\$$name`: `$type` $description \n"; - if (isset($this->psalmParams[$name])) { - [$psalmType] = $this->psalmParams[$name]; - $psalmType = \trim(\str_replace("\n", "\n ", $psalmType)); - - $sig .= " Full type:\n"; - $sig .= " ```\n"; - $sig .= " $psalmType\n"; - $sig .= " ```\n"; - } - } - $sig .= "\n"; - } - if (isset($this->return) && $this->return->getDescription() && $this->return->getDescription()->render()) { - $sig .= "\nReturn value: ".$this->return->getDescription()."\n"; - } - if (isset($this->psalmReturn)) { - $sig .= "\nFully typed return value:\n```\n".$this->psalmReturn."\n```"; - } - $sig .= $this->seeAlso(); - $sig .= "\n"; - return $sig; - } -} diff --git a/src/danog/MadelineProto/PhpDocBuilder.php b/src/danog/MadelineProto/PhpDocBuilder.php deleted file mode 100644 index 08e48321..00000000 --- a/src/danog/MadelineProto/PhpDocBuilder.php +++ /dev/null @@ -1,287 +0,0 @@ -. - * - * @author Daniil Gentili - * @copyright 2016-2020 Daniil Gentili - * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3 - * - * @link https://docs.madelineproto.xyz MadelineProto documentation - */ - -namespace danog\MadelineProto; - -use danog\ClassFinder\ClassFinder; -use danog\MadelineProto\PhpDoc\ClassDoc; -use danog\MadelineProto\PhpDoc\FunctionDoc; -use phpDocumentor\Reflection\DocBlock\Tags\Author; -use phpDocumentor\Reflection\DocBlockFactory; -use ReflectionClass; -use ReflectionFunction; - -class PhpDocBuilder -{ - /** - * Namespace. - */ - private string $namespace; - /** - * Scan mode. - */ - private int $mode; - /** - * Docblock factory. - */ - private DocBlockFactory $factory; - /** - * Authors. - */ - private array $authors = []; - /** - * Classes/interfaces/traits to ignore. - * - * @var ?callable - * @psalm-var null|callable(class-string) - */ - private $ignore; - /** - * Output directory. - */ - private string $output; - /** - * Use map. - * - * array> - */ - private array $useMap = []; - /** - * Create docblock builder. - * - * @param string $namespace Namespace (defaults to package namespace) - * @param int $mode Finder mode, an OR-selection of ClassFinder::ALLOW_* - * - * @return self - */ - public static function fromNamespace(string $namespace = '', int $mode = ClassFinder::ALLOW_ALL): self - { - return new self($namespace, $mode); - } - /** - * Constructor. - * - * @param string $namespace - * @param int $mode - */ - private function __construct(string $namespace, int $mode) - { - $this->factory = DocBlockFactory::createInstance(); - $this->namespace = $namespace; - $this->mode = $mode; - - $appRoot = new \danog\ClassFinder\AppConfig; - $appRoot = $appRoot->getAppRoot(); - $appRoot .= "/composer.json"; - $json = \json_decode(\file_get_contents($appRoot), true); - $authors = $json['authors'] ?? []; - - foreach ($authors as $author) { - $this->authors []= new Author($author['name'], $author['email']); - } - - if (!$this->namespace) { - $namespaces = \array_keys($json['autoload']['psr-4']); - $this->namespace = $namespaces[0]; - foreach ($namespaces as $namespace) { - if (\strlen($namespace) && \strlen($namespace) < \strlen($this->namespace)) { - $this->namespace = $namespace; - } - } - } - } - /** - * Set filter to ignore certain classes. - * - * @param callable $ignore - * - * @psalm-param callable(class-string) $ignore - * - * @return self - */ - public function setFilter(callable $ignore): self - { - $this->ignore = $ignore; - - return $this; - } - /** - * Set output directory. - * - * @param string $output Output directory - * - * @return self - */ - public function setOutput(string $output): self - { - $this->output = $output; - - return $this; - } - /** - * Run documentor. - * - * @return self - */ - public function run(): self - { - $classes = ClassFinder::getClassesInNamespace($this->namespace, $this->mode | ClassFinder::RECURSIVE_MODE); - foreach ($classes as $class) { - $this->addTypeAliases($class); - } - foreach ($classes as $class) { - if ($this->ignore && $this->shouldIgnore($class)) { - continue; - } - $class = \function_exists($class) - ? new ReflectionFunction($class) - : new ReflectionClass($class); - $this->generate($class); - } - - return $this; - } - /** - * Resolve type alias. - * - * @internal - * - * @param string $fromClass Class from where this function is called - * @param string $name Name to resolve - * - * @psalm-param class-string $fromClass Class from where this function is called - * @psalm-param class-string $name Name to resolve - * - * @return string - */ - public function resolveTypeAlias(string $fromClass, string $name): string - { - return $this->useMap[$fromClass][$name] ?? $name; - } - /** - * Add type alias. - * - * @param string $class - * - * @psalm-param class-string $class - * - * @return void - */ - private function addTypeAliases(string $class) - { - $reflectionClass = \function_exists($class) - ? new ReflectionFunction($class) - : new ReflectionClass($class); - $payload = \file_get_contents($reflectionClass->getFileName()); - \preg_match_all("/use *(function)? +(.*?)(?: +as +(.+))? *;/", $payload, $matches, PREG_SET_ORDER|PREG_UNMATCHED_AS_NULL); - foreach ($matches as [, $function, $import, $alias]) { - $import = "\\$import"; - $alias ??= \basename(\str_replace('\\', '/', $import)); - $this->useMap[$class][$alias] = $import; - $this->useMap[$class]['\\'.$alias] = $import; - } - } - /** - * Create directory recursively. - * - * @param string $file - * @return string - */ - private static function createDir(string $file): string - { - $dir = \dirname($file); - if (!\file_exists($dir)) { - self::createDir($dir); - \mkdir($dir); - } - return $file; - } - - /** - * Generate documentation for class. - * - * @param ReflectionClass|ReflectionFunction $class Class - * - * @return void - */ - private function generate($class): void - { - $name = $class->getName(); - $fName = $this->output; - $fName .= \str_replace('\\', DIRECTORY_SEPARATOR, $name); - $fName .= '.md'; - - $class = $class instanceof ReflectionFunction - ? new FunctionDoc($this, $class) - : new ClassDoc($this, $class); - if ($class->shouldIgnore()) { - return; - } - $class = $class->format(); - - $handle = \fopen(self::createDir($fName), 'w+'); - \fwrite($handle, $class); - \fclose($handle); - } - - /** - * Get docblock factory. - * - * @internal - * - * @return DocBlockFactory - */ - public function getFactory(): DocBlockFactory - { - return $this->factory; - } - - /** - * Whether should ignore trait/class/interface. - * - * @return bool - */ - public function shouldIgnore(string $class): bool - { - return !($this->ignore)($class); - } - - /** - * Get authors. - * - * @return Author[] - */ - public function getAuthors(): array - { - return $this->authors; - } - - /** - * Set authors. - * - * @param Author[] $authors Authors - * - * @return self - */ - public function setAuthors(array $authors): self - { - $this->authors = $authors; - - return $this; - } -} diff --git a/src/danog/MadelineProto/Stream/BufferedStreamInterface.php b/src/danog/MadelineProto/Stream/BufferedStreamInterface.php index 195b1a3d..097548aa 100644 --- a/src/danog/MadelineProto/Stream/BufferedStreamInterface.php +++ b/src/danog/MadelineProto/Stream/BufferedStreamInterface.php @@ -33,7 +33,8 @@ interface BufferedStreamInterface extends StreamInterface * * @param int $length Length of payload, as detected by this layer * - * @return Promise + * @return Promise + * @psalm-return Promise */ public function getReadBuffer(&$length): Promise; /** diff --git a/src/danog/MadelineProto/TON/InternalDoc.php b/src/danog/MadelineProto/TON/InternalDoc.php index 766178ad..e84d1be4 100644 --- a/src/danog/MadelineProto/TON/InternalDoc.php +++ b/src/danog/MadelineProto/TON/InternalDoc.php @@ -920,7 +920,7 @@ class InternalDoc extends APIFactory * * @psalm-suppress InvalidScope * - * @return Promise + * @return \Amp\Promise */ public function after($a, $b) { @@ -932,7 +932,7 @@ class InternalDoc extends APIFactory * * @param array<\Generator|Promise> $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function all(array $promises) { @@ -943,7 +943,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function any(array $promises) { @@ -1001,7 +1001,7 @@ class InternalDoc extends APIFactory * @template TReturn * @psalm-param \Generator|Promise|TReturn $promise * - * @return Promise + * @return \Amp\Promise * @psalm-return Promise */ public function call($promise) @@ -1017,7 +1017,7 @@ class InternalDoc extends APIFactory * * @psalm-suppress InvalidScope * - * @return Promise|mixed + * @return \Amp\Promise|mixed */ public function callFork($promise, $actual = null, $file = '') { @@ -1050,7 +1050,7 @@ class InternalDoc extends APIFactory * * @param string $string Message to echo * - * @return Promise + * @return \Amp\Promise */ public function echo(string $string) { @@ -1072,7 +1072,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function first(array $promises) { @@ -1088,7 +1088,7 @@ class InternalDoc extends APIFactory * @param ?Promise $token Cancellation token * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails. * - * @return Promise + * @return \Amp\Promise */ public function flock(string $file, int $operation, float $polling = 0.1, ?\Amp\Promise $token = null, $failureCb = null) { @@ -1378,7 +1378,7 @@ class InternalDoc extends APIFactory * * @param string $prompt Prompt * - * @return Promise + * @return \Amp\Promise */ public function readLine(string $prompt = '') { @@ -1442,7 +1442,7 @@ class InternalDoc extends APIFactory * * @param int|float $time Number of seconds to sleep for * - * @return Promise + * @return \Amp\Promise */ public function sleep($time) { @@ -1454,7 +1454,7 @@ class InternalDoc extends APIFactory * * @param array $promises Promises * - * @return Promise + * @return \Amp\Promise */ public function some(array $promises) { @@ -1466,7 +1466,7 @@ class InternalDoc extends APIFactory * @param \Generator|Promise $promise * @param integer $timeout * - * @return Promise + * @return \Amp\Promise */ public function timeout($promise, int $timeout) { @@ -1490,7 +1490,7 @@ class InternalDoc extends APIFactory * @psalm-param Promise|TGenerator $promise Promise to which the timeout is applied. * @psalm-param TReturnAlt $default * - * @return Promise|Promise + * @return \Amp\Promise|Promise * * @throws \TypeError If $promise is not an instance of \Amp\Promise, \Generator or \React\Promise\PromiseInterface. */ diff --git a/tools/phpdoc.php b/tools/phpdoc.php index 8664723e..f864d7c6 100644 --- a/tools/phpdoc.php +++ b/tools/phpdoc.php @@ -23,7 +23,6 @@ use danog\MadelineProto\MTProtoTools\PasswordCalculator; use danog\MadelineProto\MTProtoTools\ReferenceDatabase; use danog\MadelineProto\MTProtoTools\UpdatesState; use danog\MadelineProto\NothingInTheSocketException; -use danog\MadelineProto\PhpDocBuilder; use danog\MadelineProto\RSA; use danog\MadelineProto\Serialization; use danog\MadelineProto\SessionPaths; @@ -39,6 +38,7 @@ use danog\MadelineProto\TON\APIFactory as TONAPIFactory; use danog\MadelineProto\TON\InternalDoc as TONInternalDoc; use danog\MadelineProto\TON\Lite; use danog\MadelineProto\VoIP; +use danog\PhpDoc\PhpDocBuilder; require 'vendor/autoload.php'; @@ -100,6 +100,7 @@ $filter = function (string $class) use ($ignore): bool { || str_starts_with($class, 'danog\\MadelineProto\\MTProto\\') || str_starts_with($class, 'danog\\MadelineProto\\MTProtoSession\\') || str_starts_with($class, 'danog\\MadelineProto\\PhpDoc\\') + || str_starts_with($class, 'danog\\MadelineProto\\Stream\\') || str_starts_with($class, 'danog\\MadelineProto\\Db\\NullCache')) { return false; }