Mercurial > hg > isophonics-drupal-site
diff vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @ 13:5fb285c0d0e3
Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've
been lucky to get away with this so far, as we don't support self-registration
which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5
was vulnerable to.
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:33:26 +0100 |
parents | 4c8ae668cc8c |
children | 129ea1e6d783 |
line wrap: on
line diff
--- a/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php Fri Feb 23 15:52:07 2018 +0000 +++ b/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php Mon Apr 23 09:33:26 2018 +0100 @@ -1,9 +1,10 @@ -<?php +<?php declare(strict_types=1); namespace PhpParser\NodeVisitor; use PhpParser\Error; use PhpParser\ErrorHandler; +use PhpParser\NameContext; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Name; @@ -13,39 +14,51 @@ class NameResolver extends NodeVisitorAbstract { - /** @var null|Name Current namespace */ - protected $namespace; - - /** @var array Map of format [aliasType => [aliasName => originalName]] */ - protected $aliases; - - /** @var ErrorHandler Error handler */ - protected $errorHandler; + /** @var NameContext Naming context */ + protected $nameContext; /** @var bool Whether to preserve original names */ protected $preserveOriginalNames; + /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */ + protected $replaceNodes; + /** * Constructs a name resolution visitor. * - * Options: If "preserveOriginalNames" is enabled, an "originalName" attribute will be added to - * all name nodes that underwent resolution. + * Options: + * * preserveOriginalNames (default false): An "originalName" attribute will be added to + * all name nodes that underwent resolution. + * * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a + * resolvedName attribute is added. (Names that cannot be statically resolved receive a + * namespacedName attribute, as usual.) * * @param ErrorHandler|null $errorHandler Error handler * @param array $options Options */ public function __construct(ErrorHandler $errorHandler = null, array $options = []) { - $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; - $this->preserveOriginalNames = !empty($options['preserveOriginalNames']); + $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); + $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; + $this->replaceNodes = $options['replaceNodes'] ?? true; + } + + /** + * Get name resolution context. + * + * @return NameContext + */ + public function getNameContext() : NameContext { + return $this->nameContext; } public function beforeTraverse(array $nodes) { - $this->resetState(); + $this->nameContext->startNamespace(); + return null; } public function enterNode(Node $node) { if ($node instanceof Stmt\Namespace_) { - $this->resetState($node->name); + $this->nameContext->startNamespace($node->name); } elseif ($node instanceof Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type, null); @@ -100,10 +113,10 @@ } } elseif ($node instanceof Expr\FuncCall) { if ($node->name instanceof Name) { - $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_FUNCTION); + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof Expr\ConstFetch) { - $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_CONSTANT); + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); @@ -121,48 +134,19 @@ } } } + + return null; } - protected function resetState(Name $namespace = null) { - $this->namespace = $namespace; - $this->aliases = array( - Stmt\Use_::TYPE_NORMAL => array(), - Stmt\Use_::TYPE_FUNCTION => array(), - Stmt\Use_::TYPE_CONSTANT => array(), - ); - } - - protected function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) { + private function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) { // Add prefix for group uses $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; // Type is determined either by individual element or whole use declaration $type |= $use->type; - // Constant names are case sensitive, everything else case insensitive - if ($type === Stmt\Use_::TYPE_CONSTANT) { - $aliasName = $use->alias; - } else { - $aliasName = strtolower($use->alias); - } - - if (isset($this->aliases[$type][$aliasName])) { - $typeStringMap = array( - Stmt\Use_::TYPE_NORMAL => '', - Stmt\Use_::TYPE_FUNCTION => 'function ', - Stmt\Use_::TYPE_CONSTANT => 'const ', - ); - - $this->errorHandler->handleError(new Error( - sprintf( - 'Cannot use %s%s as %s because the name is already in use', - $typeStringMap[$type], $name, $use->alias - ), - $use->getAttributes() - )); - return; - } - - $this->aliases[$type][$aliasName] = $name; + $this->nameContext->addAlias( + $name, (string) $use->getAlias(), $type, $use->getAttributes() + ); } /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ @@ -184,7 +168,26 @@ return $node; } - protected function resolveClassName(Name $name) { + /** + * Resolve name, according to name resolver options. + * + * @param Name $name Function or constant name to resolve + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name Resolved name, or original name with attribute + */ + protected function resolveName(Name $name, int $type) : Name { + if (!$this->replaceNodes) { + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + $name->setAttribute('resolvedName', $resolvedName); + } else { + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + } + return $name; + } + if ($this->preserveOriginalNames) { // Save the original name $originalName = $name; @@ -192,81 +195,24 @@ $name->setAttribute('originalName', $originalName); } - // don't resolve special class names - if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) { - if (!$name->isUnqualified()) { - $this->errorHandler->handleError(new Error( - sprintf("'\\%s' is an invalid class name", $name->toString()), - $name->getAttributes() - )); - } - return $name; + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + return $resolvedName; } - // fully qualified names are already resolved - if ($name->isFullyQualified()) { - return $name; - } - - $aliasName = strtolower($name->getFirst()); - if (!$name->isRelative() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { - // resolve aliases (for non-relative names) - $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]; - return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); - } - - // if no alias exists prepend current namespace - return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + // unqualified names inside a namespace cannot be resolved at compile-time + // add the namespaced version of the name as an attribute + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + return $name; } - protected function resolveOtherName(Name $name, $type) { - if ($this->preserveOriginalNames) { - // Save the original name - $originalName = $name; - $name = clone $originalName; - $name->setAttribute('originalName', $originalName); - } - - // fully qualified names are already resolved - if ($name->isFullyQualified()) { - return $name; - } - - // resolve aliases for qualified names - $aliasName = strtolower($name->getFirst()); - if ($name->isQualified() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { - $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]; - return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); - } - - if ($name->isUnqualified()) { - if ($type === Stmt\Use_::TYPE_CONSTANT) { - // constant aliases are case-sensitive, function aliases case-insensitive - $aliasName = $name->getFirst(); - } - - if (isset($this->aliases[$type][$aliasName])) { - // resolve unqualified aliases - return new FullyQualified($this->aliases[$type][$aliasName], $name->getAttributes()); - } - - if (null === $this->namespace) { - // outside of a namespace unaliased unqualified is same as fully qualified - return new FullyQualified($name, $name->getAttributes()); - } - - // unqualified names inside a namespace cannot be resolved at compile-time - // add the namespaced version of the name as an attribute - $name->setAttribute('namespacedName', - FullyQualified::concat($this->namespace, $name, $name->getAttributes())); - return $name; - } - - // if no alias exists prepend current namespace - return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + protected function resolveClassName(Name $name) { + return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); } protected function addNamespacedName(Node $node) { - $node->namespacedName = Name::concat($this->namespace, $node->name); + $node->namespacedName = Name::concat( + $this->nameContext->getNamespace(), (string) $node->name); } }