Вход Регистрация
Файл: gapps/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php
Строк: 330
<?php

namespace PhpParserNodeVisitor;

use 
PhpParserNodeVisitorAbstract;
use 
PhpParserError;
use 
PhpParserNode;
use 
PhpParserNodeName;
use 
PhpParserNodeNameFullyQualified;
use 
PhpParserNodeExpr;
use 
PhpParserNodeStmt;

class 
NameResolver extends NodeVisitorAbstract
{
    
/** @var null|Name Current namespace */
    
protected $namespace;

    
/** @var array Map of format [aliasType => [aliasName => originalName]] */
    
protected $aliases;

    public function 
beforeTraverse(array $nodes) {
        
$this->resetState();
    }

    public function 
enterNode(Node $node) {
        if (
$node instanceof StmtNamespace_) {
            
$this->resetState($node->name);
        } elseif (
$node instanceof StmtUse_) {
            foreach (
$node->uses as $use) {
                
$this->addAlias($use$node->typenull);
            }
        } elseif (
$node instanceof StmtGroupUse) {
            foreach (
$node->uses as $use) {
                
$this->addAlias($use$node->type$node->prefix);
            }
        } elseif (
$node instanceof StmtClass_) {
            if (
null !== $node->extends) {
                
$node->extends $this->resolveClassName($node->extends);
            }

            foreach (
$node->implements as &$interface) {
                
$interface $this->resolveClassName($interface);
            }

            if (
null !== $node->name) {
                
$this->addNamespacedName($node);
            }
        } elseif (
$node instanceof StmtInterface_) {
            foreach (
$node->extends as &$interface) {
                
$interface $this->resolveClassName($interface);
            }

            
$this->addNamespacedName($node);
        } elseif (
$node instanceof StmtTrait_) {
            
$this->addNamespacedName($node);
        } elseif (
$node instanceof StmtFunction_) {
            
$this->addNamespacedName($node);
            
$this->resolveSignature($node);
        } elseif (
$node instanceof StmtClassMethod
                  
|| $node instanceof ExprClosure
        
) {
            
$this->resolveSignature($node);
        } elseif (
$node instanceof StmtConst_) {
            foreach (
$node->consts as $const) {
                
$this->addNamespacedName($const);
            }
        } elseif (
$node instanceof ExprStaticCall
                  
|| $node instanceof ExprStaticPropertyFetch
                  
|| $node instanceof ExprClassConstFetch
                  
|| $node instanceof ExprNew_
                  
|| $node instanceof ExprInstanceof_
        
) {
            if (
$node->class instanceof Name) {
                
$node->class $this->resolveClassName($node->class);
            }
        } elseif (
$node instanceof StmtCatch_) {
            
$node->type $this->resolveClassName($node->type);
        } elseif (
$node instanceof ExprFuncCall) {
            if (
$node->name instanceof Name) {
                
$node->name $this->resolveOtherName($node->nameStmtUse_::TYPE_FUNCTION);
            }
        } elseif (
$node instanceof ExprConstFetch) {
            
$node->name $this->resolveOtherName($node->nameStmtUse_::TYPE_CONSTANT);
        } elseif (
$node instanceof StmtTraitUse) {
            foreach (
$node->traits as &$trait) {
                
$trait $this->resolveClassName($trait);
            }

            foreach (
$node->adaptations as $adaptation) {
                if (
null !== $adaptation->trait) {
                    
$adaptation->trait $this->resolveClassName($adaptation->trait);
                }

                if (
$adaptation instanceof StmtTraitUseAdaptationPrecedence) {
                    foreach (
$adaptation->insteadof as &$insteadof) {
                        
$insteadof $this->resolveClassName($insteadof);
                    }
                }
            }

        }
    }

    protected function 
resetState(Name $namespace null) {
        
$this->namespace $namespace;
        
$this->aliases   = array(
            
StmtUse_::TYPE_NORMAL   => array(),
            
StmtUse_::TYPE_FUNCTION => array(),
            
StmtUse_::TYPE_CONSTANT => array(),
        );
    }

    protected function 
addAlias(StmtUseUse $use$typeName $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 === StmtUse_::TYPE_CONSTANT) {
            
$aliasName $use->alias;
        } else {
            
$aliasName strtolower($use->alias);
        }

        if (isset(
$this->aliases[$type][$aliasName])) {
            
$typeStringMap = array(
                
StmtUse_::TYPE_NORMAL   => '',
                
StmtUse_::TYPE_FUNCTION => 'function ',
                
StmtUse_::TYPE_CONSTANT => 'const ',
            );

            throw new 
Error(
                
sprintf(
                    
'Cannot use %s%s as %s because the name is already in use',
                    
$typeStringMap[$type], $name$use->alias
                
),
                
$use->getLine()
            );
        }

        
$this->aliases[$type][$aliasName] = $name;
    }

    
/** @param StmtFunction_|StmtClassMethod|ExprClosure $node */
    
private function resolveSignature($node) {
        foreach (
$node->params as $param) {
            if (
$param->type instanceof Name) {
                
$param->type $this->resolveClassName($param->type);
            }
        }
        if (
$node->returnType instanceof Name) {
            
$node->returnType $this->resolveClassName($node->returnType);
        }
    }

    protected function 
resolveClassName(Name $name) {
        
// don't resolve special class names
        
if (in_array(strtolower($name->toString()), array('self''parent''static'))) {
            if (!
$name->isUnqualified()) {
                throw new 
Error(
                    
sprintf("'\%s' is an invalid class name"$name->toString()),
                    
$name->getLine()
                );
            }

            return 
$name;
        }

        
// fully qualified names are already resolved
        
if ($name->isFullyQualified()) {
            return 
$name;
        }

        
$aliasName strtolower($name->getFirst());
        if (!
$name->isRelative() && isset($this->aliases[StmtUse_::TYPE_NORMAL][$aliasName])) {
            
// resolve aliases (for non-relative names)
            
$alias $this->aliases[StmtUse_::TYPE_NORMAL][$aliasName];
            return 
FullyQualified::concat($alias$name->slice(1), $name->getAttributes());
        }

        if (
null !== $this->namespace) {
            
// if no alias exists prepend current namespace
            
return FullyQualified::concat($this->namespace$name$name->getAttributes());
        }

        return new 
FullyQualified($name->parts$name->getAttributes());
    }

    protected function 
resolveOtherName(Name $name$type) {
        
// 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[StmtUse_::TYPE_NORMAL][$aliasName])) {
            
$alias $this->aliases[StmtUse_::TYPE_NORMAL][$aliasName];
            return 
FullyQualified::concat($alias$name->slice(1), $name->getAttributes());
        }

        if (
$name->isUnqualified()) {
            if (
$type === StmtUse_::TYPE_CONSTANT) {
                
// constant aliases are case-sensitive, function aliases case-insensitive
                
$aliasName $name->getFirst();
            }

            if (!isset(
$this->aliases[$type][$aliasName])) {
                
// unqualified, unaliased names cannot be resolved at compile-time
                
return $name;
            }

            
// resolve unqualified aliases
            
return new FullyQualified($this->aliases[$type][$aliasName], $name->getAttributes());
        }

        if (
null !== $this->namespace) {
            
// if no alias exists prepend current namespace
            
return FullyQualified::concat($this->namespace$name$name->getAttributes());
        }

        return new 
FullyQualified($name->parts$name->getAttributes());
    }

    protected function 
addNamespacedName(Node $node) {
        if (
null !== $this->namespace) {
            
$node->namespacedName Name::concat($this->namespace$node->name);
        } else {
            
$node->namespacedName = new Name($node->name);
        }
    }
}
Онлайн: 2
Реклама