Skip to content

Commit

Permalink
fix: only collect top level single class for composes
Browse files Browse the repository at this point in the history
  • Loading branch information
ahabhgk committed May 23, 2024
1 parent 5b0f77c commit f4e7c3a
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 35 deletions.
54 changes: 29 additions & 25 deletions src/dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,16 +363,13 @@ struct ComposesLocalClasses<'s> {
}

impl<'s> ComposesLocalClasses<'s> {
pub fn take_valid_local_classes(
&mut self,
lexer: &Lexer<'s>,
) -> Option<SmallVec<[&'s str; 2]>> {
pub fn get_valid_local_classes(&mut self, lexer: &Lexer<'s>) -> Option<SmallVec<[&'s str; 2]>> {
if let SingleLocalClass::Single(range) = &self.is_single {
let mut local_classes = self.local_classes.clone();
local_classes.push(lexer.slice(range.start, range.end)?);
Some(local_classes)
} else {
self.reset_is_single();
self.reset_to_initial();
None
}
}
Expand All @@ -397,7 +394,7 @@ impl<'s> ComposesLocalClasses<'s> {
self.is_single = SingleLocalClass::AtKeyword;
}

pub fn reset_is_single(&mut self) {
pub fn reset_to_initial(&mut self) {
self.is_single = SingleLocalClass::Initial;
}

Expand Down Expand Up @@ -1379,6 +1376,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> LexDependencies<'s, D, W
&[C_RIGHT_PARENTHESIS],
"Expected ')' during parsing of 'composes'",
);
end = lexer.cur_pos()?;
self.handle_dependency
.handle_dependency(Dependency::Composes {
local_classes: local_classes.clone(),
Expand Down Expand Up @@ -1629,7 +1627,9 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
}

let mode_data = self.mode_data.as_mut().unwrap();
mode_data.composes_local_classes.find_at_keyword();
if self.block_nesting_level == 0 {
mode_data.composes_local_classes.find_at_keyword();
}

if mode_data.is_pure_mode() {
mode_data.pure_global = None;
Expand Down Expand Up @@ -1755,10 +1755,6 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
}

self.is_next_rule_prelude = self.is_next_nested_syntax(lexer)?;
if self.is_next_rule_prelude {
let mode_data = self.mode_data.as_mut().unwrap();
mode_data.composes_local_classes.reset_is_single();
}
}
}
_ => {}
Expand Down Expand Up @@ -1917,11 +1913,11 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
message: "not allowed in nested rule",
},
});
return Some(());
}

let Some(local_classes) = mode_data
.composes_local_classes
.take_valid_local_classes(lexer)
.get_valid_local_classes(lexer)
else {
self.handle_warning.handle_warning(Warning {
range: Range::new(start, end),
Expand Down Expand Up @@ -1974,9 +1970,11 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
range: Range::new(start, end),
explicit: mode_data.is_mode_explicit(),
});
mode_data
.composes_local_classes
.find_local_class(start + 1, end);
if self.block_nesting_level == 0 {
mode_data
.composes_local_classes
.find_local_class(start + 1, end);
}

if mode_data.is_pure_mode() {
mode_data.pure_global = None;
Expand Down Expand Up @@ -2006,7 +2004,10 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
range: Range::new(start, end),
explicit: mode_data.is_mode_explicit(),
});
mode_data.composes_local_classes.invalidate();

if self.block_nesting_level == 0 {
mode_data.composes_local_classes.invalidate();
}

if mode_data.is_pure_mode() {
mode_data.pure_global = None;
Expand Down Expand Up @@ -2054,9 +2055,9 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
self.balanced.update_property_mode(mode_data);
self.balanced.pop_mode_pseudo_class(mode_data);
self.is_next_rule_prelude = self.is_next_nested_syntax(lexer)?;
if self.is_next_rule_prelude {
if self.is_next_rule_prelude && self.block_nesting_level == 0 {
let mode_data = self.mode_data.as_mut().unwrap();
mode_data.composes_local_classes.reset_is_single();
mode_data.composes_local_classes.reset_to_initial();
}
}
debug_assert!(
Expand Down Expand Up @@ -2094,10 +2095,9 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
self.scope = Scope::TopLevel;
if let Some(mode_data) = &mut self.mode_data {
self.is_next_rule_prelude = true;
mode_data.composes_local_classes.reset_is_single();
mode_data.composes_local_classes.reset_to_initial();
}
} else if let Some(mode_data) = &mut self.mode_data {
mode_data.composes_local_classes.reset_is_single();
} else if self.mode_data.is_some() {
self.is_next_rule_prelude = self.is_next_nested_syntax(lexer)?;
}
}
Expand Down Expand Up @@ -2132,7 +2132,7 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
content: "",
range: Range::new(start, lexer.cur_pos()?),
});
} else {
} else if self.block_nesting_level == 0 {
mode_data.composes_local_classes.invalidate();
}
}
Expand Down Expand Up @@ -2201,7 +2201,9 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
return Some(());
}

mode_data.composes_local_classes.invalidate();
if self.block_nesting_level == 0 {
mode_data.composes_local_classes.invalidate();
}
Some(())
}

Expand All @@ -2221,7 +2223,9 @@ impl<'s, D: HandleDependency<'s>, W: HandleWarning<'s>> Visitor<'s> for LexDepen
}
mode_data.pure_global = Some(end);

mode_data.composes_local_classes.find_comma(lexer)?;
if self.block_nesting_level == 0 {
mode_data.composes_local_classes.find_comma(lexer)?;
}

if mode_data.resulting_global.is_some() && mode_data.is_current_local_mode() {
let resulting_global_start = mode_data.resulting_global.unwrap();
Expand Down
5 changes: 1 addition & 4 deletions tests/postcss_modules/extract_imports_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,9 +609,6 @@ fn nesting() {
}
"#},
indoc! {r#"
:import("path/library.css") {
i__imported_importName_0: importName;
}
:local(.foo) {
display: grid;
Expand All @@ -621,7 +618,7 @@ fn nesting() {
@media (min-width: 1024px) {
&:local(.baz) {
composes: i__imported_importName_0;
composes: importName from "path/library.css";
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions tests/postcss_modules/scope_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,14 +442,14 @@ fn error_composes_css_nesting() {
._input__a {
._input__b {
compose-with: otherClassName;
}
}
:export {
otherClassName: _input__otherClassName;
a: _input__a;
b: _input__b _input__otherClassName;
b: _input__b;
}
"#},
"Composition is not allowed in nested rule",
Expand Down Expand Up @@ -478,15 +478,15 @@ fn error_composes_css_nesting_at_rule() {
@media (min-width: 1024px) {
._input__a {
._input__b {
compose-with: otherClassName;
}
}
}
:export {
otherClassName: _input__otherClassName;
a: _input__a;
b: _input__b _input__otherClassName;
b: _input__b;
}
"#},
"Composition is not allowed in nested rule",
Expand Down Expand Up @@ -515,15 +515,15 @@ fn error_composes_css_nesting_with_media() {
._input__a {
@media (min-width: 1024px) {
._input__b {
compose-with: otherClassName;
}
}
}
:export {
otherClassName: _input__otherClassName;
a: _input__a;
b: _input__b _input__otherClassName;
b: _input__b;
}
"#},
"Composition is not allowed in nested rule",
Expand Down
24 changes: 24 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,30 @@ fn css_modules_composes_6() {
assert_eq!(dependencies.len(), 7);
}

#[test]
fn css_modules_composes_7() {
let input = indoc! {r#"
.foo {
.bar {}
composes: global(a)
}
"#};
let (dependencies, warnings) = collect_dependencies(input, Mode::Local);
assert!(warnings.is_empty());
assert_local_class_dependency(input, &dependencies[0], ".foo", false);
assert_local_class_dependency(input, &dependencies[1], ".bar", false);
assert_composes_dependency(
input,
&dependencies[2],
"foo",
"a",
Some("global"),
"global(a)",
);
assert_replace_dependency(input, &dependencies[3], "", "composes: global(a)");
assert_eq!(dependencies.len(), 4);
}

#[test]
fn icss_export_unexpected() {
let input = ":export {\n/sl/ash;";
Expand Down

0 comments on commit f4e7c3a

Please sign in to comment.