123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- <?php declare(strict_types=1);
- namespace PhpParser;
- use PhpParser\Node\Expr;
- use PhpParser\Node\Identifier;
- use PhpParser\Node\Name;
- use PhpParser\Node\NullableType;
- use PhpParser\Node\Scalar;
- use PhpParser\Node\Stmt;
- use PhpParser\Node\UnionType;
- /**
- * This class defines helpers used in the implementation of builders. Don't use it directly.
- *
- * @internal
- */
- final class BuilderHelpers
- {
- /**
- * Normalizes a node: Converts builder objects to nodes.
- *
- * @param Node|Builder $node The node to normalize
- *
- * @return Node The normalized node
- */
- public static function normalizeNode($node) : Node {
- if ($node instanceof Builder) {
- return $node->getNode();
- } elseif ($node instanceof Node) {
- return $node;
- }
- throw new \LogicException('Expected node or builder object');
- }
- /**
- * Normalizes a node to a statement.
- *
- * Expressions are wrapped in a Stmt\Expression node.
- *
- * @param Node|Builder $node The node to normalize
- *
- * @return Stmt The normalized statement node
- */
- public static function normalizeStmt($node) : Stmt {
- $node = self::normalizeNode($node);
- if ($node instanceof Stmt) {
- return $node;
- }
- if ($node instanceof Expr) {
- return new Stmt\Expression($node);
- }
- throw new \LogicException('Expected statement or expression node');
- }
- /**
- * Normalizes strings to Identifier.
- *
- * @param string|Identifier $name The identifier to normalize
- *
- * @return Identifier The normalized identifier
- */
- public static function normalizeIdentifier($name) : Identifier {
- if ($name instanceof Identifier) {
- return $name;
- }
- if (\is_string($name)) {
- return new Identifier($name);
- }
- throw new \LogicException('Expected string or instance of Node\Identifier');
- }
- /**
- * Normalizes strings to Identifier, also allowing expressions.
- *
- * @param string|Identifier|Expr $name The identifier to normalize
- *
- * @return Identifier|Expr The normalized identifier or expression
- */
- public static function normalizeIdentifierOrExpr($name) {
- if ($name instanceof Identifier || $name instanceof Expr) {
- return $name;
- }
- if (\is_string($name)) {
- return new Identifier($name);
- }
- throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr');
- }
- /**
- * Normalizes a name: Converts string names to Name nodes.
- *
- * @param Name|string $name The name to normalize
- *
- * @return Name The normalized name
- */
- public static function normalizeName($name) : Name {
- return self::normalizeNameCommon($name, false);
- }
- /**
- * Normalizes a name: Converts string names to Name nodes, while also allowing expressions.
- *
- * @param Expr|Name|string $name The name to normalize
- *
- * @return Name|Expr The normalized name or expression
- */
- public static function normalizeNameOrExpr($name) {
- return self::normalizeNameCommon($name, true);
- }
- /**
- * Normalizes a name: Converts string names to Name nodes, optionally allowing expressions.
- *
- * @param Expr|Name|string $name The name to normalize
- * @param bool $allowExpr Whether to also allow expressions
- *
- * @return Name|Expr The normalized name, or expression (if allowed)
- */
- private static function normalizeNameCommon($name, bool $allowExpr) {
- if ($name instanceof Name) {
- return $name;
- } elseif (is_string($name)) {
- if (!$name) {
- throw new \LogicException('Name cannot be empty');
- }
- if ($name[0] === '\\') {
- return new Name\FullyQualified(substr($name, 1));
- } elseif (0 === strpos($name, 'namespace\\')) {
- return new Name\Relative(substr($name, strlen('namespace\\')));
- } else {
- return new Name($name);
- }
- }
- if ($allowExpr) {
- if ($name instanceof Expr) {
- return $name;
- }
- throw new \LogicException(
- 'Name must be a string or an instance of Node\Name or Node\Expr'
- );
- } else {
- throw new \LogicException('Name must be a string or an instance of Node\Name');
- }
- }
- /**
- * Normalizes a type: Converts plain-text type names into proper AST representation.
- *
- * In particular, builtin types become Identifiers, custom types become Names and nullables
- * are wrapped in NullableType nodes.
- *
- * @param string|Name|Identifier|NullableType|UnionType $type The type to normalize
- *
- * @return Name|Identifier|NullableType|UnionType The normalized type
- */
- public static function normalizeType($type) {
- if (!is_string($type)) {
- if (
- !$type instanceof Name && !$type instanceof Identifier &&
- !$type instanceof NullableType && !$type instanceof UnionType
- ) {
- throw new \LogicException(
- 'Type must be a string, or an instance of Name, Identifier, NullableType or UnionType'
- );
- }
- return $type;
- }
- $nullable = false;
- if (strlen($type) > 0 && $type[0] === '?') {
- $nullable = true;
- $type = substr($type, 1);
- }
- $builtinTypes = [
- 'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed'
- ];
- $lowerType = strtolower($type);
- if (in_array($lowerType, $builtinTypes)) {
- $type = new Identifier($lowerType);
- } else {
- $type = self::normalizeName($type);
- }
- if ($nullable && (string) $type === 'void') {
- throw new \LogicException('void type cannot be nullable');
- }
- if ($nullable && (string) $type === 'mixed') {
- throw new \LogicException('mixed type cannot be nullable');
- }
- return $nullable ? new NullableType($type) : $type;
- }
- /**
- * Normalizes a value: Converts nulls, booleans, integers,
- * floats, strings and arrays into their respective nodes
- *
- * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize
- *
- * @return Expr The normalized value
- */
- public static function normalizeValue($value) : Expr {
- if ($value instanceof Node\Expr) {
- return $value;
- } elseif (is_null($value)) {
- return new Expr\ConstFetch(
- new Name('null')
- );
- } elseif (is_bool($value)) {
- return new Expr\ConstFetch(
- new Name($value ? 'true' : 'false')
- );
- } elseif (is_int($value)) {
- return new Scalar\LNumber($value);
- } elseif (is_float($value)) {
- return new Scalar\DNumber($value);
- } elseif (is_string($value)) {
- return new Scalar\String_($value);
- } elseif (is_array($value)) {
- $items = [];
- $lastKey = -1;
- foreach ($value as $itemKey => $itemValue) {
- // for consecutive, numeric keys don't generate keys
- if (null !== $lastKey && ++$lastKey === $itemKey) {
- $items[] = new Expr\ArrayItem(
- self::normalizeValue($itemValue)
- );
- } else {
- $lastKey = null;
- $items[] = new Expr\ArrayItem(
- self::normalizeValue($itemValue),
- self::normalizeValue($itemKey)
- );
- }
- }
- return new Expr\Array_($items);
- } else {
- throw new \LogicException('Invalid value');
- }
- }
- /**
- * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
- *
- * @param Comment\Doc|string $docComment The doc comment to normalize
- *
- * @return Comment\Doc The normalized doc comment
- */
- public static function normalizeDocComment($docComment) : Comment\Doc {
- if ($docComment instanceof Comment\Doc) {
- return $docComment;
- } elseif (is_string($docComment)) {
- return new Comment\Doc($docComment);
- } else {
- throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
- }
- }
- /**
- * Adds a modifier and returns new modifier bitmask.
- *
- * @param int $modifiers Existing modifiers
- * @param int $modifier Modifier to set
- *
- * @return int New modifiers
- */
- public static function addModifier(int $modifiers, int $modifier) : int {
- Stmt\Class_::verifyModifier($modifiers, $modifier);
- return $modifiers | $modifier;
- }
- }
|