Arbit - project tracking

Static Reflection

Browse source code

File: / source/ pdepend/ reflection/ parser/ Parser.php

Type
text/plain text/plain
Last Author
mapi
Version
289
Line Rev. Author Source
1 18 mapi <?php
2 66 mapi /**
3 mapi * This file is part of the static reflection component.
4 mapi *
5 mapi * PHP Version 5
6 mapi *
7 247 mapi * Copyright (c) 2009-2010, Manuel Pichler <mapi@pdepend.org>.
8 66 mapi * All rights reserved.
9 mapi *
10 mapi * Redistribution and use in source and binary forms, with or without
11 mapi * modification, are permitted provided that the following conditions
12 mapi * are met:
13 mapi *
14 mapi * * Redistributions of source code must retain the above copyright
15 mapi * notice, this list of conditions and the following disclaimer.
16 mapi *
17 mapi * * Redistributions in binary form must reproduce the above copyright
18 mapi * notice, this list of conditions and the following disclaimer in
19 mapi * the documentation and/or other materials provided with the
20 mapi * distribution.
21 mapi *
22 mapi * * Neither the name of Manuel Pichler nor the names of his
23 mapi * contributors may be used to endorse or promote products derived
24 mapi * from this software without specific prior written permission.
25 mapi *
26 mapi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 mapi * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 mapi * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 mapi * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 mapi * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 mapi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 mapi * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 mapi * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 mapi * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 mapi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 mapi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 mapi * POSSIBILITY OF SUCH DAMAGE.
38 mapi *
39 mapi * @category PHP
40 248 mapi * @package pdepend\reflection\parser
41 66 mapi * @author Manuel Pichler <mapi@pdepend.org>
42 247 mapi * @copyright 2009-2010 Manuel Pichler. All rights reserved.
43 66 mapi * @license http://www.opensource.org/licenses/bsd-license.php BSD License
44 mapi * @version SVN: $Id$
45 mapi * @link http://pdepend.org/
46 mapi */
47 18 mapi
48 248 mapi namespace pdepend\reflection\parser;
49 18 mapi
50 248 mapi use pdepend\reflection\api\StaticReflectionValue;
51 mapi use pdepend\reflection\api\StaticReflectionClass;
52 mapi use pdepend\reflection\api\StaticReflectionMethod;
53 mapi use pdepend\reflection\api\StaticReflectionInterface;
54 mapi use pdepend\reflection\api\StaticReflectionParameter;
55 mapi use pdepend\reflection\api\StaticReflectionProperty;
56 mapi use pdepend\reflection\interfaces\ParserContext;
57 mapi use pdepend\reflection\exceptions\EndOfTokenStreamException;
58 mapi use pdepend\reflection\exceptions\UnexpectedTokenException;
59 19 mapi
60 67 mapi /**
61 mapi * Parser implementation based on PHP's internal tokenizer extension.
62 mapi *
63 mapi * @category PHP
64 248 mapi * @package pdepend\reflection\parser
65 67 mapi * @author Manuel Pichler <mapi@pdepend.org>
66 247 mapi * @copyright 2009-2010 Manuel Pichler. All rights reserved.
67 67 mapi * @license http://www.opensource.org/licenses/bsd-license.php BSD License
68 mapi * @version Release: @package_version@
69 mapi * @link http://pdepend.org/
70 mapi */
71 289 mapi class Parser // @codeCoverageIgnoreStart pdepend-warning pdepend-warning pdepend-error pdepend-error pdepend-warning pdepend-error pdepend-error pdepend-warning pdepend-warning pdepend-error pdepend-error pdepend-error pdepend-error pdepend-error pdepend-error pdepend-error pdepend-error pdepend-warning pdepend-error pdepend-warning pdepend-warning pdepend-warning pdepend-error pdepend-error
72 18 mapi {
73 289 mapi // @codeCoverageIgnoreEnd
74 mapi
75 18 mapi /**
76 163 mapi * The used parsing context that will be used to retriev reflection
77 mapi * interfaces or classes the currently parsed class depends on.
78 140 mapi *
79 248 mapi * @var \pdepend\reflection\interfaces\ParserContext
80 19 mapi */
81 151 mapi private $_context = null;
82 19 mapi
83 mapi /**
84 128 mapi * The source file path name.
85 mapi *
86 mapi * @var string
87 mapi */
88 mapi private $_pathName = null;
89 mapi
90 mapi /**
91 68 mapi * The used source tokenizer.
92 mapi *
93 248 mapi * @var \pdepend\reflection\parser\Tokenizer
94 18 mapi */
95 mapi private $_tokenizer = null;
96 mapi
97 mapi /**
98 68 mapi * The currently parsed namespace.
99 mapi *
100 18 mapi * @var string
101 mapi */
102 mapi private $_namespace = '';
103 mapi
104 mapi /**
105 68 mapi * Alias map created from <b>use</b> statements.
106 mapi *
107 18 mapi * @var array(string=>string)
108 mapi */
109 mapi private $_aliasMap = array();
110 93 mapi
111 mapi /**
112 mapi * Reference to the currently parsed class or interface.
113 mapi *
114 248 mapi * @var \pdepend\reflection\api\StaticReflectionInterface
115 93 mapi */
116 mapi private $_classOrInterface = null;
117 91 mapi
118 18 mapi /**
119 36 mapi * Parsed methods within a class or interface scope.
120 mapi *
121 248 mapi * @var array(\pdepend\reflection\api\StaticReflectionMethod)
122 36 mapi */
123 mapi private $_methods = array();
124 mapi
125 mapi /**
126 mapi * Parsed properties within a class scope.
127 mapi *
128 248 mapi * @var array(\pdepend\reflection\api\StaticReflectionMethod)
129 36 mapi */
130 mapi private $_properties = array();
131 mapi
132 mapi /**
133 mapi * Parsed constants within a class or interface scope.
134 mapi *
135 mapi * @var array(string=>mixed)
136 mapi */
137 mapi private $_constants = array();
138 mapi
139 mapi /**
140 81 mapi * Parsed method parameters for a single method.
141 mapi *
142 248 mapi * @var array(\pdepend\reflection\api\StaticReflectionParameter)
143 81 mapi */
144 mapi private $_parameters = array();
145 mapi
146 mapi /**
147 125 mapi * Static variables declared within a method's body.
148 mapi *
149 mapi * @var array(string=>mixed)
150 mapi */
151 mapi private $_staticVariables = array();
152 mapi
153 mapi /**
154 70 mapi * Constructs a new parser instance.
155 mapi *
156 248 mapi * @param \pdepend\reflection\interfaces\ParserContext $context The used
157 163 mapi * parsing context that will be used to retriev reflection interfaces
158 mapi * or classes the currently parsed class depends on.
159 18 mapi */
160 151 mapi public function __construct( ParserContext $context )
161 18 mapi {
162 151 mapi $this->_context = $context;
163 18 mapi }
164 mapi
165 mapi /**
166 163 mapi * Parses the given file and returns reflection class instances for all
167 mapi * found classes or interfaces.
168 mapi *
169 mapi * @param string $pathName The pathname of file which contains the class or
170 mapi * interface that must be parsed by the parser.
171 mapi *
172 248 mapi * @return array(\pdepend\reflection\api\StaticReflectionInterface)
173 18 mapi */
174 131 mapi public function parseFile( $pathName )
175 mapi {
176 mapi $this->_pathName = $pathName;
177 mapi return $this->parseSource( file_get_contents( $this->_pathName ) );
178 mapi }
179 mapi
180 139 mapi /**
181 163 mapi * Parses the given source code and returns reflection class instances for
182 mapi * all found classes or interfaces.
183 mapi *
184 mapi * @param string $source The source code of a php file that must be parsed
185 mapi * by the parser.
186 mapi *
187 248 mapi * @return array(\pdepend\reflection\api\StaticReflectionInterface)
188 139 mapi */
189 131 mapi public function parseSource( $source )
190 mapi {
191 mapi return $this->_parse( $source );
192 mapi }
193 mapi
194 129 mapi /**
195 163 mapi * This method parses the given source code and returns instances of
196 mapi * <b>\ReflectionClass</b> for all detected interfaces or classes.
197 mapi *
198 mapi * @param string $source The source code of a php file that must be parsed
199 mapi * by the parser.
200 mapi *
201 248 mapi * @return array(\pdepend\reflection\api\StaticReflectionInterface)
202 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
203 163 mapi * detects an error during the parsing process.
204 129 mapi */
205 131 mapi private function _parse( $source ) pdepend-error pdepend-error pdepend-warning pdepend-warning pdepend-warning pdepend-error
206 129 mapi {
207 131 mapi $this->_tokenizer = new Tokenizer( $source );
208 129 mapi
209 mapi $class = null;
210 mapi $classes = array();
211 18 mapi $modifiers = 0;
212 mapi $docComment = '';
213 mapi
214 mapi while ( is_object( $token = $this->_next() ) )
215 mapi {
216 mapi switch ( $token->type )
217 mapi {
218 mapi case ParserTokens::T_NAMESPACE:
219 mapi $this->_parseNamespace();
220 mapi break;
221 mapi
222 mapi case ParserTokens::T_USE:
223 mapi $this->_parseUseStatements();
224 mapi break;
225 mapi
226 mapi case ParserTokens::T_DOC_COMMENT;
227 mapi $docComment = $token->image;
228 mapi break;
229 mapi
230 mapi case ParserTokens::T_ABSTRACT:
231 20 mapi $modifiers |= StaticReflectionClass::IS_EXPLICIT_ABSTRACT;
232 18 mapi break;
233 mapi
234 mapi case ParserTokens::T_FINAL:
235 19 mapi $modifiers |= StaticReflectionClass::IS_FINAL;
236 18 mapi break;
237 mapi
238 mapi case ParserTokens::T_CLASS:
239 mapi $class = $this->_parseClassDeclaration( $docComment, $modifiers );
240 mapi break;
241 mapi
242 mapi case ParserTokens::T_INTERFACE:
243 mapi $class = $this->_parseInterfaceDeclaration( $docComment );
244 mapi break;
245 mapi }
246 mapi
247 129 mapi if ( $class === null )
248 19 mapi {
249 129 mapi continue;
250 19 mapi }
251 129 mapi
252 269 mapi $this->_context->addClass( $class );
253 268 mapi
254 129 mapi $class->initStartLine( $token->startLine );
255 mapi $class->initFileName( $this->_pathName );
256 mapi
257 mapi array_push( $classes, $class );
258 mapi
259 mapi $class = null;
260 mapi $modifiers = 0;
261 mapi $docComment = '';
262 18 mapi }
263 129 mapi return $classes;
264 18 mapi }
265 mapi
266 mapi /**
267 163 mapi * This method parses a namespace declaration in both syntax versions that
268 mapi * are valid for PHP. The one terminated with a semicolon and the one with
269 mapi * surrounding curly braces. The parsed namespace will be stored in a local
270 mapi * property and will be used as default namespace for all interfaces and
271 mapi * classes that are parsed later.
272 18 mapi *
273 93 mapi * @return void
274 248 mapi * @throws \pdepend\reflection\exceptions\UnexpectedTokenException When
275 163 mapi * this method detects a token within the token stream that is not
276 mapi * allowed within a namespace declaration.
277 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
278 163 mapi * this method reaches the end of the token stream before it finds
279 mapi * the final token <b>;</b> or <b>{</b>.
280 18 mapi */
281 mapi private function _parseNamespace() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
282 mapi {
283 mapi $this->_namespace = '';
284 mapi $this->_aliasMap = array();
285 mapi
286 mapi while ( is_object( $token = $this->_next() ) )
287 mapi {
288 mapi switch ( $token->type )
289 mapi {
290 23 mapi case ParserTokens::T_DOC_COMMENT:
291 mapi break;
292 mapi
293 18 mapi case ParserTokens::T_STRING:
294 mapi case ParserTokens::T_NS_SEPARATOR:
295 mapi $this->_namespace .= $token->image;
296 mapi break;
297 mapi
298 mapi case ParserTokens::T_SEMICOLON:
299 23 mapi case ParserTokens::T_SCOPE_OPEN:
300 18 mapi return $token;
301 23 mapi
302 mapi default:
303 128 mapi throw new UnexpectedTokenException( $token, $this->_pathName );
304 18 mapi }
305 mapi }
306 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
307 18 mapi }
308 mapi
309 163 mapi /**
310 mapi * This method parses a variable list of use statements.
311 mapi *
312 mapi * <code>
313 mapi * use foo\bar,
314 mapi * foobar as f,
315 mapi * foo\baz as fb;
316 mapi * </code>
317 mapi *
318 mapi * @return void
319 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
320 163 mapi * detects an error during the parsing process.
321 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
322 163 mapi * this method reaches the end of the underlying token stream before
323 mapi * it completes the currently parsed use statement.
324 mapi */
325 18 mapi private function _parseUseStatements()
326 mapi {
327 mapi do
328 mapi {
329 mapi $token = $this->_parseUseStatement();
330 mapi }
331 mapi while ( $token->type === ParserTokens::T_COMMA );
332 mapi }
333 mapi
334 163 mapi /**
335 mapi * This method parses a single use statement with an optional alias
336 mapi * declaration.
337 mapi *
338 mapi * <code>
339 mapi * use foo\bar;
340 mapi * </code>
341 mapi *
342 mapi * Or with an alias:
343 mapi *
344 mapi * <code>
345 mapi * use foo\bar as fb;
346 mapi * </code>
347 mapi *
348 248 mapi * @return \pdepend\reflection\parser\Token
349 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
350 163 mapi * detects an error during the parsing process.
351 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
352 163 mapi * this method reaches the end of the underlying token stream before
353 mapi * it completes the currently parsed use statement.
354 mapi */
355 18 mapi private function _parseUseStatement() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
356 mapi {
357 mapi $namespace = '';
358 mapi $alias = '';
359 mapi
360 mapi while ( is_object( $token = $this->_next() ) )
361 mapi {
362 mapi switch ( $token->type )
363 mapi {
364 mapi case ParserTokens::T_STRING:
365 mapi $alias = $token->image;
366 mapi
367 mapi case ParserTokens::T_NS_SEPARATOR:
368 mapi $namespace .= $token->image;
369 mapi break;
370 mapi
371 mapi case ParserTokens::T_AS:
372 19 mapi $alias = $this->_tokenizer->next()->image;
373 18 mapi break;
374 mapi
375 mapi case ParserTokens::T_COMMA:
376 mapi case ParserTokens::T_SEMICOLON:
377 19 mapi $this->_aliasMap[$alias] = trim( $namespace, '\\' );
378 18 mapi
379 mapi return $token;
380 mapi }
381 mapi }
382 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
383 18 mapi }
384 mapi
385 mapi /**
386 163 mapi * This method parses a complete class declartion, starting from its name,
387 mapi * an optional parent class, implemented interface and its body with methods,
388 mapi * properties and constants.
389 mapi *
390 mapi * @param string $docComment The content of a doc comment token found
391 mapi * directly before the the <b>class</b> keyword.
392 mapi * @param integer $modifiers Optional modifier like <b>abstract</b> or
393 mapi * <b>final</b> that belong to the currently parsed class.
394 mapi *
395 248 mapi * @return \pdepend\reflection\api\StaticReflectionClass
396 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
397 163 mapi * detects an error during the parsing process.
398 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
399 163 mapi * this method reaches the end of the underlying token stream before
400 mapi * it completes the currently parsed class declaration.
401 18 mapi */
402 mapi private function _parseClassDeclaration( $docComment, $modifiers ) pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
403 mapi {
404 221 mapi $this->_consumeComments();
405 18 mapi
406 221 mapi $token = $this->_consumeToken( ParserTokens::T_STRING );
407 mapi $name = $this->_createClassOrInterfaceName( array( $token->image ) );
408 mapi
409 mapi $this->_classOrInterface = new StaticReflectionClass( $name, $docComment, $modifiers );
410 mapi
411 18 mapi while ( is_object( $token = $this->_next() ) )
412 mapi {
413 mapi switch ( $token->type )
414 mapi {
415 mapi case ParserTokens::T_EXTENDS:
416 134 mapi $this->_classOrInterface->initParentClass( $this->_parseClassOrInterface() );
417 18 mapi break;
418 mapi
419 mapi case ParserTokens::T_IMPLEMENTS:
420 93 mapi $this->_classOrInterface->initInterfaces( $this->_parseInterfaceList() );
421 18 mapi break;
422 mapi
423 mapi case ParserTokens::T_SCOPE_OPEN:
424 36 mapi $endLine = $this->_parseClassOrInterfaceScope();
425 18 mapi
426 289 mapi $constants = $this->_evaluateConstants();
427 mapi
428 93 mapi $this->_classOrInterface->initEndLine( $endLine );
429 mapi $this->_classOrInterface->initMethods( $this->_methods );
430 289 mapi $this->_classOrInterface->initConstants( $constants );
431 93 mapi $this->_classOrInterface->initProperties( $this->_properties );
432 mapi
433 mapi return $this->_classOrInterface;
434 18 mapi }
435 mapi }
436 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
437 18 mapi }
438 mapi
439 mapi /**
440 163 mapi * Parses a complement interface declaration with the interface name,
441 mapi * optional parent interfaces and the interface body.
442 mapi *
443 mapi * @param string $docComment The content of a doc comment token found
444 mapi * directly before the the <b>interface</b> keyword.
445 mapi *
446 248 mapi * @return \pdepend\reflection\api\StaticReflectionInterface
447 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
448 163 mapi * detects an error during the parsing process.
449 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
450 163 mapi * this method reaches the end of the token stream before it has
451 mapi * completed the current interface declaration.
452 18 mapi */
453 mapi private function _parseInterfaceDeclaration( $docComment ) pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
454 mapi {
455 221 mapi $this->_consumeComments();
456 18 mapi
457 221 mapi $token = $this->_consumeToken( ParserTokens::T_STRING );
458 mapi $name = $this->_createClassOrInterfaceName( array( $token->image ) );
459 mapi
460 mapi $this->_classOrInterface = new StaticReflectionInterface( $name, $docComment );
461 mapi
462 18 mapi while ( is_object( $token = $this->_next() ) )
463 mapi {
464 mapi switch ( $token->type )
465 mapi {
466 mapi case ParserTokens::T_EXTENDS:
467 93 mapi $this->_classOrInterface->initInterfaces( $this->_parseInterfaceList() );
468 18 mapi break;
469 mapi
470 mapi case ParserTokens::T_SCOPE_OPEN:
471 36 mapi $endLine = $this->_parseClassOrInterfaceScope( StaticReflectionMethod::IS_ABSTRACT );
472 18 mapi
473 289 mapi $constants = $this->_evaluateConstants();
474 mapi
475 93 mapi $this->_classOrInterface->initEndLine( $endLine );
476 mapi $this->_classOrInterface->initMethods( $this->_methods );
477 289 mapi $this->_classOrInterface->initConstants( $constants );
478 93 mapi
479 mapi return $this->_classOrInterface;
480 18 mapi }
481 mapi }
482 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
483 18 mapi }
484 mapi
485 mapi /**
486 163 mapi * This method parses a list of interfaces names as they can occure after
487 mapi * the <b>implements</b> keyword within a class declaration or the
488 mapi * <b>extends</b> keyword in an interface definition. It returns an array
489 mapi * with <b>\ReflectionClass</b> instances for all parsed interface names.
490 mapi *
491 62 mapi * @return array(\ReflectionClass)
492 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
493 163 mapi * detects an error during the parsing process.
494 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
495 163 mapi * this method reaches the end of the underlying token stream before
496 mapi * it completes the interface list parsing process.
497 18 mapi */
498 mapi private function _parseInterfaceList() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
499 mapi {
500 mapi $interfaces = array();
501 19 mapi
502 mapi while ( ( $tokenType = $this->_peek() ) !== Tokenizer::EOF )
503 18 mapi {
504 19 mapi switch ( $tokenType )
505 18 mapi {
506 mapi case ParserTokens::T_STRING:
507 82 mapi case ParserTokens::T_NAMESPACE:
508 18 mapi case ParserTokens::T_NS_SEPARATOR:
509 134 mapi $interfaces[] = $this->_parseClassOrInterface();
510 18 mapi break;
511 mapi
512 mapi case ParserTokens::T_IMPLEMENTS:
513 mapi case ParserTokens::T_SCOPE_OPEN:
514 mapi return $interfaces;
515 19 mapi
516 mapi default:
517 mapi $this->_next();
518 mapi break;
519 18 mapi }
520 mapi }
521 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
522 18 mapi }
523 mapi
524 mapi /**
525 135 mapi * This method parses a single class or interface reference. Such a reference
526 mapi * can be the currently class self or any other class inside or outside of
527 mapi * the currently parsed source.
528 mapi *
529 62 mapi * @return \ReflectionClass
530 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
531 163 mapi * detects an error during the parsing process.
532 18 mapi */
533 134 mapi private function _parseClassOrInterface()
534 18 mapi {
535 109 mapi $className = $this->_parseClassOrInterfaceName();
536 mapi if ( $className === $this->_classOrInterface->getName() )
537 mapi {
538 mapi return $this->_classOrInterface;
539 mapi }
540 263 mapi return $this->_context->getClassReference( $className );
541 18 mapi }
542 mapi
543 mapi /**
544 163 mapi * This method parses a valid PHP class or interface name. This implementation
545 mapi * supports simple PHP < 5.3 names, but also full qualified PHP 5.3 names
546 mapi * with namespace.
547 mapi *
548 18 mapi * @return string
549 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
550 163 mapi * detects an error during the parsing process.
551 18 mapi */
552 mapi private function _parseClassOrInterfaceName()
553 mapi {
554 96 mapi return $this->_createClassOrInterfaceName( $this->_parseIdentifier() );
555 mapi }
556 mapi
557 163 mapi /**
558 mapi * This method parses a valid PHP identifier for classes, interfaces,
559 mapi * constants or functions. It will handles simple PHP < 5.3 identifies, but
560 mapi * also namespaced class names, function calls or constant references. The
561 mapi * returned array contains all tokens that are part of the identifier.
562 mapi *
563 mapi * @return array(string)
564 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When the parser
565 163 mapi * detects an error during the identifier parsing process.
566 mapi */
567 96 mapi private function _parseIdentifier() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
568 mapi {
569 19 mapi $name = array();
570 18 mapi
571 19 mapi $this->_consumeComments();
572 82 mapi if ( $this->_peek() === ParserTokens::T_NAMESPACE )
573 18 mapi {
574 82 mapi $this->_consumeToken( ParserTokens::T_NAMESPACE );
575 mapi
576 mapi $name[] = '\\';
577 mapi $name[] = $this->_namespace;
578 96 mapi
579 82 mapi $this->_consumeComments();
580 mapi $name[] = $this->_consumeToken( ParserTokens::T_NS_SEPARATOR )->image;
581 mapi }
582 mapi else if ( $this->_peek() === ParserTokens::T_NS_SEPARATOR )
583 mapi {
584 19 mapi $name[] = $this->_next()->image;
585 mapi }
586 18 mapi
587 19 mapi while ( $this->_peek() !== Tokenizer::EOF )
588 mapi {
589 mapi $this->_consumeComments();
590 mapi $token = $this->_consumeToken( ParserTokens::T_STRING );
591 18 mapi
592 19 mapi $name[] = $token->image;
593 mapi
594 mapi $this->_consumeComments();
595 mapi if ( $this->_peek() === ParserTokens::T_NS_SEPARATOR )
596 mapi {
597 mapi $name[] = $this->_next()->image;
598 18 mapi }
599 19 mapi else
600 mapi {
601 mapi break;
602 mapi }
603 18 mapi }
604 96 mapi return $name;
605 18 mapi }
606 mapi
607 163 mapi /**
608 mapi * This method parses the body of a class or interface. When this method has
609 mapi * reached the end of the body it will return the line number of the closing
610 mapi * curly brace.
611 mapi *
612 mapi * @param integer $defaultModifiers Optional default modifiers for detected
613 mapi * methods or properties within the class or interface body.
614 mapi *
615 mapi * @return integer
616 248 mapi * @throws \pdepend\reflection\exceptions\UnexpectedTokenException When
617 163 mapi * the parser detects an unexpected token within the body of the
618 mapi * currently parsed class or interface.
619 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
620 163 mapi * the parser reaches the end of the token stream before it has
621 mapi * reached the end of the class or interface body.
622 mapi */
623 18 mapi private function _parseClassOrInterfaceScope( $defaultModifiers = 0 ) pdepend-error pdepend-warning pdepend-warning pdepend-error pdepend-error pdepend-error pdepend-error pdepend-error pdepend-warning pdepend-warning pdepend-warning pdepend-warning
624 mapi {
625 36 mapi $this->_methods = array();
626 mapi $this->_constants = array();
627 mapi $this->_properties = array();
628 18 mapi
629 19 mapi $modifiers = $defaultModifiers | StaticReflectionMethod::IS_PUBLIC;
630 18 mapi $docComment = '';
631 278 mapi $startLine = -1;
632 18 mapi
633 19 mapi while ( ( $tokenType = $this->_peek() ) !== Tokenizer::EOF )
634 18 mapi {
635 19 mapi switch ( $tokenType )
636 18 mapi {
637 mapi case ParserTokens::T_DOC_COMMENT:
638 19 mapi $token = $this->_consumeToken( ParserTokens::T_DOC_COMMENT );
639 mapi $docComment = $token->image;
640 18 mapi break;
641 mapi
642 mapi case ParserTokens::T_SCOPE_CLOSE:
643 22 mapi $token = $this->_consumeToken( ParserTokens::T_SCOPE_CLOSE );
644 18 mapi
645 36 mapi return $token->endLine;
646 22 mapi
647 18 mapi case ParserTokens::T_ABSTRACT:
648 278 mapi $token = $this->_consumeToken( ParserTokens::T_ABSTRACT );
649 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
650 19 mapi $modifiers |= StaticReflectionMethod::IS_ABSTRACT;
651 18 mapi break;
652 mapi
653 mapi case ParserTokens::T_FINAL:
654 278 mapi $token = $this->_consumeToken( ParserTokens::T_FINAL );
655 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
656 19 mapi $modifiers |= StaticReflectionMethod::IS_FINAL;
657 18 mapi break;
658 mapi
659 mapi case ParserTokens::T_PUBLIC:
660 278 mapi $token = $this->_consumeToken( ParserTokens::T_PUBLIC );
661 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
662 19 mapi $modifiers |= StaticReflectionMethod::IS_PUBLIC;
663 18 mapi break;
664 mapi
665 mapi case ParserTokens::T_PRIVATE:
666 278 mapi $token = $this->_consumeToken( ParserTokens::T_PRIVATE );
667 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
668 19 mapi $modifiers ^= StaticReflectionMethod::IS_PUBLIC;
669 mapi $modifiers |= StaticReflectionMethod::IS_PRIVATE;
670 18 mapi break;
671 mapi
672 mapi case ParserTokens::T_PROTECTED:
673 278 mapi $token = $this->_consumeToken( ParserTokens::T_PROTECTED );
674 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
675 19 mapi $modifiers ^= StaticReflectionMethod::IS_PUBLIC;
676 mapi $modifiers |= StaticReflectionMethod::IS_PROTECTED;
677 18 mapi break;
678 mapi
679 mapi case ParserTokens::T_STATIC:
680 278 mapi $token = $this->_consumeToken( ParserTokens::T_STATIC );
681 mapi $startLine = ( $startLine === -1 ? $token->startLine : $startLine );
682 19 mapi $modifiers |= StaticReflectionMethod::IS_STATIC;
683 18 mapi break;
684 mapi
685 36 mapi case ParserTokens::T_CONST:
686 134 mapi $this->_parseConstantDefinitions();
687 36 mapi break;
688 mapi
689 18 mapi case ParserTokens::T_FUNCTION:
690 278 mapi $this->_parseMethodDeclaration( $docComment, $modifiers, $startLine );
691 24 mapi
692 19 mapi $modifiers = $defaultModifiers | StaticReflectionMethod::IS_PUBLIC;
693 18 mapi $docComment = '';
694 278 mapi $startLine = -1;
695 18 mapi break;
696 mapi
697 mapi case ParserTokens::T_VARIABLE:
698 36 mapi $this->_parsePropertyDeclarations( $docComment, $modifiers );
699 19 mapi
700 mapi $modifiers = $defaultModifiers | StaticReflectionMethod::IS_PUBLIC;
701 mapi $docComment = '';
702 278 mapi $startLine = -1;
703 18 mapi break;
704 36 mapi
705 mapi default:
706 128 mapi throw new UnexpectedTokenException( $this->_next(), $this->_pathName );
707 18 mapi }
708 mapi }
709 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
710 18 mapi }
711 mapi
712 31 mapi /**
713 mapi * Parses a method declaration for/from the currently parsed class/interface.
714 mapi *
715 mapi * @param string $docComment Optional doc comment for the parsed method.
716 mapi * @param integer $modifiers Bitfield with method modifiers.
717 278 mapi * @param integer $startLine Optional start line number of the first modifier
718 mapi * or -1 which means that the function token is on the first line.
719 31 mapi *
720 81 mapi * @return void
721 31 mapi */
722 278 mapi private function _parseMethodDeclaration( $docComment, $modifiers, $startLine ) pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
723 18 mapi {
724 125 mapi $this->_staticVariables = array();
725 mapi
726 278 mapi $token = $this->_consumeToken( ParserTokens::T_FUNCTION );
727 mapi
728 mapi $startLine = ( $startLine < 1 ? $token->startLine : $startLine );
729 75 mapi $returnsRef = $this->_parseOptionalByReference();
730 18 mapi
731 81 mapi $this->_consumeComments();
732 mapi $token = $this->_consumeToken( ParserTokens::T_STRING );
733 mapi
734 113 mapi $this->_methods[] = new StaticReflectionMethod( $token->image, $docComment, $modifiers);
735 mapi
736 81 mapi $this->_parseMethodParameterList();
737 mapi
738 mapi $this->_consumeComments();
739 mapi if ( $this->_peek() === ParserTokens::T_SEMICOLON )
740 18 mapi {
741 81 mapi $endLine = $this->_consumeToken( ParserTokens::T_SEMICOLON )->endLine;
742 mapi }
743 mapi else
744 mapi {
745 134 mapi $endLine = $this->_parseMethodBody()->endLine;
746 81 mapi }
747 mapi
748 113 mapi $method = end( $this->_methods );
749 81 mapi $method->initStartLine( $startLine );
750 mapi $method->initEndLine( $endLine );
751 mapi $method->initParameters( $this->_parameters );
752 125 mapi $method->initStaticVariables( $this->_staticVariables );
753 81 mapi
754 mapi if ( $returnsRef )
755 mapi {
756 mapi $method->initReturnsReference();
757 mapi }
758 mapi }
759 mapi
760 mapi /**
761 mapi * Parses the signature of a method, which means everything starting from
762 mapi * the opening <b>(</b> parenthesis until the closing parenthesis <b>)</b>.
763 mapi *
764 mapi * @return void
765 mapi */
766 mapi private function _parseMethodParameterList()
767 mapi {
768 mapi $this->_consumeComments();
769 mapi $this->_consumeToken( ParserTokens::T_BLOCK_OPEN );
770 mapi
771 mapi $this->_parameters = array();
772 mapi while ( $this->_parseMethodParameter() )
773 mapi {
774 mapi $this->_consumeComments();
775 mapi if ( $this->_peek() !== ParserTokens::T_COMMA )
776 18 mapi {
777 81 mapi break;
778 mapi }
779 mapi $this->_consumeToken( ParserTokens::T_COMMA );
780 mapi }
781 mapi $this->_consumeToken( ParserTokens::T_BLOCK_CLOSE );
782 mapi }
783 18 mapi
784 81 mapi /**
785 mapi * Parses a single method parameter and returns <b>true</b> when a parameter
786 mapi * was found. Otherwise this method will return <b>false</b>.
787 mapi *
788 mapi * @return boolean
789 mapi */
790 mapi private function _parseMethodParameter() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
791 mapi {
792 mapi $typeHint = $this->_parseOptionalMethodParameterTypeHint();
793 mapi $byRef = $this->_parseOptionalByReference();
794 31 mapi
795 81 mapi $this->_consumeComments();
796 mapi if ( $this->_peek() !== ParserTokens::T_VARIABLE )
797 mapi {
798 mapi return false;
799 mapi }
800 18 mapi
801 81 mapi $token = $this->_consumeToken( ParserTokens::T_VARIABLE );
802 31 mapi
803 102 mapi $parameter = new StaticReflectionParameter( $token->image, count( $this->_parameters ) );
804 192 mapi $parameter->initStaticReflectionValue( $this->_parseOptionalStaticReflectionValue() );
805 75 mapi
806 84 mapi if ( $byRef )
807 mapi {
808 mapi $parameter->initPassedByReference();
809 mapi }
810 85 mapi if ( $typeHint )
811 mapi {
812 mapi $parameter->initTypeHint( $typeHint );
813 mapi }
814 36 mapi
815 84 mapi $this->_parameters[] = $parameter;
816 mapi
817 81 mapi return true;
818 mapi }
819 mapi
820 mapi /**
821 mapi * Parses an optional parameter type-hint and returns a reflection class
822 mapi * instance for a type type-hint, <b>true</b> for an array type-hint or
823 mapi * <b>false</b> when no type hint exists.
824 mapi *
825 mapi * @return \ReflectionClass|boolean
826 mapi */
827 mapi private function _parseOptionalMethodParameterTypeHint()
828 mapi {
829 mapi $this->_consumeComments();
830 mapi switch ( $this->_peek() )
831 mapi {
832 107 mapi case ParserTokens::T_ARRAY:
833 mapi $this->_consumeToken( ParserTokens::T_ARRAY );
834 mapi return true;
835 mapi
836 84 mapi case ParserTokens::T_STRING:
837 mapi case ParserTokens::T_NAMESPACE:
838 81 mapi case ParserTokens::T_NS_SEPARATOR:
839 134 mapi return $this->_parseClassOrInterface();
840 18 mapi }
841 81 mapi return false;
842 18 mapi }
843 mapi
844 75 mapi /**
845 mapi * Parses an optional by reference flag from the token stream and returns
846 mapi * <b>true</b> when a by reference token was found, otherwise the return
847 mapi * value will be <b>false</b>.
848 mapi *
849 mapi * @return boolean
850 mapi */
851 mapi private function _parseOptionalByReference()
852 mapi {
853 mapi $this->_consumeComments();
854 mapi if ( $this->_peek() === ParserTokens::T_BITWISE_AND )
855 mapi {
856 mapi $this->_consumeToken( ParserTokens::T_BITWISE_AND );
857 mapi $this->_consumeComments();
858 mapi return true;
859 mapi }
860 mapi return false;
861 mapi }
862 mapi
863 134 mapi /**
864 mapi * This method parses a variable, comma separated list of properties. All
865 mapi * parsed properties will be stored in the parser property <b>$_properties</b>.
866 mapi *
867 mapi * @param string $docComment The doc comment for the next property.
868 mapi * @param integer $modifiers The specified property modifiers.
869 mapi *
870 mapi * @return void
871 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
872 134 mapi * error occured during body parsing.
873 mapi */
874 19 mapi private function _parsePropertyDeclarations( $docComment, $modifiers )
875 18 mapi {
876 19 mapi $this->_consumeComments();
877 36 mapi $this->_parsePropertyDeclaration( $docComment, $modifiers );
878 19 mapi
879 mapi $this->_consumeComments();
880 mapi while ( ( $tokensType = $this->_peek() ) === ParserTokens::T_COMMA )
881 mapi {
882 mapi $this->_consumeToken( ParserTokens::T_COMMA );
883 mapi
884 36 mapi $docComment = $this->_consumeComments();
885 mapi $this->_parsePropertyDeclaration( $docComment, $modifiers );
886 19 mapi
887 mapi $this->_consumeComments();
888 mapi }
889 mapi $this->_consumeToken( ParserTokens::T_SEMICOLON );
890 18 mapi }
891 mapi
892 98 mapi /**
893 134 mapi * Parses a single property declaration. A variable declaration consists at
894 mapi * least of a variable name. Additionally it can contain a default value
895 mapi * definition.
896 98 mapi *
897 134 mapi * All parsed properties will be stored in the parser property
898 mapi * <b>$_properties</b>.
899 mapi *
900 98 mapi * @param string $docComment The doc comment for the next property.
901 mapi * @param integer $modifiers The specified property modifiers.
902 mapi *
903 mapi * @return void
904 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
905 134 mapi * error occured during body parsing.
906 98 mapi */
907 19 mapi private function _parsePropertyDeclaration( $docComment, $modifiers )
908 mapi {
909 mapi $this->_consumeComments();
910 mapi $token = $this->_consumeToken( ParserTokens::T_VARIABLE );
911 mapi
912 98 mapi $property = new StaticReflectionProperty( $token->image, $docComment, $modifiers );
913 192 mapi $property->initValue( $this->_parseOptionalStaticReflectionValue() );
914 102 mapi
915 98 mapi $this->_properties[] = $property;
916 19 mapi }
917 mapi
918 134 mapi /**
919 mapi * This method parses a variable amount of constant definitions. A single
920 mapi * <b>const</b> can contain various constant definitions, separated by
921 mapi * a comma.
922 mapi *
923 mapi * All found constant definitions will be stored in the parser's property
924 mapi * <b>$_constants</b>.
925 mapi *
926 mapi * @return void
927 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
928 134 mapi * error occured during body parsing.
929 mapi */
930 mapi private function _parseConstantDefinitions()
931 36 mapi {
932 mapi $this->_consumeToken( ParserTokens::T_CONST );
933 134 mapi $this->_parseConstantDefinition();
934 36 mapi
935 mapi $this->_consumeComments();
936 mapi while ( ($tokenType = $this->_peek() ) === ParserTokens::T_COMMA )
937 mapi {
938 mapi $this->_consumeToken( ParserTokens::T_COMMA );
939 134 mapi $this->_parseConstantDefinition();
940 36 mapi $this->_consumeComments();
941 mapi }
942 mapi $this->_consumeToken( ParserTokens::T_SEMICOLON );
943 mapi }
944 mapi
945 95 mapi /**
946 134 mapi * This method parses a single constant declaration. A constant definitions
947 mapi * consists of a constant identifier, a <b>T_EQUAL</b> token and any valid
948 mapi * static scalar value.
949 95 mapi *
950 134 mapi * The parsed constant will be stored in the property <b>$_constants</b>.
951 mapi *
952 95 mapi * @return void
953 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
954 134 mapi * error occured during body parsing.
955 248 mapi * @see \pdepend\reflection\parser\Parser::_parseStaticScalar()
956 95 mapi */
957 134 mapi private function _parseConstantDefinition()
958 36 mapi {
959 mapi $this->_consumeComments();
960 mapi $token = $this->_consumeToken( ParserTokens::T_STRING );
961 mapi
962 95 mapi $this->_consumeComments();
963 mapi $this->_consumeToken( ParserTokens::T_EQUAL );
964 mapi
965 96 mapi $this->_constants[$token->image] = $this->_parseStaticScalar();
966 36 mapi }
967 mapi
968 113 mapi /**
969 mapi * Parses an optional default as it can occure for property or parameter
970 134 mapi * nodes. The return value of this method will be <b>null</b> when no
971 mapi * default value exists.
972 113 mapi *
973 248 mapi * @return \pdepend\reflection\api\StaticReflectionValue
974 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
975 134 mapi * error occured during body parsing.
976 113 mapi */
977 192 mapi private function _parseOptionalStaticReflectionValue()
978 113 mapi {
979 mapi $this->_consumeComments();
980 mapi if ( $this->_peek() === ParserTokens::T_EQUAL )
981 mapi {
982 mapi $this->_consumeToken( ParserTokens::T_EQUAL );
983 192 mapi return $this->_parseStaticReflectionValue();
984 113 mapi }
985 mapi return null;
986 mapi }
987 mapi
988 mapi /**
989 mapi * Parses an optional default as it can occure for property or parameter
990 mapi * nodes.
991 mapi *
992 248 mapi * @return \pdepend\reflection\api\StaticReflectionValue
993 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
994 134 mapi * error occured during body parsing.
995 113 mapi */
996 192 mapi private function _parseStaticReflectionValue()
997 113 mapi {
998 192 mapi return new StaticReflectionValue( $this->_parseStaticScalarOrArray() );
999 113 mapi }
1000 mapi
1001 134 mapi /**
1002 mapi * This method parses any valid static scalar value as it can be used for
1003 mapi * constant, parameter or property default values.
1004 mapi *
1005 mapi * @return mixed
1006 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
1007 134 mapi * error occured during body parsing.
1008 mapi */
1009 113 mapi private function _parseStaticScalarOrArray()
1010 mapi {
1011 mapi $this->_consumeComments();
1012 mapi if ( $this->_peek() === ParserTokens::T_ARRAY )
1013 mapi {
1014 mapi return $this->_parseStaticArray();
1015 mapi }
1016 mapi return $this->_parseStaticScalar();
1017 mapi }
1018 mapi
1019 134 mapi /**
1020 mapi * This method parses a static array. Static arrays can be found as default
1021 mapi * value for method parameters or class property default values.
1022 mapi *
1023 mapi * @return array
1024 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
1025 134 mapi * error occured during body parsing.
1026 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
1027 134 mapi * this method does not find any token left on the current token
1028 mapi * stream.
1029 mapi */
1030 113 mapi private function _parseStaticArray() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
1031 mapi {
1032 mapi $this->_consumeComments();
1033 mapi $this->_consumeToken( ParserTokens::T_ARRAY );
1034 mapi
1035 mapi $this->_consumeComments();
1036 mapi $this->_consumeToken( ParserTokens::T_BLOCK_OPEN );
1037 mapi
1038 mapi $array = array();
1039 mapi
1040 mapi while ( ( $tokenType = $this->_peek() ) !== Tokenizer::EOF )
1041 mapi {
1042 mapi if ( $tokenType === ParserTokens::T_BLOCK_CLOSE )
1043 mapi {
1044 mapi break;
1045 mapi }
1046 mapi
1047 mapi $keyOrValue = $this->_parseStaticScalarOrArray();
1048 mapi
1049 mapi $this->_consumeComments();
1050 mapi if ( $this->_peek() === ParserTokens::T_COMMA )
1051 mapi {
1052 mapi $array[] = $keyOrValue;
1053 mapi }
1054 mapi else if ( $this->_peek() !== ParserTokens::T_BLOCK_CLOSE )
1055 mapi {
1056 mapi $array[$keyOrValue] = $this->_parseStaticScalarOrArray();
1057 mapi }
1058 mapi
1059 mapi $this->_consumeComments();
1060 132 mapi if ( $this->_peek() === ParserTokens::T_COMMA )
1061 mapi {
1062 mapi $this->_consumeToken( ParserTokens::T_COMMA );
1063 mapi }
1064 mapi
1065 mapi $this->_consumeComments();
1066 113 mapi }
1067 mapi
1068 mapi $this->_consumeComments();
1069 mapi $this->_consumeToken( ParserTokens::T_BLOCK_CLOSE );
1070 mapi
1071 mapi return $array;
1072 mapi }
1073 mapi
1074 134 mapi /**
1075 mapi * This method parses a single static scalar value as it can be found as
1076 mapi * constant default value or as default value for properties or parameters.
1077 mapi *
1078 mapi * @return mixed
1079 248 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
1080 134 mapi * error occured during body parsing.
1081 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
1082 134 mapi * this method does not find any token left on the current token
1083 mapi * stream.
1084 mapi */
1085 36 mapi private function _parseStaticScalar() pdepend-error pdepend-error pdepend-warning pdepend-error pdepend-error pdepend-error pdepend-warning pdepend-warning pdepend-error pdepend-warning pdepend-error pdepend-error pdepend-warning pdepend-error pdepend-warning
1086 mapi {
1087 mapi $this->_consumeComments();
1088 101 mapi switch ( $this->_peek() )
1089 36 mapi {
1090 138 mapi case ParserTokens::T_DIR:
1091 mapi $this->_consumeToken( ParserTokens::T_DIR );
1092 mapi return dirname( $this->_pathName );
1093 mapi
1094 110 mapi case ParserTokens::T_FILE:
1095 mapi $this->_consumeToken( ParserTokens::T_FILE );
1096 128 mapi return $this->_pathName;
1097 110 mapi
1098 112 mapi case ParserTokens::T_LINE:
1099 mapi return $this->_consumeToken( ParserTokens::T_LINE )->startLine;
1100 mapi
1101 mapi case ParserTokens::T_CLASS_C:
1102 mapi $this->_consumeToken( ParserTokens::T_CLASS_C );
1103 mapi return $this->_classOrInterface->getName();
1104 mapi
1105 113 mapi case ParserTokens::T_NS_C:
1106 mapi $this->_consumeToken( ParserTokens::T_NS_C );
1107 mapi return $this->_classOrInterface->getNamespaceName();
1108 mapi
1109 mapi case ParserTokens::T_FUNCTION_C:
1110 mapi $this->_consumeToken( ParserTokens::T_FUNCTION_C );
1111 mapi return end( $this->_methods )->getName();
1112 mapi
1113 mapi case ParserTokens::T_METHOD_C:
1114 mapi $this->_consumeToken( ParserTokens::T_METHOD_C );
1115 mapi return sprintf(
1116 mapi '%s::%s',
1117 mapi $this->_classOrInterface->getName(),
1118 mapi end( $this->_methods )->getName()
1119 mapi );
1120 mapi
1121 101 mapi case ParserTokens::T_NULL;
1122 mapi $this->_consumeToken( ParserTokens::T_NULL );
1123 mapi return null;
1124 97 mapi
1125 101 mapi case ParserTokens::T_TRUE:
1126 mapi $this->_consumeToken( ParserTokens::T_TRUE );
1127 mapi return true;
1128 99 mapi
1129 101 mapi case ParserTokens::T_FALSE:
1130 mapi $this->_consumeToken( ParserTokens::T_FALSE );
1131 mapi return false;
1132 98 mapi
1133 101 mapi case ParserTokens::T_TEXT:
1134 mapi $text = $this->_consumeToken( ParserTokens::T_TEXT )->image;
1135 mapi $text = str_replace( '\\' . substr( $text, 0, 1 ), substr( $text, 0, 1 ), $text );
1136 mapi return substr( $text, 1, -1 );
1137 99 mapi
1138 101 mapi case ParserTokens::T_DNUMBER:
1139 mapi return (float) $this->_consumeToken( ParserTokens::T_DNUMBER )->image;
1140 99 mapi
1141 101 mapi case ParserTokens::T_LNUMBER:
1142 mapi return (int) $this->_consumeToken( ParserTokens::T_LNUMBER )->image;
1143 96 mapi
1144 101 mapi case ParserTokens::T_SELF:
1145 mapi case ParserTokens::T_PARENT:
1146 289 mapi $value = $this->_consumeToken( $this->_peek() )->image;
1147 mapi
1148 101 mapi $this->_consumeComments();
1149 124 mapi $value .= $this->_consumeToken( ParserTokens::T_DOUBLE_COLON )->image;
1150 mapi $this->_consumeComments();
1151 101 mapi $value .= $this->_consumeToken( ParserTokens::T_STRING )->image;
1152 113 mapi
1153 289 mapi return $this->_evaluateConstantExpression( $value );
1154 96 mapi
1155 101 mapi case ParserTokens::T_STRING:
1156 mapi $parts = $this->_parseIdentifier();
1157 96 mapi
1158 101 mapi $this->_consumeComments();
1159 96 mapi
1160 289 mapi $value = '';
1161 124 mapi if ( $this->_peek() === ParserTokens::T_DOUBLE_COLON )
1162 101 mapi {
1163 mapi $value .= $this->_createClassOrInterfaceName( $parts );
1164 124 mapi $value .= $this->_consumeToken( ParserTokens::T_DOUBLE_COLON )->image;
1165 mapi $this->_consumeComments();
1166 101 mapi $value .= $this->_consumeToken( ParserTokens::T_STRING )->image;
1167 mapi }
1168 mapi else if ( count( $parts ) === 1 )
1169 mapi {
1170 mapi $value .= array_shift( $parts );
1171 mapi }
1172 mapi else
1173 mapi {
1174 mapi $value .= $this->_createClassOrInterfaceName( $parts );
1175 mapi }
1176 289 mapi return $this->_evaluateConstantExpression( $value );
1177 96 mapi
1178 163 mapi case ParserTokens::T_NAMESPACE:
1179 mapi case ParserTokens::T_NS_SEPARATOR:
1180 289 mapi $value = $this->_parseClassOrInterfaceName();
1181 96 mapi
1182 101 mapi $this->_consumeComments();
1183 124 mapi if ( $this->_peek() === ParserTokens::T_DOUBLE_COLON )
1184 101 mapi {
1185 124 mapi $value .= $this->_consumeToken( ParserTokens::T_DOUBLE_COLON )->image;
1186 mapi $this->_consumeComments();
1187 101 mapi $value .= $this->_consumeToken( ParserTokens::T_STRING )->image;
1188 mapi }
1189 289 mapi return $this->_evaluateConstantExpression( $value );
1190 36 mapi }
1191 163 mapi throw new UnexpectedTokenException( $this->_next(), $this->_pathName );
1192 36 mapi }
1193 mapi
1194 134 mapi /**
1195 289 mapi * Tries to evaluate a given constant against constants available during the
1196 mapi * parsing process.
1197 mapi *
1198 mapi * @param string $expression The constant expression.
1199 mapi *
1200 mapi * @return mixed
1201 mapi */
1202 mapi private function _evaluateConstantExpression( $expression )
1203 mapi {
1204 mapi if ( stripos( $expression, 'parent::' ) === false && defined( $expression ) )
1205 mapi {
1206 mapi return constant( $expression );
1207 mapi }
1208 mapi return '__StaticReflectionConstantValue(' . $expression . ')';
1209 mapi }
1210 mapi
1211 mapi /**
1212 mapi * Evaluates constants is the context of the currently parsed class or
1213 mapi * interface instance.
1214 mapi *
1215 mapi * @return array(string=>mixed)
1216 mapi */
1217 mapi private function _evaluateConstants() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
1218 mapi {
1219 mapi $regexp = '(__StaticReflectionConstantValue\(self::(.*)\))i';
1220 mapi
1221 mapi while ( true )
1222 mapi {
1223 mapi $evaluated = false;
1224 mapi foreach ( $this->_constants as $name => $value )
1225 mapi {
1226 mapi if ( preg_match( $regexp, $value, $match ) === 0 )
1227 mapi {
1228 mapi continue;
1229 mapi }
1230 mapi
1231 mapi if ( !isset( $this->_constants[$match[1]] ) )
1232 mapi {
1233 mapi continue;
1234 mapi }
1235 mapi $this->_constants[$name] = $this->_constants[$match[1]];
1236 mapi
1237 mapi $evaluated = true;
1238 mapi }
1239 mapi
1240 mapi if ( !$evaluated )
1241 mapi {
1242 mapi break;
1243 mapi }
1244 mapi }
1245 mapi
1246 mapi return $this->_constants;
1247 mapi }
1248 mapi
1249 mapi /**
1250 134 mapi * This method parses the body of a method. It expects that the first token
1251 mapi * found on the token stream is of type <b>T_SCOPE_OPEN</b>.
1252 mapi *
1253 248 mapi * @return \pdepend\reflection\parser\Token
1254 mapi * @throws \pdepend\reflection\exceptions\ParserException When any
1255 134 mapi * error occured during body parsing.
1256 248 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
1257 134 mapi * this method reaches the end of the token stream and the parsed
1258 mapi * method body is still open.
1259 mapi */
1260 mapi private function _parseMethodBody() pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning pdepend-warning
1261 18 mapi {
1262 81 mapi $this->_consumeComments();
1263 mapi $this->_consumeToken( ParserTokens::T_SCOPE_OPEN );
1264 mapi
1265 18 mapi $scope = 1;
1266 mapi
1267 mapi while ( is_object( $token = $this->_next() ) )
1268 mapi {
1269 mapi switch ( $token->type )
1270 mapi {
1271 mapi case ParserTokens::T_SCOPE_OPEN:
1272 mapi ++$scope;
1273 mapi break;
1274 mapi
1275 mapi case ParserTokens::T_SCOPE_CLOSE:
1276 mapi --$scope;
1277 mapi break;
1278 125 mapi
1279 mapi case ParserTokens::T_STATIC:
1280 mapi $this->_consumeComments();
1281 mapi if ( $this->_peek() === ParserTokens::T_VARIABLE )
1282 mapi {
1283 mapi $this->_parseStaticVariables();
1284 mapi }
1285 mapi break;
1286 18 mapi }
1287 mapi
1288 mapi if ( $scope === 0 )
1289 mapi {
1290 24 mapi return $token;
1291 18 mapi }
1292 mapi }
1293 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
1294 18 mapi }
1295 mapi
1296 134 mapi /**
1297 mapi * This method parses a variable amount of static variables as they can be
1298 mapi * declared in the body of a function or method. These variables will be
1299 mapi * stored in the parser's property <b>$_staticVariables</b>.
1300 mapi *
1301 mapi * <code>
1302 mapi * function foo()
1303 mapi * {
1304 mapi * static $foo = 42, $bar;
1305 mapi * static $baz = true;
1306 mapi * }
1307 mapi * </code>
1308 mapi *
1309 mapi * @return void
1310 mapi */
1311 125 mapi private function _parseStaticVariables() pdepend-warning pdepend-warning pdepend-warning
1312 mapi {
1313 mapi do
1314 mapi {
1315 mapi $this->_parseStaticVariable();
1316 mapi $this->_consumeComments();
1317 mapi
1318 mapi if ( $this->_peek() === ParserTokens::T_COMMA )
1319 mapi {
1320 mapi $this->_consumeToken( ParserTokens::T_COMMA );
1321 mapi $this->_consumeComments();
1322 mapi }
1323 mapi else
1324 mapi {
1325 mapi break;
1326 mapi }
1327 mapi }
1328 mapi while ( $this->_peek() === ParserTokens::T_VARIABLE );
1329 mapi
1330 mapi $this->_consumeToken( ParserTokens::T_SEMICOLON );
1331 mapi }
1332 mapi
1333 134 mapi /**
1334 mapi * This method parses a single static variable as it can be declared in the
1335 mapi * body of a function or method. The parsed variable will be stored in the
1336 mapi * <b>$_staticVariables</b> property of this parser.
1337 mapi *
1338 mapi * <code>
1339 mapi * function foo()
1340 mapi * {
1341 mapi * static $foo = 42, $bar;
1342 mapi * static $baz = true;
1343 mapi * }
1344 mapi * </code>
1345 mapi *
1346 mapi * @return void
1347 mapi */
1348 125 mapi private function _parseStaticVariable()
1349 mapi {
1350 mapi $this->_consumeComments();
1351 mapi
1352 126 mapi $name = $this->_consumeToken( ParserTokens::T_VARIABLE )->image;
1353 192 mapi $value = $this->_parseOptionalStaticReflectionValue();
1354 125 mapi
1355 mapi if ( is_object( $value ) )
1356 mapi {
1357 mapi $this->_staticVariables[$name] = $value->getData();
1358 mapi }
1359 mapi else
1360 mapi {
1361 mapi $this->_staticVariables[$name] = null;
1362 mapi }
1363 mapi }
1364 mapi
1365 18 mapi /**
1366 133 mapi * This method creates a qualified class/interface name from the given
1367 mapi * identifier fragments array. This means that the method will expand
1368 mapi * namespace aliases and local class names into full qualified class names
1369 mapi * within the currently parsed namespace.
1370 18 mapi *
1371 133 mapi * @param array(string) $identifierFragments Array with string tokens that
1372 mapi * were found during identifier parsing.
1373 mapi *
1374 18 mapi * @return string
1375 mapi */
1376 133 mapi private function _createClassOrInterfaceName( array $identifierFragments )
1377 18 mapi {
1378 133 mapi if ( isset( $this->_aliasMap[$identifierFragments[0]] ) )
1379 18 mapi {
1380 133 mapi $identifierFragments[0] = $this->_aliasMap[$identifierFragments[0]];
1381 18 mapi }
1382 133 mapi else if ( $identifierFragments[0] !== '\\' )
1383 18 mapi {
1384 133 mapi array_unshift( $identifierFragments, $this->_namespace, '\\' );
1385 18 mapi }
1386 133 mapi return trim( join( '', $identifierFragments ), '\\' );
1387 18 mapi }
1388 mapi
1389 mapi /**
1390 133 mapi * This method consumes the next token from the underlying token stream.
1391 mapi * Then it checks that the found token is of the given type and throws an
1392 mapi * exception when actual and expected token type do not match.
1393 19 mapi *
1394 133 mapi * @param integer $tokenType The expected token type.
1395 mapi *
1396 248 mapi * @return \pdepend\reflection\parser\Token
1397 mapi * @throws \pdepend\reflection\exceptions\EndOfTokenStreamException When
1398 133 mapi * the end of the token stream was reached and no next token exists.
1399 248 mapi * @throws \pdepend\reflection\exceptions\UnexpectedTokenException When
1400 133 mapi * the found token type and the expected token type do not match.
1401 18 mapi */
1402 19 mapi private function _consumeToken( $tokenType )
1403 mapi {
1404 mapi if ( is_object( $token = $this->_next() ) === false )
1405 mapi {
1406 128 mapi throw new EndOfTokenStreamException( $this->_pathName );
1407 19 mapi }
1408 mapi if ( $token->type !== $tokenType )
1409 mapi {
1410 128 mapi throw new UnexpectedTokenException( $token, $this->_pathName );
1411 19 mapi }
1412 mapi return $token;
1413 mapi }
1414 mapi
1415 133 mapi /**
1416 mapi * Consumes a variable amount of comment tokens at the current token stream
1417 mapi * position. The return value of this method contains the comment image of
1418 mapi * the last consumed comment or an empty string when no comment was found.
1419 mapi *
1420 mapi * @return string
1421 mapi */
1422 19 mapi private function _consumeComments()
1423 mapi {
1424 mapi $comment = '';
1425 mapi while ( $this->_peek() === ParserTokens::T_DOC_COMMENT )
1426 mapi {
1427 mapi $comment = $this->_next()->image;
1428 mapi }
1429 mapi return $comment;
1430 mapi }
1431 mapi
1432 mapi /**
1433 133 mapi * This method returns the type code of the next available token or the
1434 mapi * <b>Tokenizer::EOF</b> flag when no next token exists.
1435 mapi *
1436 mapi * @return integer
1437 19 mapi */
1438 18 mapi private function _peek()
1439 mapi {
1440 mapi if ( is_object( $token = $this->_tokenizer->peek() ) )
1441 mapi {
1442 19 mapi return $token->type;
1443 18 mapi }
1444 19 mapi return $token;
1445 18 mapi }
1446 mapi
1447 mapi /**
1448 133 mapi * This method returns the next available token instance or <b>null</b> when
1449 mapi * no next token exists.
1450 mapi *
1451 248 mapi * @return \pdepend\reflection\parser\Token
1452 18 mapi */
1453 mapi private function _next()
1454 mapi {
1455 mapi if ( is_object( $token = $this->_tokenizer->next() ) )
1456 mapi {
1457 mapi return $token;
1458 mapi }
1459 mapi return null;
1460 mapi }
1461 221 mapi }