Complex classes like TokenStream often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TokenStream, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 13 | class TokenStream { | ||
| 14 | private $current = null; | ||
| 15 | /** | ||
| 16 | * @var InputStream | ||
| 17 | */ | ||
| 18 | private $input; | ||
| 19 | |||
| 20 | /** | ||
| 21 | * TokenStream constructor. | ||
| 22 | * | ||
| 23 | * @param InputStream $input | ||
| 24 | */ | ||
| 25 | 35 |     public function __construct(InputStream $input) { | |
| 28 | |||
| 29 | /** | ||
| 30 | * @return Token | ||
| 31 | */ | ||
| 32 | 35 |     public function next() { | |
| 40 | |||
| 41 | /** | ||
| 42 | * @return bool | ||
| 43 | */ | ||
| 44 | 22 |     public function eof() { | |
| 47 | |||
| 48 | /** | ||
| 49 | * @return Token | ||
|  | |||
| 50 | */ | ||
| 51 | 22 |     public function peek() { | |
| 58 | |||
| 59 | /** | ||
| 60 | * @param string $msg | ||
| 61 | * | ||
| 62 | * @throws ParseException | ||
| 63 | */ | ||
| 64 | 1 |     public function error($msg) { | |
| 67 | |||
| 68 | /** | ||
| 69 | * @return Token | ||
| 70 | * @throws ParseException | ||
| 71 | */ | ||
| 72 | 35 |     protected function readNext() { | |
| 102 | |||
| 103 | 5 |     protected function skipComment() { | |
| 111 | |||
| 112 | /** | ||
| 113 | * @return Token | ||
| 114 | */ | ||
| 115 | 12 |     protected function readDoubleQuotedString() { | |
| 118 | |||
| 119 | /** | ||
| 120 | * @return Token | ||
| 121 | */ | ||
| 122 | 1 |     protected function readSingleQuotedString() { | |
| 125 | |||
| 126 | /** | ||
| 127 | * @return Token | ||
| 128 | */ | ||
| 129 | 10 |     protected function readDoubleBracketString() { | |
| 189 | |||
| 190 | /** | ||
| 191 | * @param string $end | ||
| 192 | * | ||
| 193 | * @return string | ||
| 194 | */ | ||
| 195 | 13 |     protected function readEscaped($end) { | |
| 218 | |||
| 219 | /** | ||
| 220 | * @return Token | ||
| 221 | */ | ||
| 222 | 10 |     protected function readNumber() { | |
| 238 | |||
| 239 | /** | ||
| 240 | * @return Token | ||
| 241 | */ | ||
| 242 | 15 |     protected function readIdentifier() { | |
| 258 | |||
| 259 | /** | ||
| 260 | * @return Token | ||
| 261 | */ | ||
| 262 | 14 |     protected function readPunctuation() { | |
| 265 | |||
| 266 | /** | ||
| 267 | * @param callable $predicate | ||
| 268 | * | ||
| 269 | * @return string | ||
| 270 | */ | ||
| 271 | 35 |     protected function readWhile(callable $predicate) { | |
| 278 | |||
| 279 | /** | ||
| 280 | * @param string $char | ||
| 281 | * | ||
| 282 | * @return bool | ||
| 283 | */ | ||
| 284 | 35 |     protected function isWhitespace($char) { | |
| 287 | |||
| 288 | /** | ||
| 289 | * @param string $char | ||
| 290 | * | ||
| 291 | * @return bool | ||
| 292 | */ | ||
| 293 | 23 |     protected function isDigit($char) { | |
| 296 | |||
| 297 | /** | ||
| 298 | * @return bool | ||
| 299 | */ | ||
| 300 | 30 |     protected function isDoubleBracketString() { | |
| 303 | |||
| 304 | /** | ||
| 305 | * @return bool | ||
| 306 | */ | ||
| 307 | 35 |     protected function isComment() { | |
| 310 | |||
| 311 | /** | ||
| 312 | * @param string $char | ||
| 313 | * | ||
| 314 | * @return bool | ||
| 315 | */ | ||
| 316 | 19 |     protected function isStartIdentifierCharacter($char) { | |
| 319 | |||
| 320 | /** | ||
| 321 | * @param string $char | ||
| 322 | * | ||
| 323 | * @return bool | ||
| 324 | */ | ||
| 325 | 15 |     protected function isIdentifierCharacter($char) { | |
| 328 | |||
| 329 | /** | ||
| 330 | * @param string $char | ||
| 331 | * | ||
| 332 | * @return bool | ||
| 333 | */ | ||
| 334 | 15 |     protected function isPunctuation($char) { | |
| 337 | |||
| 338 | /** | ||
| 339 | * @param string $text | ||
| 340 | * | ||
| 341 | * @return bool | ||
| 342 | */ | ||
| 343 | 15 |     protected function isKeyword($text) { | |
| 346 | } | 
This check compares the return type specified in the
@returnannotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.