diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 45c4ac66..dfe00ab7 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -27,5 +27,5 @@ jobs: php-version: 8.0 coverage: none - - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress --ignore-platform-reqs + - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress - run: php temp/coding-standard/ecs check diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 266902db..e87ca57d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.2', '7.3', '7.4', '8.0', '8.1'] + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] fail-fast: false diff --git a/composer.json b/composer.json index 388d21cf..3d6dbe3e 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.2", + "php": ">=7.2 <8.3", "nette/utils": "^3.1.2" }, "require-dev": { diff --git a/readme.md b/readme.md index d3cfe485..4e089ee8 100644 --- a/readme.md +++ b/readme.md @@ -590,14 +590,14 @@ To simplify a fully qualified class, function or constant name according to the ```php echo $namespace->simplifyName('Foo\Bar'); // 'Bar', because 'Foo' is current namespace -echo $namespace->simplifyName('iter\range', $namespace::NAME_FUNCTION); // 'range', because of the defined use-statement +echo $namespace->simplifyName('iter\range', $namespace::NameFunction); // 'range', because of the defined use-statement ``` Conversely, you can convert a simplified class, function or constant name to a fully qualified one using the `resolveName` method: ```php echo $namespace->resolveName('Bar'); // 'Foo\Bar' -echo $namespace->resolveName('range', $namespace::NAME_FUNCTION); // 'iter\range' +echo $namespace->resolveName('range', $namespace::NameFunction); // 'iter\range' ``` Class Names Resolving diff --git a/src/PhpGenerator/ClassType.php b/src/PhpGenerator/ClassType.php index ec2f38b2..7b89fbf7 100644 --- a/src/PhpGenerator/ClassType.php +++ b/src/PhpGenerator/ClassType.php @@ -31,9 +31,14 @@ final class ClassType TYPE_ENUM = 'enum'; public const - VISIBILITY_PUBLIC = 'public', - VISIBILITY_PROTECTED = 'protected', - VISIBILITY_PRIVATE = 'private'; + VisibilityPublic = 'public', + VisibilityProtected = 'protected', + VisibilityPrivate = 'private'; + + public const + VISIBILITY_PUBLIC = self::VisibilityPublic, + VISIBILITY_PROTECTED = self::VisibilityProtected, + VISIBILITY_PRIVATE = self::VisibilityPrivate; /** @var PhpNamespace|null */ private $namespace; @@ -155,7 +160,7 @@ public function getNamespace(): ?PhpNamespace /** @return static */ public function setName(?string $name): self { - if ($name !== null && (!Helpers::isIdentifier($name) || isset(Helpers::KEYWORDS[strtolower($name)]))) { + if ($name !== null && (!Helpers::isIdentifier($name) || isset(Helpers::Keywords[strtolower($name)]))) { throw new Nette\InvalidArgumentException("Value '$name' is not valid class name."); } @@ -662,6 +667,7 @@ private function validateNames(array $names): void public function __clone() { $clone = function ($item) { return clone $item; }; + $this->traits = array_map($clone, $this->traits); $this->cases = array_map($clone, $this->cases); $this->consts = array_map($clone, $this->consts); $this->properties = array_map($clone, $this->properties); diff --git a/src/PhpGenerator/Dumper.php b/src/PhpGenerator/Dumper.php index ec6766af..3af2e353 100644 --- a/src/PhpGenerator/Dumper.php +++ b/src/PhpGenerator/Dumper.php @@ -17,7 +17,7 @@ */ final class Dumper { - private const INDENT_LENGTH = 4; + private const IndentLength = 4; /** @var int */ public $maxDepth = 50; @@ -110,7 +110,7 @@ private function dumpArray(array &$var, array $parents, int $level, int $column) if (empty($var)) { return '[]'; - } elseif ($level > $this->maxDepth || in_array($var, $parents ?? [], true)) { + } elseif ($level > $this->maxDepth || in_array($var, $parents, true)) { throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.'); } @@ -135,7 +135,7 @@ private function dumpArray(array &$var, array $parents, int $level, int $column) } array_pop($parents); - $wrap = strpos($outInline, "\n") !== false || $level * self::INDENT_LENGTH + $column + strlen($outInline) + 3 > $this->wrapLength; // 3 = [], + $wrap = strpos($outInline, "\n") !== false || $level * self::IndentLength + $column + strlen($outInline) + 3 > $this->wrapLength; // 3 = [], return '[' . ($wrap ? $outWrapped : $outInline) . ']'; } @@ -170,7 +170,7 @@ private function dumpObject($var, array $parents, int $level): string $arr = (array) $var; $space = str_repeat($this->indentation, $level); - if ($level > $this->maxDepth || in_array($var, $parents ?? [], true)) { + if ($level > $this->maxDepth || in_array($var, $parents, true)) { throw new Nette\InvalidArgumentException('Nesting level too deep or recursive dependency.'); } diff --git a/src/PhpGenerator/Extractor.php b/src/PhpGenerator/Extractor.php index 5653e81a..d7eba32f 100644 --- a/src/PhpGenerator/Extractor.php +++ b/src/PhpGenerator/Extractor.php @@ -62,8 +62,7 @@ public function extractMethodBodies(string $className): array { $nodeFinder = new NodeFinder; $classNode = $nodeFinder->findFirst($this->statements, function (Node $node) use ($className) { - return ($node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_) - && $node->namespacedName->toString() === $className; + return $node instanceof Node\Stmt\ClassLike && $node->namespacedName->toString() === $className; }); $res = []; @@ -100,14 +99,14 @@ private function getReformattedContents(array $statements, int $level): string private function prepareReplacements(array $statements): array { - $start = $statements[0]->getStartFilePos(); + $start = $this->getNodeStartPos($statements[0]); $replacements = []; (new NodeFinder)->find($statements, function (Node $node) use (&$replacements, $start) { if ($node instanceof Node\Name\FullyQualified) { if ($node->getAttribute('originalName') instanceof Node\Name) { $of = $node->getAttribute('parent') instanceof Node\Expr\ConstFetch - ? PhpNamespace::NAME_CONSTANT - : ($node->getAttribute('parent') instanceof Node\Expr\FuncCall ? PhpNamespace::NAME_FUNCTION : PhpNamespace::NAME_NORMAL); + ? PhpNamespace::NameConstant + : ($node->getAttribute('parent') instanceof Node\Expr\FuncCall ? PhpNamespace::NameFunction : PhpNamespace::NameNormal); $replacements[] = [ $node->getStartFilePos() - $start, $node->getEndFilePos() - $start, @@ -164,6 +163,9 @@ public function extractAll(): PhpFile $phpFile = new PhpFile; $namespace = ''; $visitor = new class extends PhpParser\NodeVisitorAbstract { + public $callback; + + public function enterNode(Node $node) { return ($this->callback)($node); @@ -222,9 +224,9 @@ public function enterNode(Node $node) private function addUseToNamespace(Node\Stmt\Use_ $node, PhpNamespace $namespace): void { $of = [ - $node::TYPE_NORMAL => PhpNamespace::NAME_NORMAL, - $node::TYPE_FUNCTION => PhpNamespace::NAME_FUNCTION, - $node::TYPE_CONSTANT => PhpNamespace::NAME_CONSTANT, + $node::TYPE_NORMAL => PhpNamespace::NameNormal, + $node::TYPE_FUNCTION => PhpNamespace::NameFunction, + $node::TYPE_CONSTANT => PhpNamespace::NameConstant, ][$node->type]; foreach ($node->uses as $use) { $namespace->addUse($use->name->toString(), $use->alias ? $use->alias->toString() : null, $of); @@ -308,12 +310,7 @@ private function addPropertyToClass(ClassType $class, Node\Stmt\Property $node): foreach ($node->props as $item) { $prop = $class->addProperty($item->name->toString()); $prop->setStatic($node->isStatic()); - if ($node->isPrivate()) { - $prop->setPrivate(); - } elseif ($node->isProtected()) { - $prop->setProtected(); - } - + $prop->setVisibility($this->toVisibility($node->flags)); $prop->setType($node->type ? $this->toPhp($node->type) : null); if ($item->default) { $prop->setValue(new Literal($this->getReformattedContents([$item->default], 1))); @@ -331,12 +328,7 @@ private function addMethodToClass(ClassType $class, Node\Stmt\ClassMethod $node) $method->setAbstract($node->isAbstract()); $method->setFinal($node->isFinal()); $method->setStatic($node->isStatic()); - if ($node->isPrivate()) { - $method->setPrivate(); - } elseif ($node->isProtected()) { - $method->setProtected(); - } - + $method->setVisibility($this->toVisibility($node->flags)); $this->setupFunction($method, $node); } @@ -346,12 +338,7 @@ private function addConstantToClass(ClassType $class, Node\Stmt\ClassConst $node foreach ($node->consts as $item) { $value = $this->getReformattedContents([$item->value], 1); $const = $class->addConstant($item->name->toString(), new Literal($value)); - if ($node->isPrivate()) { - $const->setPrivate(); - } elseif ($node->isProtected()) { - $const->setProtected(); - } - + $const->setVisibility($this->toVisibility($node->flags)); $const->setFinal(method_exists($node, 'isFinal') && $node->isFinal()); $this->addCommentAndAttributes($const, $node); } @@ -399,8 +386,12 @@ private function setupFunction($function, Node\FunctionLike $node): void { $function->setReturnReference($node->returnsByRef()); $function->setReturnType($node->getReturnType() ? $this->toPhp($node->getReturnType()) : null); - foreach ($node->params as $item) { - $param = $function->addParameter($item->var->name); + foreach ($node->getParams() as $item) { + $visibility = $this->toVisibility($item->flags); + $isReadonly = (bool) ($item->flags & Node\Stmt\Class_::MODIFIER_READONLY); + $param = $visibility + ? ($function->addPromotedParameter($item->var->name))->setVisibility($visibility)->setReadonly($isReadonly) + : $function->addParameter($item->var->name); $param->setType($item->type ? $this->toPhp($item->type) : null); $param->setReference($item->byRef); $function->setVariadic($item->variadic); @@ -412,12 +403,25 @@ private function setupFunction($function, Node\FunctionLike $node): void } $this->addCommentAndAttributes($function, $node); - if ($node->stmts) { - $function->setBody($this->getReformattedContents($node->stmts, 2)); + if ($node->getStmts()) { + $function->setBody($this->getReformattedContents($node->getStmts(), 2)); } } + private function toVisibility(int $flags): ?string + { + if ($flags & Node\Stmt\Class_::MODIFIER_PUBLIC) { + return ClassType::VisibilityPublic; + } elseif ($flags & Node\Stmt\Class_::MODIFIER_PROTECTED) { + return ClassType::VisibilityProtected; + } elseif ($flags & Node\Stmt\Class_::MODIFIER_PRIVATE) { + return ClassType::VisibilityPrivate; + } + return null; + } + + private function toPhp($value): string { return $this->printer->prettyPrint([$value]); @@ -426,7 +430,15 @@ private function toPhp($value): string private function getNodeContents(Node ...$nodes): string { - $start = $nodes[0]->getStartFilePos(); + $start = $this->getNodeStartPos($nodes[0]); return substr($this->code, $start, end($nodes)->getEndFilePos() - $start + 1); } + + + private function getNodeStartPos(Node $node): int + { + return ($comments = $node->getComments()) + ? $comments[0]->getStartFilePos() + : $node->getStartFilePos(); + } } diff --git a/src/PhpGenerator/Factory.php b/src/PhpGenerator/Factory.php index 176037c3..b4ab7a1f 100644 --- a/src/PhpGenerator/Factory.php +++ b/src/PhpGenerator/Factory.php @@ -28,7 +28,8 @@ public function fromClassReflection( \ReflectionClass $from, bool $withBodies = false, bool $materializeTraits = true - ): ClassType { + ): ClassType + { if ($withBodies && $from->isAnonymous()) { throw new Nette\NotSupportedException('The $withBodies parameter cannot be used for anonymous functions.'); } @@ -63,7 +64,7 @@ public function fromClassReflection( } $class->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); - $class->setAttributes(self::getAttributes($from)); + $class->setAttributes($this->getAttributes($from)); if ($from->getParentClass()) { $class->setExtends($from->getParentClass()->name); $class->setImplements(array_diff($class->getImplements(), $from->getParentClass()->getInterfaceNames())); @@ -153,7 +154,7 @@ public function fromMethodReflection(\ReflectionMethod $from): Method $method->setReturnReference($from->returnsReference()); $method->setVariadic($from->isVariadic()); $method->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); - $method->setAttributes(self::getAttributes($from)); + $method->setAttributes($this->getAttributes($from)); if ($from->getReturnType() instanceof \ReflectionNamedType) { $method->setReturnType($from->getReturnType()->getName()); $method->setReturnNullable($from->getReturnType()->allowsNull()); @@ -179,7 +180,7 @@ public function fromFunctionReflection(\ReflectionFunction $from, bool $withBody $function->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); } - $function->setAttributes(self::getAttributes($from)); + $function->setAttributes($this->getAttributes($from)); if ($from->getReturnType() instanceof \ReflectionNamedType) { $function->setReturnType($from->getReturnType()->getName()); $function->setReturnNullable($from->getReturnType()->allowsNull()); @@ -207,8 +208,8 @@ public function fromCallable(callable $from) { $ref = Nette\Utils\Callback::toReflection($from); return $ref instanceof \ReflectionMethod - ? self::fromMethodReflection($ref) - : self::fromFunctionReflection($ref); + ? $this->fromMethodReflection($ref) + : $this->fromFunctionReflection($ref); } @@ -245,7 +246,7 @@ public function fromParameterReflection(\ReflectionParameter $from): Parameter $param->setNullable($param->isNullable() && $param->getDefaultValue() !== null); } - $param->setAttributes(self::getAttributes($from)); + $param->setAttributes($this->getAttributes($from)); return $param; } @@ -257,7 +258,7 @@ public function fromConstantReflection(\ReflectionClassConstant $from): Constant $const->setVisibility($this->getVisibility($from)); $const->setFinal(PHP_VERSION_ID >= 80100 ? $from->isFinal() : false); $const->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); - $const->setAttributes(self::getAttributes($from)); + $const->setAttributes($this->getAttributes($from)); return $const; } @@ -267,7 +268,7 @@ public function fromCaseReflection(\ReflectionClassConstant $from): EnumCase $const = new EnumCase($from->name); $const->setValue($from->getValue()->value ?? null); $const->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); - $const->setAttributes(self::getAttributes($from)); + $const->setAttributes($this->getAttributes($from)); return $const; } @@ -297,14 +298,14 @@ public function fromPropertyReflection(\ReflectionProperty $from): Property } $prop->setComment(Helpers::unformatDocComment((string) $from->getDocComment())); - $prop->setAttributes(self::getAttributes($from)); + $prop->setAttributes($this->getAttributes($from)); return $prop; } public function fromObject(object $obj): Literal { - return new Literal('new ' . get_class($obj) . '(/* unknown */)'); + return new Literal('new \\' . get_class($obj) . '(/* unknown */)'); } @@ -348,8 +349,8 @@ private function getAttributes($from): array private function getVisibility($from): string { return $from->isPrivate() - ? ClassType::VISIBILITY_PRIVATE - : ($from->isProtected() ? ClassType::VISIBILITY_PROTECTED : ClassType::VISIBILITY_PUBLIC); + ? ClassType::VisibilityPrivate + : ($from->isProtected() ? ClassType::VisibilityProtected : ClassType::VisibilityPublic); } diff --git a/src/PhpGenerator/Helpers.php b/src/PhpGenerator/Helpers.php index 74c61b1d..288a6adf 100644 --- a/src/PhpGenerator/Helpers.php +++ b/src/PhpGenerator/Helpers.php @@ -19,9 +19,9 @@ final class Helpers { use Nette\StaticClass; - public const PHP_IDENT = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'; + public const ReIdentifier = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'; - public const KEYWORDS = [ + public const Keywords = [ // built-in types 'string' => 1, 'int' => 1, 'float' => 1, 'bool' => 1, 'array' => 1, 'object' => 1, 'callable' => 1, 'iterable' => 1, 'void' => 1, 'null' => 1, 'mixed' => 1, 'false' => 1, @@ -37,16 +37,21 @@ final class Helpers 'endforeach' => 1, 'declare' => 1, 'enddeclare' => 1, 'as' => 1, 'try' => 1, 'catch' => 1, 'finally' => 1, 'throw' => 1, 'use' => 1, 'insteadof' => 1, 'global' => 1, 'var' => 1, 'unset' => 1, 'isset' => 1, 'empty' => 1, 'continue' => 1, 'goto' => 1, 'function' => 1, 'const' => 1, 'return' => 1, 'print' => 1, 'yield' => 1, 'list' => 1, - 'switch' => 1, 'endswitch' => 1, 'case' => 1, 'default' => 1, 'break' => 1, 'array' => 1, 'callable' => 1, + 'switch' => 1, 'endswitch' => 1, 'case' => 1, 'default' => 1, 'break' => 1, 'extends' => 1, 'implements' => 1, 'namespace' => 1, 'trait' => 1, 'interface' => 1, 'class' => 1, '__CLASS__' => 1, '__TRAIT__' => 1, '__FUNCTION__' => 1, '__METHOD__' => 1, '__LINE__' => 1, '__FILE__' => 1, '__DIR__' => 1, - '__NAMESPACE__' => 1, 'fn' => 1, 'match' => 1, 'enum' => 1, 'static' => 1, 'abstract' => 1, 'final' => 1, + '__NAMESPACE__' => 1, 'fn' => 1, 'match' => 1, 'enum' => 1, 'abstract' => 1, 'final' => 1, 'private' => 1, 'protected' => 1, 'public' => 1, 'readonly' => 1, // additional reserved class names 'true' => 1, ]; + /** @deprecated */ + public const + PHP_IDENT = self::ReIdentifier, + KEYWORDS = self::Keywords; + /** @deprecated use (new Nette\PhpGenerator\Dumper)->dump() */ public static function dump($var): string @@ -83,9 +88,9 @@ public static function formatDocComment(string $content): string } - public static function tagName(string $name, string $of = PhpNamespace::NAME_NORMAL): string + public static function tagName(string $name, string $of = PhpNamespace::NameNormal): string { - return isset(self::KEYWORDS[strtolower($name)]) + return isset(self::Keywords[strtolower($name)]) ? $name : "/*($of*/$name"; } @@ -118,13 +123,13 @@ public static function unindent(string $s, int $level = 1): string public static function isIdentifier($value): bool { - return is_string($value) && preg_match('#^' . self::PHP_IDENT . '$#D', $value); + return is_string($value) && preg_match('#^' . self::ReIdentifier . '$#D', $value); } public static function isNamespaceIdentifier($value, bool $allowLeadingSlash = false): bool { - $re = '#^' . ($allowLeadingSlash ? '\\\\?' : '') . self::PHP_IDENT . '(\\\\' . self::PHP_IDENT . ')*$#D'; + $re = '#^' . ($allowLeadingSlash ? '\\\\?' : '') . self::ReIdentifier . '(\\\\' . self::ReIdentifier . ')*$#D'; return is_string($value) && preg_match($re, $value); } diff --git a/src/PhpGenerator/Method.php b/src/PhpGenerator/Method.php index c8b1d779..de8bd797 100644 --- a/src/PhpGenerator/Method.php +++ b/src/PhpGenerator/Method.php @@ -138,7 +138,7 @@ public function addPromotedParameter(string $name, $defaultValue = null): Promot /** @throws Nette\InvalidStateException */ public function validate(): void { - if ($this->abstract && ($this->final || $this->visibility === ClassType::VISIBILITY_PRIVATE)) { + if ($this->abstract && ($this->final || $this->visibility === ClassType::VisibilityPrivate)) { throw new Nette\InvalidStateException("Method $this->name() cannot be abstract and final or private at the same time."); } } diff --git a/src/PhpGenerator/PhpFile.php b/src/PhpGenerator/PhpFile.php index c06ad451..4c15cd28 100644 --- a/src/PhpGenerator/PhpFile.php +++ b/src/PhpGenerator/PhpFile.php @@ -137,7 +137,7 @@ public function getFunctions(): array /** @return static */ - public function addUse(string $name, ?string $alias = null, string $of = PhpNamespace::NAME_NORMAL): self + public function addUse(string $name, ?string $alias = null, string $of = PhpNamespace::NameNormal): self { $this->addNamespace('')->addUse($name, $alias, $of); return $this; diff --git a/src/PhpGenerator/PhpNamespace.php b/src/PhpGenerator/PhpNamespace.php index f0171019..8190ba66 100644 --- a/src/PhpGenerator/PhpNamespace.php +++ b/src/PhpGenerator/PhpNamespace.php @@ -26,9 +26,14 @@ final class PhpNamespace use Nette\SmartObject; public const - NAME_NORMAL = 'n', - NAME_FUNCTION = 'f', - NAME_CONSTANT = 'c'; + NameNormal = 'n', + NameFunction = 'f', + NameConstant = 'c'; + + public const + NAME_NORMAL = self::NameNormal, + NAME_FUNCTION = self::NameFunction, + NAME_CONSTANT = self::NameConstant; /** @var string */ private $name; @@ -38,9 +43,9 @@ final class PhpNamespace /** @var string[][] */ private $aliases = [ - self::NAME_NORMAL => [], - self::NAME_FUNCTION => [], - self::NAME_CONSTANT => [], + self::NameNormal => [], + self::NameFunction => [], + self::NameConstant => [], ]; /** @var ClassType[] */ @@ -94,21 +99,21 @@ public function getBracketedSyntax(): bool * @throws InvalidStateException * @return static */ - public function addUse(string $name, ?string $alias = null, string $of = self::NAME_NORMAL): self + public function addUse(string $name, ?string $alias = null, string $of = self::NameNormal): self { if ( !Helpers::isNamespaceIdentifier($name, true) - || (Helpers::isIdentifier($name) && isset(Helpers::KEYWORDS[strtolower($name)])) + || (Helpers::isIdentifier($name) && isset(Helpers::Keywords[strtolower($name)])) ) { throw new Nette\InvalidArgumentException("Value '$name' is not valid class/function/constant name."); - } elseif ($alias && (!Helpers::isIdentifier($alias) || isset(Helpers::KEYWORDS[strtolower($alias)]))) { + } elseif ($alias && (!Helpers::isIdentifier($alias) || isset(Helpers::Keywords[strtolower($alias)]))) { throw new Nette\InvalidArgumentException("Value '$alias' is not valid alias."); } $name = ltrim($name, '\\'); $aliases = array_change_key_case($this->aliases[$of]); - $used = [self::NAME_NORMAL => $this->classes, self::NAME_FUNCTION => $this->functions, self::NAME_CONSTANT => []][$of]; + $used = [self::NameNormal => $this->classes, self::NameFunction => $this->functions, self::NameConstant => []][$of]; if ($alias === null) { $base = Helpers::extractShortName($name); @@ -134,22 +139,32 @@ public function addUse(string $name, ?string $alias = null, string $of = self::N } + public function removeUse(string $name, string $of = self::NameNormal): void + { + foreach ($this->aliases[$of] as $alias => $item) { + if (strcasecmp($item, $name) === 0) { + unset($this->aliases[$of][$alias]); + } + } + } + + /** @return static */ public function addUseFunction(string $name, ?string $alias = null): self { - return $this->addUse($name, $alias, self::NAME_FUNCTION); + return $this->addUse($name, $alias, self::NameFunction); } /** @return static */ public function addUseConstant(string $name, ?string $alias = null): self { - return $this->addUse($name, $alias, self::NAME_CONSTANT); + return $this->addUse($name, $alias, self::NameConstant); } /** @return string[] */ - public function getUses(string $of = self::NAME_NORMAL): array + public function getUses(string $of = self::NameNormal): array { asort($this->aliases[$of]); return array_filter( @@ -167,16 +182,16 @@ public function unresolveName(string $name): string } - public function resolveName(string $name, string $of = self::NAME_NORMAL): string + public function resolveName(string $name, string $of = self::NameNormal): string { - if (isset(Helpers::KEYWORDS[strtolower($name)]) || $name === '') { + if (isset(Helpers::Keywords[strtolower($name)]) || $name === '') { return $name; } elseif ($name[0] === '\\') { return substr($name, 1); } $aliases = array_change_key_case($this->aliases[$of]); - if ($of !== self::NAME_NORMAL) { + if ($of !== self::NameNormal) { return $aliases[strtolower($name)] ?? $this->resolveName(Helpers::extractNamespace($name) . '\\') . Helpers::extractShortName($name); } @@ -188,21 +203,21 @@ public function resolveName(string $name, string $of = self::NAME_NORMAL): strin } - public function simplifyType(string $type, string $of = self::NAME_NORMAL): string + public function simplifyType(string $type, string $of = self::NameNormal): string { return preg_replace_callback('~[\w\x7f-\xff\\\\]+~', function ($m) use ($of) { return $this->simplifyName($m[0], $of); }, $type); } - public function simplifyName(string $name, string $of = self::NAME_NORMAL): string + public function simplifyName(string $name, string $of = self::NameNormal): string { - if (isset(Helpers::KEYWORDS[strtolower($name)]) || $name === '') { + if (isset(Helpers::Keywords[strtolower($name)]) || $name === '') { return $name; } $name = ltrim($name, '\\'); - if ($of !== self::NAME_NORMAL) { + if ($of !== self::NameNormal) { foreach ($this->aliases[$of] as $alias => $original) { if (strcasecmp($original, $name) === 0) { return $alias; @@ -247,7 +262,7 @@ public function add(ClassType $class): self } $lower = strtolower($name); - if ($orig = array_change_key_case($this->aliases[self::NAME_NORMAL])[$lower] ?? null) { + if ($orig = array_change_key_case($this->aliases[self::NameNormal])[$lower] ?? null) { throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig."); } @@ -291,7 +306,7 @@ public function removeClass(string $name): self public function addFunction(string $name): GlobalFunction { $lower = strtolower($name); - if ($orig = array_change_key_case($this->aliases[self::NAME_FUNCTION])[$lower] ?? null) { + if ($orig = array_change_key_case($this->aliases[self::NameFunction])[$lower] ?? null) { throw new Nette\InvalidStateException("Name '$name' used already as alias for $orig."); } diff --git a/src/PhpGenerator/Printer.php b/src/PhpGenerator/Printer.php index 668d1ea3..eb8239fc 100644 --- a/src/PhpGenerator/Printer.php +++ b/src/PhpGenerator/Printer.php @@ -61,7 +61,7 @@ public function printFunction(GlobalFunction $function, ?PhpNamespace $namespace $body = Helpers::simplifyTaggedNames($function->getBody(), $this->namespace); return Helpers::formatDocComment($function->getComment() . "\n") - . self::printAttributes($function->getAttributes()) + . $this->printAttributes($function->getAttributes()) . $line . $this->printParameters($function, strlen($line) + strlen($returnType) + 2) // 2 = parentheses . $returnType @@ -82,7 +82,7 @@ public function printClosure(Closure $closure, ?PhpNamespace $namespace = null): : $tmp; $body = Helpers::simplifyTaggedNames($closure->getBody(), $this->namespace); - return self::printAttributes($closure->getAttributes(), true) + return $this->printAttributes($closure->getAttributes(), true) . 'function ' . ($closure->getReturnReference() ? '&' : '') . $this->printParameters($closure) @@ -103,7 +103,7 @@ public function printArrowFunction(Closure $closure, ?PhpNamespace $namespace = $body = Helpers::simplifyTaggedNames($closure->getBody(), $this->namespace); - return self::printAttributes($closure->getAttributes()) + return $this->printAttributes($closure->getAttributes()) . 'fn' . ($closure->getReturnReference() ? '&' : '') . $this->printParameters($closure) @@ -128,7 +128,7 @@ public function printMethod(Method $method, ?PhpNamespace $namespace = null): st $body = Helpers::simplifyTaggedNames((string) $method->getBody(), $this->namespace); return Helpers::formatDocComment($method->getComment() . "\n") - . self::printAttributes($method->getAttributes()) + . $this->printAttributes($method->getAttributes()) . $line . $params . $returnType @@ -162,7 +162,7 @@ public function printClass(ClassType $class, ?PhpNamespace $namespace = null): s $cases = []; foreach ($class->getCases() as $case) { $cases[] = Helpers::formatDocComment((string) $case->getComment()) - . self::printAttributes($case->getAttributes()) + . $this->printAttributes($case->getAttributes()) . 'case ' . $case->getName() . ($case->getValue() === null ? '' : ' = ' . $this->dump($case->getValue())) . ";\n"; @@ -179,7 +179,7 @@ public function printClass(ClassType $class, ?PhpNamespace $namespace = null): s . 'const ' . $const->getName() . ' = '; $consts[] = Helpers::formatDocComment((string) $const->getComment()) - . self::printAttributes($const->getAttributes()) + . $this->printAttributes($const->getAttributes()) . $def . $this->dump($const->getValue(), strlen($def)) . ";\n"; } @@ -196,7 +196,7 @@ public function printClass(ClassType $class, ?PhpNamespace $namespace = null): s . '$' . $property->getName()); $properties[] = Helpers::formatDocComment((string) $property->getComment()) - . self::printAttributes($property->getAttributes()) + . $this->printAttributes($property->getAttributes()) . $def . ($property->getValue() === null && !$property->isInitialized() ? '' @@ -220,7 +220,7 @@ public function printClass(ClassType $class, ?PhpNamespace $namespace = null): s return Strings::normalize( Helpers::formatDocComment($class->getComment() . "\n") - . self::printAttributes($class->getAttributes()) + . $this->printAttributes($class->getAttributes()) . ($class->isAbstract() ? 'abstract ' : '') . ($class->isFinal() ? 'final ' : '') . ($class->getName() ? $class->getType() . ' ' . $class->getName() . $enumType . ' ' : '') @@ -238,8 +238,8 @@ public function printNamespace(PhpNamespace $namespace): string $this->namespace = $this->resolveTypes ? $namespace : null; $name = $namespace->getName(); $uses = $this->printUses($namespace) - . $this->printUses($namespace, PhpNamespace::NAME_FUNCTION) - . $this->printUses($namespace, PhpNamespace::NAME_CONSTANT); + . $this->printUses($namespace, PhpNamespace::NameFunction) + . $this->printUses($namespace, PhpNamespace::NameConstant); $items = []; foreach ($namespace->getClasses() as $class) { @@ -282,12 +282,12 @@ public function printFile(PhpFile $file): string } - protected function printUses(PhpNamespace $namespace, string $of = PhpNamespace::NAME_NORMAL): string + protected function printUses(PhpNamespace $namespace, string $of = PhpNamespace::NameNormal): string { $prefix = [ - PhpNamespace::NAME_NORMAL => '', - PhpNamespace::NAME_FUNCTION => 'function ', - PhpNamespace::NAME_CONSTANT => 'const ', + PhpNamespace::NameNormal => '', + PhpNamespace::NameFunction => 'function ', + PhpNamespace::NameConstant => 'const ', ][$of]; $name = $namespace->getName(); $uses = []; @@ -317,7 +317,7 @@ protected function printParameters($function, int $column = 0): string $promoted = $param instanceof PromotedParameter ? $param : null; $params[] = ($promoted ? Helpers::formatDocComment((string) $promoted->getComment()) : '') - . ($attrs = self::printAttributes($param->getAttributes(), true)) + . ($attrs = $this->printAttributes($param->getAttributes(), true)) . ($promoted ? ($promoted->getVisibility() ?: 'public') . ($promoted->isReadOnly() && $type ? ' readonly' : '') diff --git a/src/PhpGenerator/Traits/VisibilityAware.php b/src/PhpGenerator/Traits/VisibilityAware.php index 113953a4..148d66b3 100644 --- a/src/PhpGenerator/Traits/VisibilityAware.php +++ b/src/PhpGenerator/Traits/VisibilityAware.php @@ -28,7 +28,7 @@ trait VisibilityAware */ public function setVisibility(?string $val): self { - if (!in_array($val, [ClassType::VISIBILITY_PUBLIC, ClassType::VISIBILITY_PROTECTED, ClassType::VISIBILITY_PRIVATE, null], true)) { + if (!in_array($val, [ClassType::VisibilityPublic, ClassType::VisibilityProtected, ClassType::VisibilityPrivate, null], true)) { throw new Nette\InvalidArgumentException('Argument must be public|protected|private.'); } @@ -46,41 +46,41 @@ public function getVisibility(): ?string /** @return static */ public function setPublic(): self { - $this->visibility = ClassType::VISIBILITY_PUBLIC; + $this->visibility = ClassType::VisibilityPublic; return $this; } public function isPublic(): bool { - return $this->visibility === ClassType::VISIBILITY_PUBLIC || $this->visibility === null; + return $this->visibility === ClassType::VisibilityPublic || $this->visibility === null; } /** @return static */ public function setProtected(): self { - $this->visibility = ClassType::VISIBILITY_PROTECTED; + $this->visibility = ClassType::VisibilityProtected; return $this; } public function isProtected(): bool { - return $this->visibility === ClassType::VISIBILITY_PROTECTED; + return $this->visibility === ClassType::VisibilityProtected; } /** @return static */ public function setPrivate(): self { - $this->visibility = ClassType::VISIBILITY_PRIVATE; + $this->visibility = ClassType::VisibilityPrivate; return $this; } public function isPrivate(): bool { - return $this->visibility === ClassType::VISIBILITY_PRIVATE; + return $this->visibility === ClassType::VisibilityPrivate; } } diff --git a/src/PhpGenerator/Type.php b/src/PhpGenerator/Type.php index f7568550..2bfef1e0 100644 --- a/src/PhpGenerator/Type.php +++ b/src/PhpGenerator/Type.php @@ -16,22 +16,41 @@ class Type { public const - STRING = 'string', - INT = 'int', - FLOAT = 'float', - BOOL = 'bool', - ARRAY = 'array', - OBJECT = 'object', - CALLABLE = 'callable', - ITERABLE = 'iterable', - VOID = 'void', - NEVER = 'never', - MIXED = 'mixed', - FALSE = 'false', - NULL = 'null', - SELF = 'self', - PARENT = 'parent', - STATIC = 'static'; + String = 'string', + Int = 'int', + Float = 'float', + Bool = 'bool', + Array = 'array', + Object = 'object', + Callable = 'callable', + Iterable = 'iterable', + Void = 'void', + Never = 'never', + Mixed = 'mixed', + False = 'false', + Null = 'null', + Self = 'self', + Parent = 'parent', + Static = 'static'; + + /** @deprecated */ + public const + STRING = self::String, + INT = self::Int, + FLOAT = self::Float, + BOOL = self::Bool, + ARRAY = self::Array, + OBJECT = self::Object, + CALLABLE = self::Callable, + ITERABLE = self::Iterable, + VOID = self::Void, + NEVER = self::Never, + MIXED = self::Mixed, + FALSE = self::False, + NULL = self::Null, + SELF = self::Self, + PARENT = self::Parent, + STATIC = self::Static; public static function nullable(string $type, bool $state = true): string diff --git a/tests/PhpGenerator/ClassType.from.phpt b/tests/PhpGenerator/ClassType.from.phpt index 41fd1b57..5ec16b15 100644 --- a/tests/PhpGenerator/ClassType.from.phpt +++ b/tests/PhpGenerator/ClassType.from.phpt @@ -20,7 +20,7 @@ $res[] = ClassType::from(Abc\Interface4::class); $res[] = ClassType::from(Abc\Class1::class); $res[] = ClassType::from(new Abc\Class2); $obj = new Abc\Class3; -$obj->prop2 = 1; +@$obj->prop2 = 1; // dynamic property $res[] = (new Factory)->fromClassReflection(new ReflectionObject($obj)); $res[] = ClassType::from(Abc\Class4::class); $res[] = ClassType::from(Abc\Class5::class); diff --git a/tests/PhpGenerator/ClassType.fromCode.phpt b/tests/PhpGenerator/ClassType.fromCode.phpt index 786d6ea8..f90f9608 100644 --- a/tests/PhpGenerator/ClassType.fromCode.phpt +++ b/tests/PhpGenerator/ClassType.fromCode.phpt @@ -17,10 +17,10 @@ Assert::match(<<<'XX' */ interface Interface1 { - function func1(); + public function func1(); } XX -, (string) $class); + , (string) $class); Assert::exception(function () { diff --git a/tests/PhpGenerator/ClassType.phpt b/tests/PhpGenerator/ClassType.phpt index b29ac616..cf2fcbb5 100644 --- a/tests/PhpGenerator/ClassType.phpt +++ b/tests/PhpGenerator/ClassType.phpt @@ -58,16 +58,16 @@ $class->addProperty('order') ->setValue(new Literal('RecursiveIteratorIterator::SELF_FIRST')); $class->addProperty('typed1') - ->setType(Type::ARRAY) + ->setType(Type::Array) ->setReadOnly(); $class->addProperty('typed2') - ->setType(Type::ARRAY) + ->setType(Type::Array) ->setNullable() ->setInitialized(); $class->addProperty('typed3') - ->setType(Type::ARRAY) + ->setType(Type::Array) ->setValue(null); $p = $class->addProperty('sections', ['first' => true]) @@ -126,7 +126,7 @@ $method->addParameter('item'); $method->addParameter('res', null) ->setReference(true) - ->setType(Type::union(Type::ARRAY, 'null')); + ->setType(Type::union(Type::Array, 'null')); $method->addParameter('bar', null) ->setType('stdClass|string') diff --git a/tests/PhpGenerator/Dumper.dump().enum.phpt b/tests/PhpGenerator/Dumper.dump().enum.phpt index 188b5723..0963c169 100644 --- a/tests/PhpGenerator/Dumper.dump().enum.phpt +++ b/tests/PhpGenerator/Dumper.dump().enum.phpt @@ -14,7 +14,8 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -enum Suit { +enum Suit +{ case Clubs; case Diamonds; case Hearts; diff --git a/tests/PhpGenerator/Extractor.extractAll.phpt b/tests/PhpGenerator/Extractor.extractAll.phpt index c680d860..e7ed4b89 100644 --- a/tests/PhpGenerator/Extractor.extractAll.phpt +++ b/tests/PhpGenerator/Extractor.extractAll.phpt @@ -30,59 +30,8 @@ sameFile(__DIR__ . '/expected/Extractor.traits.expect', (string) $file); $file = (new Extractor(file_get_contents(__DIR__ . '/fixtures/bodies.php')))->extractAll(); sameFile(__DIR__ . '/expected/Extractor.bodies.expect', (string) $file); -$file = (new Extractor( - <<<'XX' -extractAll(); -Assert::type(Nette\PhpGenerator\PhpFile::class, $file); -Assert::match(<<<'XX' -extractAll(); +sameFile(__DIR__ . '/expected/Extractor.expect', (string) $file); Assert::exception(function () { (new Extractor('')); diff --git a/tests/PhpGenerator/Extractor.getMethodBodies.phpt b/tests/PhpGenerator/Extractor.getMethodBodies.phpt index 1ebf3d6c..4cb6c14a 100644 --- a/tests/PhpGenerator/Extractor.getMethodBodies.phpt +++ b/tests/PhpGenerator/Extractor.getMethodBodies.phpt @@ -35,6 +35,17 @@ abstract class Another echo 123; } } + +enum Color +{ + case Red; + case Blue; + + public function getName(): string + { + return $this->name; + } +} '); $bodies = $extractor->extractMethodBodies('NS\Undefined'); @@ -45,3 +56,8 @@ Assert::same([ 'bar1' => "\$a = 10;\necho 123;", 'bar2' => 'echo "hello";', ], $bodies); + +$bodies = $extractor->extractMethodBodies('NS\Color'); +Assert::same([ + 'getName' => 'return $this->name;', +], $bodies); diff --git a/tests/PhpGenerator/Factory.fromClassCode.phpt b/tests/PhpGenerator/Factory.fromClassCode.phpt index e3d17d07..594b33ff 100644 --- a/tests/PhpGenerator/Factory.fromClassCode.phpt +++ b/tests/PhpGenerator/Factory.fromClassCode.phpt @@ -20,7 +20,7 @@ Assert::match(<<<'XX' */ interface Interface1 { - function func1(); + public function func1(); } XX -, (string) $class); + , (string) $class); diff --git a/tests/PhpGenerator/GlobalFunction.phpt b/tests/PhpGenerator/GlobalFunction.phpt index 7cf3e5cb..9cd4f2bd 100644 --- a/tests/PhpGenerator/GlobalFunction.phpt +++ b/tests/PhpGenerator/GlobalFunction.phpt @@ -60,4 +60,4 @@ function func(stdClass $a, $b = null) } XX -, (string) $function); + , (string) $function); diff --git a/tests/PhpGenerator/Method.returnTypes.phpt b/tests/PhpGenerator/Method.returnTypes.phpt index 68527385..bfdbd547 100644 --- a/tests/PhpGenerator/Method.returnTypes.phpt +++ b/tests/PhpGenerator/Method.returnTypes.phpt @@ -13,8 +13,7 @@ namespace A } } -namespace -{ +namespace { use Nette\PhpGenerator\Method; use Tester\Assert; diff --git a/tests/PhpGenerator/Method.scalarParameters.phpt b/tests/PhpGenerator/Method.scalarParameters.phpt index fac07279..3a1d5965 100644 --- a/tests/PhpGenerator/Method.scalarParameters.phpt +++ b/tests/PhpGenerator/Method.scalarParameters.phpt @@ -39,8 +39,8 @@ Assert::same('float', $method->getParameters()['d']->getType()); $method = (new Method('create')) ->setBody('return null;'); -$method->addParameter('a')->setType(Type::STRING); -$method->addParameter('b')->setType(Type::BOOL); +$method->addParameter('a')->setType(Type::String); +$method->addParameter('b')->setType(Type::Bool); same( 'function create(string $a, bool $b) diff --git a/tests/PhpGenerator/PhpNamespace.aliases.phpt b/tests/PhpGenerator/PhpNamespace.aliases.phpt index 1e217f83..5f8dc034 100644 --- a/tests/PhpGenerator/PhpNamespace.aliases.phpt +++ b/tests/PhpGenerator/PhpNamespace.aliases.phpt @@ -48,7 +48,7 @@ Assert::exception(function () use ($namespace) { }, Nette\InvalidStateException::class, "Name 'F2' used already for 'Foo\\f2'."); Assert::same(['C' => 'Bar\C'], $namespace->getUses()); -Assert::same(['f1' => 'Bar\f1'], $namespace->getUses($namespace::NAME_FUNCTION)); +Assert::same(['f1' => 'Bar\f1'], $namespace->getUses($namespace::NameFunction)); // alias generation @@ -57,6 +57,8 @@ $namespace->addUse('C'); Assert::same('C', $namespace->simplifyName('C')); $namespace->addUse('Bar\C'); Assert::same('C1', $namespace->simplifyName('Bar\C')); +$namespace->removeUse('bar\c'); +Assert::same('Bar\C', $namespace->simplifyName('Bar\C')); $namespace = new PhpNamespace(''); $namespace->addUse('Bar\C'); @@ -90,4 +92,6 @@ Assert::same('Qux', $namespace->simplifyName('Foo\Bar\Baz\Qux')); $namespace = new PhpNamespace('Foo'); $namespace->addUseFunction('Bar\c'); $namespace->addUseFunction('c'); -Assert::same('c1', $namespace->simplifyName('c', $namespace::NAME_FUNCTION)); +Assert::same('c1', $namespace->simplifyName('c', $namespace::NameFunction)); +$namespace->removeUse('c', $namespace::NameFunction); +Assert::same('\c', $namespace->simplifyName('c', $namespace::NameFunction)); diff --git a/tests/PhpGenerator/PhpNamespace.resolve.phpt b/tests/PhpGenerator/PhpNamespace.resolve.phpt index e5b78f1e..50ec9ffe 100644 --- a/tests/PhpGenerator/PhpNamespace.resolve.phpt +++ b/tests/PhpGenerator/PhpNamespace.resolve.phpt @@ -26,21 +26,21 @@ Assert::same('Bar\C\D', $namespace->resolveName('C\D')); $namespace->addUseFunction('Foo\a'); -Assert::same('bar\c', $namespace->resolveName('bar\c', $namespace::NAME_FUNCTION)); -Assert::same('Foo\a', $namespace->resolveName('A', $namespace::NAME_FUNCTION)); -Assert::same('foo\a\b', $namespace->resolveName('foo\a\b', $namespace::NAME_FUNCTION)); +Assert::same('bar\c', $namespace->resolveName('bar\c', $namespace::NameFunction)); +Assert::same('Foo\a', $namespace->resolveName('A', $namespace::NameFunction)); +Assert::same('foo\a\b', $namespace->resolveName('foo\a\b', $namespace::NameFunction)); $namespace->addUseFunction('Bar\c'); -Assert::same('Bar', $namespace->resolveName('Bar', $namespace::NAME_FUNCTION)); -Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NAME_FUNCTION)); -Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NAME_FUNCTION)); +Assert::same('Bar', $namespace->resolveName('Bar', $namespace::NameFunction)); +Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NameFunction)); +Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NameFunction)); $namespace->addUseConstant('Bar\c'); -Assert::same('Bar', $namespace->resolveName('Bar', $namespace::NAME_CONSTANT)); -Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NAME_CONSTANT)); -Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NAME_CONSTANT)); +Assert::same('Bar', $namespace->resolveName('Bar', $namespace::NameConstant)); +Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NameConstant)); +Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NameConstant)); @@ -71,16 +71,16 @@ Assert::same('Bar\C\D', $namespace->resolveName('c\D')); $namespace->addUseFunction('Foo\a'); foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self', 'parent', ''] as $type) { - Assert::same($type, $namespace->resolveName($type, $namespace::NAME_FUNCTION)); + Assert::same($type, $namespace->resolveName($type, $namespace::NameFunction)); } -Assert::same('bar\c', $namespace->resolveName('\bar\c', $namespace::NAME_FUNCTION)); -Assert::same('Foo\a', $namespace->resolveName('A', $namespace::NAME_FUNCTION)); -Assert::same('Foo\C\b', $namespace->resolveName('foo\C\b', $namespace::NAME_FUNCTION)); -Assert::same('Foo\A\b', $namespace->resolveName('A\b', $namespace::NAME_FUNCTION)); +Assert::same('bar\c', $namespace->resolveName('\bar\c', $namespace::NameFunction)); +Assert::same('Foo\a', $namespace->resolveName('A', $namespace::NameFunction)); +Assert::same('Foo\C\b', $namespace->resolveName('foo\C\b', $namespace::NameFunction)); +Assert::same('Foo\A\b', $namespace->resolveName('A\b', $namespace::NameFunction)); $namespace->addUseFunction('Bar\c'); -Assert::same('Bar', $namespace->resolveName('\Bar', $namespace::NAME_FUNCTION)); -Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NAME_FUNCTION)); -Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NAME_FUNCTION)); +Assert::same('Bar', $namespace->resolveName('\Bar', $namespace::NameFunction)); +Assert::same('Bar\c', $namespace->resolveName('C', $namespace::NameFunction)); +Assert::same('Bar\C\d', $namespace->resolveName('c\d', $namespace::NameFunction)); diff --git a/tests/PhpGenerator/PhpNamespace.simplify.phpt b/tests/PhpGenerator/PhpNamespace.simplify.phpt index ca978a5a..a093cae8 100644 --- a/tests/PhpGenerator/PhpNamespace.simplify.phpt +++ b/tests/PhpGenerator/PhpNamespace.simplify.phpt @@ -23,21 +23,21 @@ Assert::same('C\D', $namespace->simplifyName('Bar\C\D')); $namespace->addUseFunction('Foo\a'); -Assert::same('bar\c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION)); -Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NAME_FUNCTION)); -Assert::same('foo\a\b', $namespace->simplifyName('foo\a\b', $namespace::NAME_FUNCTION)); +Assert::same('bar\c', $namespace->simplifyName('bar\c', $namespace::NameFunction)); +Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NameFunction)); +Assert::same('foo\a\b', $namespace->simplifyName('foo\a\b', $namespace::NameFunction)); $namespace->addUseFunction('Bar\c'); -Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NAME_FUNCTION)); -Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION)); -Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_FUNCTION)); +Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NameFunction)); +Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NameFunction)); +Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NameFunction)); $namespace->addUseConstant('Bar\c'); -Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NAME_CONSTANT)); -Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_CONSTANT)); -Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_CONSTANT)); +Assert::same('Bar', $namespace->simplifyName('Bar', $namespace::NameConstant)); +Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NameConstant)); +Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NameConstant)); @@ -75,16 +75,16 @@ Assert::same('žluťoučký', $namespace->simplifyType('foo\žluťoučký')); $namespace->addUseFunction('Foo\a'); foreach (['String', 'string', 'int', 'float', 'bool', 'array', 'callable', 'self', 'parent', ''] as $type) { - Assert::same($type, $namespace->simplifyName($type, $namespace::NAME_FUNCTION)); + Assert::same($type, $namespace->simplifyName($type, $namespace::NameFunction)); } -Assert::same('\bar\c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION)); -Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NAME_FUNCTION)); -Assert::same('Foo\C\b', $namespace->simplifyName('foo\C\b', $namespace::NAME_FUNCTION)); -Assert::same('a\b', $namespace->simplifyName('foo\a\b', $namespace::NAME_FUNCTION)); +Assert::same('\bar\c', $namespace->simplifyName('bar\c', $namespace::NameFunction)); +Assert::same('a', $namespace->simplifyName('foo\A', $namespace::NameFunction)); +Assert::same('Foo\C\b', $namespace->simplifyName('foo\C\b', $namespace::NameFunction)); +Assert::same('a\b', $namespace->simplifyName('foo\a\b', $namespace::NameFunction)); $namespace->addUseFunction('Bar\c'); -Assert::same('\Bar', $namespace->simplifyName('Bar', $namespace::NAME_FUNCTION)); -Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NAME_FUNCTION)); -Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NAME_FUNCTION)); +Assert::same('\Bar', $namespace->simplifyName('Bar', $namespace::NameFunction)); +Assert::same('c', $namespace->simplifyName('bar\c', $namespace::NameFunction)); +Assert::same('C\d', $namespace->simplifyName('Bar\C\d', $namespace::NameFunction)); diff --git a/tests/PhpGenerator/Type.phpt b/tests/PhpGenerator/Type.phpt index d487f18b..e49f2c82 100644 --- a/tests/PhpGenerator/Type.phpt +++ b/tests/PhpGenerator/Type.phpt @@ -8,7 +8,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::same('A|string', Type::union(A::class, Type::STRING)); +Assert::same('A|string', Type::union(A::class, Type::String)); Assert::same('?A', Type::nullable(A::class)); Assert::same('?A', Type::nullable(A::class, true)); diff --git a/tests/PhpGenerator/expected/ClassType.from.81.expect b/tests/PhpGenerator/expected/ClassType.from.81.expect index 2200d27e..f52acd06 100644 --- a/tests/PhpGenerator/expected/ClassType.from.81.expect +++ b/tests/PhpGenerator/expected/ClassType.from.81.expect @@ -1,4 +1,4 @@ -#[Attr(new Abc\Attr(/* unknown */))] +#[Attr(new \Abc\Attr(/* unknown */))] class Class11 { final public const FOO = 10; @@ -12,7 +12,7 @@ class Class11 } - public function bar($c = new stdClass(/* unknown */)) + public function bar($c = new \stdClass(/* unknown */)) { } } diff --git a/tests/PhpGenerator/expected/ClassType.from.bodies.expect b/tests/PhpGenerator/expected/ClassType.from.bodies.expect index 1ce8fe8f..a251549e 100644 --- a/tests/PhpGenerator/expected/ClassType.from.bodies.expect +++ b/tests/PhpGenerator/expected/ClassType.from.bodies.expect @@ -27,6 +27,7 @@ abstract class Class7 public function long() { + // comment if ($member instanceof Method) { $s = [1, 2, 3]; } @@ -39,6 +40,7 @@ abstract class Class7 public function resolving($a = Abc\a\FOO, self $b = null, $c = self::FOO) { + // constants echo FOO; echo \FOO; echo a\FOO; diff --git a/tests/PhpGenerator/expected/Extractor.bodies.expect b/tests/PhpGenerator/expected/Extractor.bodies.expect index aaa0a3ff..6e321ade 100644 --- a/tests/PhpGenerator/expected/Extractor.bodies.expect +++ b/tests/PhpGenerator/expected/Extractor.bodies.expect @@ -10,33 +10,34 @@ use const BAR; abstract class Class7 { - abstract public function abstractFun(); + abstract function abstractFun(); - public function emptyFun() + function emptyFun() { } - public function emptyFun2() + function emptyFun2() { } - public function simple() + function simple() { return 1; } - public function simple2() + function simple2() { return 1; } - public function long() + function long() { + // comment if ($member instanceof Method) { $s = [1, 2, 3]; } @@ -47,8 +48,9 @@ abstract class Class7 } - public function resolving($a = a\FOO, self $b = null, $c = self::FOO) + function resolving($a = a\FOO, self $b = null, $c = self::FOO) { + // constants echo FOO; echo \FOO; echo a\FOO; @@ -67,7 +69,7 @@ abstract class Class7 } - public function complex() + function complex() { echo 1; // single line comment diff --git a/tests/PhpGenerator/expected/Extractor.bodies.resolving.expect b/tests/PhpGenerator/expected/Extractor.bodies.resolving.expect index d2e1236f..cb64aca7 100644 --- a/tests/PhpGenerator/expected/Extractor.bodies.resolving.expect +++ b/tests/PhpGenerator/expected/Extractor.bodies.resolving.expect @@ -5,33 +5,34 @@ use Abc\a\func; abstract class Class7 { - abstract public function abstractFun(); + abstract function abstractFun(); - public function emptyFun() + function emptyFun() { } - public function emptyFun2() + function emptyFun2() { } - public function simple() + function simple() { return 1; } - public function simple2() + function simple2() { return 1; } - public function long() + function long() { + // comment if ($member instanceof \Abc\Method) { $s = [1, 2, 3]; } @@ -42,8 +43,9 @@ abstract class Class7 } - public function resolving($a = \Abc\a\FOO, self $b = null, $c = self::FOO) + function resolving($a = \Abc\a\FOO, self $b = null, $c = self::FOO) { + // constants echo FOO; echo \FOO; echo \Abc\a\FOO; @@ -62,7 +64,7 @@ abstract class Class7 } - public function complex() + function complex() { echo 1; // single line comment diff --git a/tests/PhpGenerator/expected/Extractor.bodies.unresolving.expect b/tests/PhpGenerator/expected/Extractor.bodies.unresolving.expect index 4aaf061d..6ae6f85c 100644 --- a/tests/PhpGenerator/expected/Extractor.bodies.unresolving.expect +++ b/tests/PhpGenerator/expected/Extractor.bodies.unresolving.expect @@ -5,33 +5,34 @@ use Abc\a\func; abstract class Class7 { - abstract public function abstractFun(); + abstract function abstractFun(); - public function emptyFun() + function emptyFun() { } - public function emptyFun2() + function emptyFun2() { } - public function simple() + function simple() { return 1; } - public function simple2() + function simple2() { return 1; } - public function long() + function long() { + // comment if ($member instanceof \Abc\Method) { $s = [1, 2, 3]; } @@ -42,8 +43,9 @@ abstract class Class7 } - public function resolving($a = \Abc\a\FOO, self $b = null, $c = self::FOO) + function resolving($a = \Abc\a\FOO, self $b = null, $c = self::FOO) { + // constants echo FOO; echo \FOO; echo \Abc\a\FOO; @@ -62,7 +64,7 @@ abstract class Class7 } - public function complex() + function complex() { echo 1; // single line comment diff --git a/tests/PhpGenerator/expected/Extractor.classes.80.expect b/tests/PhpGenerator/expected/Extractor.classes.80.expect index 7696e495..e78d8681 100644 --- a/tests/PhpGenerator/expected/Extractor.classes.80.expect +++ b/tests/PhpGenerator/expected/Extractor.classes.80.expect @@ -6,8 +6,11 @@ namespace Abc; class Class8 { - public function __construct($a, int|string $b = 10, $c = null) - { + public function __construct( + public $a, + private int|string $b = 10, + $c = null, + ) { } } @@ -21,7 +24,7 @@ class Class9 /** Commented */ #[ExampleAttribute] #[WithArguments(true)] - public const FOO = 123; + const FOO = 123; /** @var resource */ #[ExampleAttribute] @@ -42,7 +45,7 @@ class Class10 public string|int $prop; - public function test(mixed $param): string|int + function test(mixed $param): string|int { } } diff --git a/tests/PhpGenerator/expected/Extractor.classes.81.expect b/tests/PhpGenerator/expected/Extractor.classes.81.expect index 427d927b..831e8e31 100644 --- a/tests/PhpGenerator/expected/Extractor.classes.81.expect +++ b/tests/PhpGenerator/expected/Extractor.classes.81.expect @@ -27,3 +27,14 @@ class Class11 class Attr { } + +class Class12 +{ + private readonly string $bar; + + + public function __construct(private readonly string $foo) + { + $this->bar = "foobar"; + } +} diff --git a/tests/PhpGenerator/expected/Extractor.classes.expect b/tests/PhpGenerator/expected/Extractor.classes.expect index a4485052..a2d09443 100644 --- a/tests/PhpGenerator/expected/Extractor.classes.expect +++ b/tests/PhpGenerator/expected/Extractor.classes.expect @@ -14,7 +14,7 @@ namespace Abc; */ interface Interface1 { - function func1(); + public function func1(); } interface Interface2 @@ -82,7 +82,7 @@ class Class3 class Class4 { - public const THE_CONSTANT = 9; + const THE_CONSTANT = 9; } class Class5 diff --git a/tests/PhpGenerator/expected/Extractor.enum.expect b/tests/PhpGenerator/expected/Extractor.enum.expect index 3f7943a0..c4fee069 100644 --- a/tests/PhpGenerator/expected/Extractor.enum.expect +++ b/tests/PhpGenerator/expected/Extractor.enum.expect @@ -18,8 +18,8 @@ enum Enum1 case Hearts; case Spades; - public const FOO = 123; - public const BAR = self::Clubs; + const FOO = 123; + const BAR = self::Clubs; public function foo($x = self::Diamonds) { @@ -31,7 +31,7 @@ enum Enum2: string implements \Countable case GET = 'get'; case POST = 'post'; - public function count(): int + function count(): int { } } diff --git a/tests/PhpGenerator/expected/Extractor.expect b/tests/PhpGenerator/expected/Extractor.expect new file mode 100644 index 00000000..8b3afc30 --- /dev/null +++ b/tests/PhpGenerator/expected/Extractor.expect @@ -0,0 +1,43 @@ +bar = "foobar"; + } +} diff --git a/tests/PhpGenerator/fixtures/extractor.php b/tests/PhpGenerator/fixtures/extractor.php new file mode 100644 index 00000000..fafe8004 --- /dev/null +++ b/tests/PhpGenerator/fixtures/extractor.php @@ -0,0 +1,39 @@ +