diff --git a/src/Parsing/ParserState.php b/src/Parsing/ParserState.php index 3451fe0c..f8297d06 100644 --- a/src/Parsing/ParserState.php +++ b/src/Parsing/ParserState.php @@ -201,12 +201,16 @@ public function parseCharacter(bool $isForIdentifier): ?string * This method may change the state of the object by advancing the internal position; * it does not simply 'get' a value. */ - public function consumeWhiteSpace(array &$comments = []): string + public function consumeWhiteSpace(array &$comments = [], bool $stopAfterLineFeed = false): string { $consumed = ''; do { while (preg_match('/\\s/isSu', $this->peek()) === 1) { - $consumed .= $this->consume(1); + $characterComsumed = $this->consume(1); + $consumed .= $characterComsumed; + if ($stopAfterLineFeed && $characterComsumed === "\n") { + break 2; + } } if ($this->parserSettings->usesLenientParsing()) { try { diff --git a/tests/Unit/Parsing/ParserStateTest.php b/tests/Unit/Parsing/ParserStateTest.php index ebc3c7fa..0ffaa9a9 100644 --- a/tests/Unit/Parsing/ParserStateTest.php +++ b/tests/Unit/Parsing/ParserStateTest.php @@ -303,4 +303,67 @@ public function consumeWhiteSpaceStopsAtNonWhitespace(string $nonWhitespace, str self::assertTrue($subject->comes($nonWhitespace)); } + + /** + * @return array + */ + public static function providePossibleWhitespaceWithoutLineFeedPossiblyIncludingComments(): array + { + return [ + 'nothing' => [''], + 'space' => [' '], + 'tab' => ["\t"], + 'carriage return' => ["\r"], // inclusion of this is debatable, but Mac line endings are not generally seen + 'two spaces' => [' '], + 'comment' => ['/* Time for bed */'], + 'comment with spacing around' => [' /* I am so tired */ '], + ]; + } + + /** + * @return DataProvider + */ + public function providePossibleWhitespaceWithoutLineFeedPossiblyIncludingCommentsAndTheSameAgain(): DataProvider + { + return DataProvider::cross( + self::providePossibleWhitespaceWithoutLineFeedPossiblyIncludingComments(), + self::providePossibleWhitespaceWithoutLineFeedPossiblyIncludingComments() + ); + } + + /** + * @test + * + * @dataProvider providePossibleWhitespaceWithoutLineFeedPossiblyIncludingCommentsAndTheSameAgain + */ + public function consumeWhiteSpaceStopsAfterLineFeedWhenRequested(string $firstLine, string $secondLine): void + { + $subject = new ParserState($firstLine . "\n" . $secondLine, Settings::create()); + + $comments = []; + $subject->consumeWhiteSpace($comments, true); + + if ($secondLine === '') { + self::assertTrue($subject->isEnd()); + } else { + self::assertTrue($subject->comes($secondLine)); + } + } + + /** + * @test + * + * @dataProvider providePossibleWhitespaceWithoutLineFeedPossiblyIncludingCommentsAndTheSameAgain + */ + public function consumeWhiteSpaceDoesNotStopAfterLineFeedWhenNotRequested( + string $firstLine, + string $secondLine + ): void { + $subject = new ParserState($firstLine . "\n" . $secondLine, Settings::create()); + + $comments = []; + $subject->consumeWhiteSpace($comments, false); + + self::assertTrue($subject->isEnd()); + } }