Overview

Namespaces

  • TokenReflection
    • Broker
      • Backend
    • Dummy
    • Exception
    • Invalid
    • Php
    • Stream

Exceptions

  • BaseException
  • BrokerException
  • FileProcessingException
  • ParseException
  • RuntimeException
  • StreamException
  • Overview
  • Namespace
  • Class
  • Tree
  • Download
  1: <?php
  2: /**
  3:  * PHP Token Reflection
  4:  *
  5:  * Version 1.3.1
  6:  *
  7:  * LICENSE
  8:  *
  9:  * This source file is subject to the new BSD license that is bundled
 10:  * with this library in the file LICENSE.
 11:  *
 12:  * @author Ondřej Nešpor
 13:  * @author Jaroslav Hanslík
 14:  */
 15: 
 16: namespace TokenReflection\Exception;
 17: 
 18: use TokenReflection\Stream\StreamBase;
 19: use TokenReflection\IReflection;
 20: 
 21: /**
 22:  * Parse exception.
 23:  *
 24:  * Thrown while parsing source codes.
 25:  */
 26: class ParseException extends StreamException
 27: {
 28:     /**
 29:      * An unexpected  token was encountered.
 30:      *
 31:      * @var integer
 32:      */
 33:     const UNEXPECTED_TOKEN = 1101;
 34: 
 35:     /**
 36:      * A logical error was encountered.
 37:      *
 38:      * @var integer
 39:      */
 40:     const LOGICAL_ERROR = 1102;
 41: 
 42:     /**
 43:      * An invalid reflection parent was provided.
 44:      *
 45:      * @var integer
 46:      */
 47:     const INVALID_PARENT = 1103;
 48: 
 49:     /**
 50:      * Minimal number of source code lines around the token.
 51:      *
 52:      * @var integer
 53:      */
 54:     const SOURCE_LINES_AROUND = 5;
 55: 
 56:     /**
 57:      * The token that caused the expection to be thrown.
 58:      *
 59:      * @var array|null
 60:      */
 61:     private $token;
 62: 
 63:     /**
 64:      * The name of the token that caused the exception to be thrown.
 65:      *
 66:      * @var string|null
 67:      */
 68:     private $tokenName;
 69: 
 70:     /**
 71:      * The line where the exception was thrown.
 72:      *
 73:      * @var integer
 74:      */
 75:     private $exceptionLine;
 76: 
 77:     /**
 78:      * Boundaries of the token substream around the token.
 79:      *
 80:      * @var array
 81:      */
 82:     private $scopeBoundaries = array();
 83: 
 84:     /**
 85:      * The reflection element that caused this exception to be raised.
 86:      *
 87:      * @var \TokenReflection\IReflection
 88:      */
 89:     private $sender;
 90: 
 91:     /**
 92:      * Constructor.
 93:      *
 94:      * @param \TokenReflection\IReflection $sender Reflection element
 95:      * @param \TokenReflection\Stream\StreamBase $tokenStream Token stream
 96:      * @param string $message Exception message
 97:      * @param integer $code Exception code
 98:      */
 99:     public function __construct(IReflection $sender, StreamBase $tokenStream, $message, $code)
100:     {
101:         parent::__construct($tokenStream, $message, $code);
102: 
103:         $this->sender = $sender;
104: 
105:         $token = $tokenStream->current();
106:         $position = $tokenStream->key();
107: 
108:         if (!empty($token) && !empty($position)) {
109:             $this->token = $token;
110:             $this->tokenName = $tokenStream->getTokenName();
111: 
112:             $line = $this->token[2];
113:             $min = $max = $position;
114:         } else {
115:             $min = $max = $tokenStream->count() - 1;
116:             $line = $tokenStream[$min][2];
117:         }
118: 
119:         $this->exceptionLine = $line;
120: 
121:         static $skip = array(T_WHITESPACE => true, T_COMMENT => true, T_DOC_COMMENT => true);
122: 
123:         $significant = array();
124:         while (isset($tokenStream[$min - 1])) {
125:             if (!isset($significant[$tokenStream[$min][2]])) {
126:                 if (self::SOURCE_LINES_AROUND <= array_sum($significant)) {
127:                     break;
128:                 }
129: 
130:                 $significant[$tokenStream[$min][2]] = !isset($skip[$tokenStream[$min][0]]);
131:             } else {
132:                 $significant[$tokenStream[$min][2]] |= !isset($skip[$tokenStream[$min][0]]);
133:             }
134: 
135:             $min--;
136:         }
137: 
138:         $significant = array();
139:         while (isset($tokenStream[$max + 1])) {
140:             if (!isset($significant[$tokenStream[$max][2]])) {
141:                 if (self::SOURCE_LINES_AROUND <= array_sum($significant)) {
142:                     break;
143:                 }
144: 
145:                 $significant[$tokenStream[$max][2]] = !isset($skip[$tokenStream[$max][0]]);
146:             } else {
147:                 $significant[$tokenStream[$max][2]] |= !isset($skip[$tokenStream[$max][0]]);
148:             }
149: 
150:             $max++;
151:         }
152: 
153:         $this->scopeBoundaries = array($min, $max);
154:     }
155: 
156:     /**
157:      * Returns the token where the problem was detected or NULL if the token stream was empty or an end was reached.
158:      *
159:      * @return array|null
160:      */
161:     public function getToken()
162:     {
163:         return $this->token;
164:     }
165: 
166:     /**
167:      * Returns the name of the token where the problem was detected or NULL if the token stream was empty or an end was reached.
168:      *
169:      * @return string|null
170:      */
171:     public function getTokenName()
172:     {
173:         return $this->tokenName;
174:     }
175: 
176:     /**
177:      * Returns the line where the exception was thrown.
178:      *
179:      * @return integer
180:      */
181:     public function getExceptionLine()
182:     {
183:         return $this->exceptionLine;
184:     }
185: 
186:     /**
187:      * Returns the file line with the token or null.
188:      *
189:      * @return integer|null
190:      */
191:     public function getTokenLine()
192:     {
193:         return null === $this->token ? null : $this->token[2];
194:     }
195: 
196:     /**
197:      * Returns the source code part around the token.
198:      *
199:      * @param boolean $lineNumbers Returns the source code part with line numbers
200:      * @return string|null
201:      */
202:     public function getSourcePart($lineNumbers = false)
203:     {
204:         if (empty($this->scopeBoundaries)) {
205:             return null;
206:         }
207: 
208:         list($lo, $hi) = $this->scopeBoundaries;
209:         $stream = $this->getStream();
210: 
211:         $code = $stream->getSourcePart($lo, $hi);
212: 
213:         if ($lineNumbers) {
214:             $lines = explode("\n", $code);
215: 
216:             $startLine = $stream[$lo][2];
217:             $width = strlen($startLine + count($lines) - 1);
218:             $errorLine = $this->token[2];
219:             $actualLine = $startLine;
220: 
221:             $code = implode(
222:                 "\n",
223:                 array_map(function($line) use (&$actualLine, $width, $errorLine) {
224:                     return ($actualLine === $errorLine ? '*' : ' ') . str_pad($actualLine++, $width, ' ', STR_PAD_LEFT) . ': ' . $line;
225:                 }, $lines)
226:             );
227:         }
228: 
229:         return $code;
230:     }
231: 
232:     /**
233:      * Returns the reflection element that caused the exception to be raised.
234:      *
235:      * @return \TokenReflection\IReflection
236:      */
237:     public function getSender()
238:     {
239:         return $this->sender;
240:     }
241: 
242:     /**
243:      * Returns an exception description detail.
244:      *
245:      * @return string
246:      */
247:     public function getDetail()
248:     {
249:         if (0 === $this->getStream()->count()) {
250:             return parent::getDetail() . 'The token stream was empty.';
251:         } elseif (empty($this->token)) {
252:             return parent::getDetail() . 'The token stream was read out of its bounds.';
253:         } else {
254:             return parent::getDetail() .
255:                 sprintf(
256:                     "\nThe cause of the exception was the %s token (line %s) in following part of %s source code:\n\n%s",
257:                     $this->tokenName,
258:                     $this->token[2],
259:                     $this->sender && $this->sender->getName() ? $this->sender->getPrettyName() : 'the',
260:                     $this->getSourcePart(true)
261:                 );
262:         }
263:     }
264: }
265: 
PHP Token Reflection API documentation generated by ApiGen 2.8.0