Skip to content

Commit dada8f8

Browse files
authored
[BUGFIX] Improve recovery parsing upon a rogue } (#1425)
(My IDE thinks that the test results now updated should be parsed as such.) Also remove a duplicated test.
1 parent a2c978c commit dada8f8

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Please also have a look at our
2424

2525
### Fixed
2626

27+
- Improve recovery parsing when a rogue `}` is encountered (#1425)
2728
- Parse comment(s) immediately preceding a selector (#1421)
2829
- Parse consecutive comments (#1421)
2930
- Support attribute selectors with values containing commas in

src/RuleSet/DeclarationBlock.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static function parse(ParserState $parserState, ?CSSList $list = null): ?
7474
}
7575
} catch (UnexpectedTokenException $e) {
7676
if ($parserState->getSettings()->usesLenientParsing()) {
77-
if (!$parserState->comes('}')) {
77+
if (!$parserState->consumeIfComes('}')) {
7878
$parserState->consumeUntil('}', false, true);
7979
}
8080
return null;

tests/ParserTest.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ public function invalidSelectorsInFile(): void
718718
$document = self::parsedStructureForFile('invalid-selectors', Settings::create()->withMultibyteSupport(true));
719719
$expected = '@keyframes mymove {from {top: 0px;}}
720720
#test {color: white;background: green;}
721+
#test {display: block;background: red;color: white;}
721722
#test {display: block;background: white;color: black;}';
722723
self::assertSame($expected, $document->render());
723724

@@ -727,6 +728,7 @@ public function invalidSelectorsInFile(): void
727728
.super-menu > li:last-of-type {border-right-width: 0;}
728729
html[dir="rtl"] .super-menu > li:first-of-type {border-left-width: 1px;border-right-width: 0;}
729730
html[dir="rtl"] .super-menu > li:last-of-type {border-left-width: 0;}}
731+
.super-menu.menu-floated {border-right-width: 1px;border-left-width: 1px;border-color: #5a4242;border-style: dotted;}
730732
body {background-color: red;}';
731733
self::assertSame($expected, $document->render());
732734
}
@@ -740,15 +742,6 @@ public function selectorEscapesInFile(): void
740742
$expected = '#\\# {color: red;}
741743
.col-sm-1\\/5 {width: 20%;}';
742744
self::assertSame($expected, $document->render());
743-
744-
$document = self::parsedStructureForFile('invalid-selectors-2', Settings::create()->withMultibyteSupport(true));
745-
$expected = '@media only screen and (max-width: 1215px) {.breadcrumb {padding-left: 10px;}
746-
.super-menu > li:first-of-type {border-left-width: 0;}
747-
.super-menu > li:last-of-type {border-right-width: 0;}
748-
html[dir="rtl"] .super-menu > li:first-of-type {border-left-width: 1px;border-right-width: 0;}
749-
html[dir="rtl"] .super-menu > li:last-of-type {border-left-width: 0;}}
750-
body {background-color: red;}';
751-
self::assertSame($expected, $document->render());
752745
}
753746

754747
/**

tests/Unit/RuleSet/DeclarationBlockTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,45 @@ public function parseSkipsBlockWithInvalidSelector(string $selector): void
192192
self::assertTrue($parserState->comes($nextCss));
193193
}
194194

195+
/**
196+
* @return array<non-empty-string, array{0: non-empty-string}>
197+
*/
198+
public static function provideClosingBrace(): array
199+
{
200+
return [
201+
'as is' => ['}'],
202+
'with space before' => [' }'],
203+
'with newline before' => ["\n}"],
204+
];
205+
}
206+
207+
/**
208+
* @return DataProvider<non-empty-string, array{0: non-empty-string, 1: non-empty-string}>
209+
*/
210+
public static function provideInvalidSelectorAndClosingBrace(): DataProvider
211+
{
212+
return DataProvider::cross(self::provideInvalidSelector(), self::provideClosingBrace());
213+
}
214+
215+
/**
216+
* TODO: It's probably not the responsibility of `DeclarationBlock` to deal with this.
217+
*
218+
* @test
219+
*
220+
* @param non-empty-string $selector
221+
* @param non-empty-string $closingBrace
222+
*
223+
* @dataProvider provideInvalidSelectorAndClosingBrace
224+
*/
225+
public function parseConsumesClosingBraceAfterInvalidSelector(string $selector, string $closingBrace): void
226+
{
227+
$parserState = new ParserState($selector . $closingBrace, Settings::create());
228+
229+
DeclarationBlock::parse($parserState);
230+
231+
self::assertTrue($parserState->isEnd());
232+
}
233+
195234
/**
196235
* @return array<string>
197236
*/

0 commit comments

Comments
 (0)