vendor/doctrine-common/lib/Doctrine/Common/Annotations/PhpParser.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
 * This software consists of voluntary contributions made by many individuals
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
 * and is licensed under the LGPL. For more information, see
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * <http://www.doctrine-project.org>.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
namespace Doctrine\Common\Annotations;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
 * Parses a file for namespaces/use/class declarations.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
 * @author Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
final class PhpParser
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
    private $tokens;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
     * Parses a class.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
     * @param \ReflectionClass $class
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    public function parseClass(\ReflectionClass $class)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
        if (false === $filename = $class->getFilename()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
            return array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        $src = file_get_contents($filename);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        $name = $class->getName();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        // This is a short-cut for code that follows some conventions:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
        // - namespaced
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        // - one class per file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        if (preg_match_all('#\bnamespace\s+'.str_replace('\\', '\\\\', $class->getNamespaceName()).'\s*;.*?\b(?:class|interface)\s+'.$class->getShortName().'\b#s', $src, $matches)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
            foreach ($matches[0] as $match) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
                $classes = $this->parse('<?php '.$match, $name);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
                if (isset($classes[$name])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
                    return $classes[$name];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        $classes = $this->parse($src, $name);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        return $classes[$name];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    private function parse($src, $interestedClass = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        $this->tokens = token_get_all($src);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        $classes = $uses = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        $namespace = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
        while ($token = $this->next()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
            if (T_NAMESPACE === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
                $namespace = $this->parseNamespace();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
                $uses = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
            } elseif (T_CLASS === $token[0] || T_INTERFACE === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
                if ('' !== $namespace) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
                    $class = $namespace.'\\'.$this->nextValue();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
                    $class = $this->nextValue();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
                $classes[$class] = $uses;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
                if (null !== $interestedClass && $interestedClass === $class) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
                    return $classes;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
            } elseif (T_USE === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
                foreach ($this->parseUseStatement() as $useStatement) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
                    list($alias, $class) = $useStatement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                    $uses[strtolower($alias)] = $class;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
        return $classes;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    private function parseNamespace()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
        $namespace = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        while ($token = $this->next()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
            if (T_NS_SEPARATOR === $token[0] || T_STRING === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
                $namespace .= $token[1];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
            } elseif (is_string($token) && in_array($token, array(';', '{'))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
                return $namespace;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
    private function parseUseStatement()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
        $statements = $class = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
        $alias = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
        while ($token = $this->next()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
            if (T_NS_SEPARATOR === $token[0] || T_STRING === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
                $class[] = $token[1];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
            } else if (T_AS === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
                $alias = $this->nextValue();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
            } else if (is_string($token)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
                if (',' === $token || ';' === $token) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
                    $statements[] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
                        $alias ? $alias : $class[count($class) - 1],
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
                        implode('', $class)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
                    );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
                if (';' === $token) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
                    return $statements;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
                if (',' === $token) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
                    $class = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
                    $alias = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
                    continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
    private function next()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
        while ($token = array_shift($this->tokens)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
            if (in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
                continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
            return $token;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
    private function nextValue()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
        $token = $this->next();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
        return is_array($token) ? $token[1] : $token;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
}