diff --git a/crates/swc_css_modules/tests/fixture/url/url.compiled.css b/crates/swc_css_modules/tests/fixture/url/url.compiled.css index 0f44fdcd8d54..5060579893ca 100644 --- a/crates/swc_css_modules/tests/fixture/url/url.compiled.css +++ b/crates/swc_css_modules/tests/fixture/url/url.compiled.css @@ -72,6 +72,7 @@ b { } @keyframes __local__anim { background: green url('./img.png') xyz; + } .__local__a { background-image: -webkit-image-set(url('./img1x.png') 1x, url('./img2x.png') 2x); diff --git a/crates/swc_css_parser/src/parser/syntax/mod.rs b/crates/swc_css_parser/src/parser/syntax/mod.rs index 0af6f9b38d91..2218024d97b6 100644 --- a/crates/swc_css_parser/src/parser/syntax/mod.rs +++ b/crates/swc_css_parser/src/parser/syntax/mod.rs @@ -14,6 +14,8 @@ where I: ParserInput, { fn parse(&mut self) -> PResult { + // Create a new stylesheet, with its location set to location (or null, if + // location was not passed). let start = self.input.cur_span(); // Consume a list of rules from input, with the top-level flag set, and set the @@ -46,10 +48,9 @@ where // Repeatedly consume the next input token: loop { - // TODO: remove `}` // // Return the list of rules. - if is_one_of!(self, EOF, "}") { + if is!(self, EOF) { return Ok(rules); } @@ -92,28 +93,21 @@ where self.input.reset(&state); let span = self.input.cur_span(); - let mut children = vec![]; + let mut list_of_component_values = ListOfComponentValues { + span: Default::default(), + children: vec![], + }; - while !is_one_of!(self, EOF, "}") { - if let Some(token_and_span) = self.input.bump() { - children.push(ComponentValue::PreservedToken(token_and_span)); - } + while !is_one_of!(self, EOF) { + let component_value = self.parse_as::()?; - if is!(self, ";") { - if let Some(token_and_span) = self.input.bump() { - children - .push(ComponentValue::PreservedToken(token_and_span)); - } - - break; - } + list_of_component_values.children.push(component_value); } + list_of_component_values.span = span!(self, span.lo); + rules.push(Rule::ListOfComponentValues(Box::new( - ListOfComponentValues { - span: span!(self, span.lo), - children, - }, + list_of_component_values, ))); } }; diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.json index fbafe0cbfaf7..3bd845d4d2b1 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.json @@ -121,7 +121,7 @@ "type": "ListOfComponentValues", "span": { "start": 33, - "end": 57, + "end": 58, "ctxt": 0 }, "children": [ @@ -186,6 +186,19 @@ "ctxt": 0 }, "token": "Semi" + }, + { + "type": "PreservedToken", + "span": { + "start": 57, + "end": 58, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n" + } + } } ] } diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/span.rust-debug index 4ea1b206ea77..69077b5cdf44 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/span.rust-debug @@ -132,13 +132,15 @@ x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:2:5] 2 | max-inline-size: 1024px; - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } `---- x Rule ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:2:5] 2 | max-inline-size: 1024px; - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } `---- x ComponentValue @@ -200,3 +202,18 @@ 2 | max-inline-size: 1024px; : ^ `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:2:5] + 2 | max-inline-size: 1024px; + : ^ + 3 | } + `---- + + x WhiteSpace { value: Atom(' + | ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:2:5] + 2 | max-inline-size: 1024px; + : ^ + 3 | } + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/input.css b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/input.css new file mode 100644 index 000000000000..c603e2cd8dba --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/input.css @@ -0,0 +1,5 @@ +a { color: red } + +@media {}; + +a { color: blue } diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.json b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.json new file mode 100644 index 000000000000..8271ae86016f --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.json @@ -0,0 +1,279 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 49, + "ctxt": 0 + }, + "rules": [ + { + "type": "QualifiedRule", + "span": { + "start": 1, + "end": 17, + "ctxt": 0 + }, + "prelude": { + "type": "SelectorList", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "children": [ + { + "type": "ComplexSelector", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "children": [ + { + "type": "CompoundSelector", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "nestingSelector": null, + "typeSelector": { + "type": "TagNameSelector", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "name": { + "type": "WqName", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "prefix": null, + "value": { + "type": "Ident", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "value": "a", + "raw": "a" + } + } + }, + "subclassSelectors": [] + } + ] + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 3, + "end": 17, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 3, + "end": 4, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 5, + "end": 16, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 5, + "end": 10, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 12, + "end": 15, + "ctxt": 0 + }, + "value": "red", + "raw": "red" + } + ], + "important": null + } + ] + } + }, + { + "type": "AtRule", + "span": { + "start": 19, + "end": 28, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 20, + "end": 25, + "ctxt": 0 + }, + "value": "media", + "raw": "media" + }, + "prelude": null, + "block": { + "type": "SimpleBlock", + "span": { + "start": 26, + "end": 28, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 26, + "end": 27, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [] + } + }, + { + "type": "QualifiedRule", + "span": { + "start": 28, + "end": 48, + "ctxt": 0 + }, + "prelude": { + "type": "ListOfComponentValues", + "span": { + "start": 28, + "end": 33, + "ctxt": 0 + }, + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 28, + "end": 29, + "ctxt": 0 + }, + "token": "Semi" + }, + { + "type": "PreservedToken", + "span": { + "start": 29, + "end": 31, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "a", + "raw": "a" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 32, + "end": 33, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 33, + "end": 48, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 34, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 35, + "end": 47, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 35, + "end": 40, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 42, + "end": 46, + "ctxt": 0 + }, + "value": "blue", + "raw": "blue" + } + ], + "important": null + } + ] + } + } + ] +} diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.swc-stderr b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.swc-stderr new file mode 100644 index 000000000000..5c4cdea96d6b --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/output.swc-stderr @@ -0,0 +1,6 @@ + + x Invalid selector + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/span.rust-debug b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/span.rust-debug new file mode 100644 index 000000000000..f4b25b1286d8 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-in-middle/span.rust-debug @@ -0,0 +1,273 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | ,-> a { color: red } + 2 | | + 3 | | @media {}; + 4 | | + 5 | `-> a { color: blue } + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^^^^^^ + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^^^^^^ + `---- + + x SelectorList + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x ComplexSelector + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x CompoundSelector + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x TypeSelector + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x TagNameSelector + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x WqName + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:1:1] + 1 | a { color: red } + : ^^^ + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^^^^^^^^^ + `---- + + x AtRule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^^^^^^^^^ + `---- + + x AtRuleName + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^ + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | ,-> @media {}; + 4 | | + 5 | `-> a { color: blue } + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | ,-> @media {}; + 4 | | + 5 | `-> a { color: blue } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^ + `---- + + x Semi + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | @media {}; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | ,-> @media {}; + 4 | `-> + 5 | a { color: blue } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:3:1] + 3 | ,-> @media {}; + 4 | `-> + 5 | a { color: blue } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x Ident { value: Atom('a' type=static), raw: Atom('a' type=static) } + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-in-middle/input.css:5:1] + 5 | a { color: blue } + : ^^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/input.css b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/input.css new file mode 100644 index 000000000000..57bac48e1247 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/input.css @@ -0,0 +1,5 @@ +@media {}; + +a { color: red } + +a { color: blue } diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.json b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.json new file mode 100644 index 000000000000..1f6a69c63eaf --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.json @@ -0,0 +1,279 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 49, + "ctxt": 0 + }, + "rules": [ + { + "type": "AtRule", + "span": { + "start": 1, + "end": 10, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 2, + "end": 7, + "ctxt": 0 + }, + "value": "media", + "raw": "media" + }, + "prelude": null, + "block": { + "type": "SimpleBlock", + "span": { + "start": 8, + "end": 10, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 9, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [] + } + }, + { + "type": "QualifiedRule", + "span": { + "start": 10, + "end": 29, + "ctxt": 0 + }, + "prelude": { + "type": "ListOfComponentValues", + "span": { + "start": 10, + "end": 15, + "ctxt": 0 + }, + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 10, + "end": 11, + "ctxt": 0 + }, + "token": "Semi" + }, + { + "type": "PreservedToken", + "span": { + "start": 11, + "end": 13, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 13, + "end": 14, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "a", + "raw": "a" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 14, + "end": 15, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 15, + "end": 29, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 15, + "end": 16, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 17, + "end": 28, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 17, + "end": 22, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 24, + "end": 27, + "ctxt": 0 + }, + "value": "red", + "raw": "red" + } + ], + "important": null + } + ] + } + }, + { + "type": "QualifiedRule", + "span": { + "start": 31, + "end": 48, + "ctxt": 0 + }, + "prelude": { + "type": "SelectorList", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "children": [ + { + "type": "ComplexSelector", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "children": [ + { + "type": "CompoundSelector", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "nestingSelector": null, + "typeSelector": { + "type": "TagNameSelector", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "name": { + "type": "WqName", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "prefix": null, + "value": { + "type": "Ident", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "value": "a", + "raw": "a" + } + } + }, + "subclassSelectors": [] + } + ] + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 33, + "end": 48, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 34, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 35, + "end": 47, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 35, + "end": 40, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 42, + "end": 46, + "ctxt": 0 + }, + "value": "blue", + "raw": "blue" + } + ], + "important": null + } + ] + } + } + ] +} diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.swc-stderr b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.swc-stderr new file mode 100644 index 000000000000..2eff53d3ec12 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/output.swc-stderr @@ -0,0 +1,6 @@ + + x Invalid selector + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/span.rust-debug b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/span.rust-debug new file mode 100644 index 000000000000..61bbe3c7cf6d --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/at-rule-with-semi/span.rust-debug @@ -0,0 +1,273 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | ,-> @media {}; + 2 | | + 3 | | a { color: red } + 4 | | + 5 | `-> a { color: blue } + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^^^^^^^^^ + `---- + + x AtRule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^^^^^^^^^ + `---- + + x AtRuleName + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^ + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | ,-> @media {}; + 2 | | + 3 | `-> a { color: red } + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | ,-> @media {}; + 2 | | + 3 | `-> a { color: red } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^ + `---- + + x Semi + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | @media {}; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | ,-> @media {}; + 2 | `-> + 3 | a { color: red } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:1:1] + 1 | ,-> @media {}; + 2 | `-> + 3 | a { color: red } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x Ident { value: Atom('a' type=static), raw: Atom('a' type=static) } + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:3:1] + 3 | a { color: red } + : ^^^ + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^^^^^^ + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^^^^^^ + `---- + + x SelectorList + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x ComplexSelector + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x CompoundSelector + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x TypeSelector + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x TagNameSelector + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x WqName + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/at-rule-with-semi/input.css:5:1] + 5 | a { color: blue } + : ^^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/input.css b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/input.css new file mode 100644 index 000000000000..74ba67e531e9 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/input.css @@ -0,0 +1,7 @@ +.class[attr= { + +} + +.class { color: red } + +.class { color: blue } \ No newline at end of file diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.json b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.json new file mode 100644 index 000000000000..77a9ca8eaaae --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.json @@ -0,0 +1,434 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 65, + "ctxt": 0 + }, + "rules": [ + { + "type": "ListOfComponentValues", + "span": { + "start": 1, + "end": 65, + "ctxt": 0 + }, + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 1, + "end": 2, + "ctxt": 0 + }, + "token": { + "Delim": { + "value": "." + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 2, + "end": 7, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "class", + "raw": "class" + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 7, + "end": 65, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": "LBracket" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 12, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "attr", + "raw": "attr" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 12, + "end": 13, + "ctxt": 0 + }, + "token": { + "Delim": { + "value": "=" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 13, + "end": 14, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 14, + "end": 18, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 14, + "end": 15, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 15, + "end": 17, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 20, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 20, + "end": 21, + "ctxt": 0 + }, + "token": { + "Delim": { + "value": "." + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 21, + "end": 26, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "class", + "raw": "class" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 26, + "end": 27, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 27, + "end": 41, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 28, + "end": 29, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 29, + "end": 34, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "color", + "raw": "color" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 34, + "end": 35, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 35, + "end": 36, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 36, + "end": 39, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "red", + "raw": "red" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 39, + "end": 40, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 41, + "end": 43, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 43, + "end": 44, + "ctxt": 0 + }, + "token": { + "Delim": { + "value": "." + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 44, + "end": 49, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "class", + "raw": "class" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 49, + "end": 50, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 50, + "end": 65, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 50, + "end": 51, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 51, + "end": 52, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 52, + "end": 57, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "color", + "raw": "color" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 57, + "end": 58, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 58, + "end": 59, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 59, + "end": 63, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "blue", + "raw": "blue" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 63, + "end": 64, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.swc-stderr b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.swc-stderr new file mode 100644 index 000000000000..f1f14629c75f --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/output.swc-stderr @@ -0,0 +1,22 @@ + + x Unexpected end of file, but expected ']' + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- + + x Unexpected end of file, but expected '{' + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/span.rust-debug b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/span.rust-debug new file mode 100644 index 000000000000..48dd3e9854be --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-brackets/span.rust-debug @@ -0,0 +1,430 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x Delim { value: '.' } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^^^^^ + `---- + + x Ident { value: Atom('class' type=static), raw: Atom('class' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | | } + 4 | | + 5 | | .class { color: red } + 6 | | + 7 | `-> .class { color: blue } + `---- + + x LBracket + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^^^^ + `---- + + x Ident { value: Atom('attr' type=inline), raw: Atom('attr' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x Delim { value: '=' } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | .class[attr= { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | `-> + 3 | } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | `-> + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:3:1] + 3 | ,-> } + 4 | `-> + 5 | .class { color: red } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:3:1] + 3 | ,-> } + 4 | `-> + 5 | .class { color: red } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x Delim { value: '.' } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^ + `---- + + x Ident { value: Atom('class' type=static), raw: Atom('class' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^ + `---- + + x Ident { value: Atom('color' type=static), raw: Atom('color' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^ + `---- + + x Ident { value: Atom('red' type=inline), raw: Atom('red' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | .class { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | ,-> .class { color: red } + 6 | `-> + 7 | .class { color: blue } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:5:1] + 5 | ,-> .class { color: red } + 6 | `-> + 7 | .class { color: blue } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x Delim { value: '.' } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^ + `---- + + x Ident { value: Atom('class' type=static), raw: Atom('class' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^ + `---- + + x Ident { value: Atom('color' type=static), raw: Atom('color' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^ + `---- + + x Ident { value: Atom('blue' type=inline), raw: Atom('blue' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-brackets/input.css:7:1] + 7 | .class { color: blue } + : ^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/input.css b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/input.css new file mode 100644 index 000000000000..c6d016df9d92 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/input.css @@ -0,0 +1,5 @@ +test}; + +a { color: red } + +a { color: blue; } diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.json b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.json new file mode 100644 index 000000000000..bfa0ae0d6562 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.json @@ -0,0 +1,265 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 46, + "ctxt": 0 + }, + "rules": [ + { + "type": "QualifiedRule", + "span": { + "start": 1, + "end": 25, + "ctxt": 0 + }, + "prelude": { + "type": "ListOfComponentValues", + "span": { + "start": 1, + "end": 11, + "ctxt": 0 + }, + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 1, + "end": 5, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "test", + "raw": "test" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 5, + "end": 6, + "ctxt": 0 + }, + "token": "RBrace" + }, + { + "type": "PreservedToken", + "span": { + "start": 6, + "end": 7, + "ctxt": 0 + }, + "token": "Semi" + }, + { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 9, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 9, + "end": 10, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "a", + "raw": "a" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 10, + "end": 11, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 11, + "end": 25, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 11, + "end": 12, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 13, + "end": 24, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 13, + "end": 18, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 20, + "end": 23, + "ctxt": 0 + }, + "value": "red", + "raw": "red" + } + ], + "important": null + } + ] + } + }, + { + "type": "QualifiedRule", + "span": { + "start": 27, + "end": 45, + "ctxt": 0 + }, + "prelude": { + "type": "SelectorList", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "children": [ + { + "type": "ComplexSelector", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "children": [ + { + "type": "CompoundSelector", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "nestingSelector": null, + "typeSelector": { + "type": "TagNameSelector", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "name": { + "type": "WqName", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "prefix": null, + "value": { + "type": "Ident", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "value": "a", + "raw": "a" + } + } + }, + "subclassSelectors": [] + } + ] + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 29, + "end": 45, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 29, + "end": 30, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 31, + "end": 42, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 31, + "end": 36, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 38, + "end": 42, + "ctxt": 0 + }, + "value": "blue", + "raw": "blue" + } + ], + "important": null + } + ] + } + } + ] +} diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.swc-stderr b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.swc-stderr new file mode 100644 index 000000000000..238e50b74ab2 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/output.swc-stderr @@ -0,0 +1,6 @@ + + x Invalid selector + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/span.rust-debug b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/span.rust-debug new file mode 100644 index 000000000000..f6e4b5a675cd --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/rules/unclosed-curly/span.rust-debug @@ -0,0 +1,261 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | ,-> test}; + 2 | | + 3 | | a { color: red } + 4 | | + 5 | `-> a { color: blue; } + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | ,-> test}; + 2 | | + 3 | `-> a { color: red } + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | ,-> test}; + 2 | | + 3 | `-> a { color: red } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^^^^ + `---- + + x Ident { value: Atom('test' type=inline), raw: Atom('test' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^ + `---- + + x RBrace + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^ + `---- + + x Semi + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | test}; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | ,-> test}; + 2 | `-> + 3 | a { color: red } + `---- + + x WhiteSpace { value: Atom(' + | + | ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:1:1] + 1 | ,-> test}; + 2 | `-> + 3 | a { color: red } + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x Ident { value: Atom('a' type=static), raw: Atom('a' type=static) } + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:3:1] + 3 | a { color: red } + : ^^^ + `---- + + x Rule + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^^^^^^^^ + `---- + + x QualifiedRule + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^^^^^^^^ + `---- + + x SelectorList + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x ComplexSelector + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x CompoundSelector + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x TypeSelector + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x TagNameSelector + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x WqName + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^^^^^^ + `---- + + x LBrace + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^ + `---- + + x StyleBlock + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/rules/unclosed-curly/input.css:5:1] + 5 | a { color: blue; } + : ^^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/output.json b/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/output.json index 6ca83c16d8a9..d112c01b57ba 100644 --- a/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/output.json +++ b/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/output.json @@ -2,7 +2,7 @@ "type": "Stylesheet", "span": { "start": 1, - "end": 17, + "end": 19, "ctxt": 0 }, "rules": [ @@ -10,7 +10,7 @@ "type": "ListOfComponentValues", "span": { "start": 1, - "end": 17, + "end": 19, "ctxt": 0 }, "children": [ @@ -42,75 +42,108 @@ } }, { - "type": "PreservedToken", + "type": "SimpleBlock", "span": { "start": 7, - "end": 8, + "end": 19, "ctxt": 0 }, - "token": "LBracket" - }, - { - "type": "PreservedToken", - "span": { - "start": 8, - "end": 12, - "ctxt": 0 - }, - "token": { - "Ident": { - "value": "attr", - "raw": "attr" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 12, - "end": 13, - "ctxt": 0 + "name": { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": "LBracket" }, - "token": { - "Delim": { - "value": "=" + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 12, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "attr", + "raw": "attr" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 12, + "end": 13, + "ctxt": 0 + }, + "token": { + "Delim": { + "value": "=" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 13, + "end": 14, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 14, + "end": 18, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 14, + "end": 15, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 15, + "end": 17, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n\n" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": "\n" + } + } } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 13, - "end": 14, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": " " - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 14, - "end": 15, - "ctxt": 0 - }, - "token": "LBrace" - }, - { - "type": "PreservedToken", - "span": { - "start": 15, - "end": 17, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n\n" - } - } + ] } ] } diff --git a/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/span.rust-debug b/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/span.rust-debug index c844961a521b..522bc30ba147 100644 --- a/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/selector/attribute/unclosed/span.rust-debug @@ -2,15 +2,15 @@ x Stylesheet ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] 1 | ,-> .class[attr= { - 2 | `-> - 3 | } + 2 | | + 3 | `-> } `---- x Rule ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] 1 | ,-> .class[attr= { - 2 | `-> - 3 | } + 2 | | + 3 | `-> } `---- x ComponentValue @@ -39,8 +39,16 @@ x ComponentValue ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] - 1 | .class[attr= { - : ^ + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } `---- x LBracket @@ -87,8 +95,16 @@ x ComponentValue ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] - 1 | .class[attr= { - : ^ + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:1:1] + 1 | ,-> .class[attr= { + 2 | | + 3 | `-> } `---- x LBrace @@ -112,3 +128,16 @@ 2 | `-> 3 | } `---- + + x ComponentValue + ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:3:1] + 3 | } + : ^ + `---- + + x WhiteSpace { value: Atom(' + | ' type=inline) } + ,-[$DIR/tests/recovery/selector/attribute/unclosed/input.css:3:1] + 3 | } + : ^ + `----