Skip to content

Commit

Permalink
refactor(linter): use cow_to_ascii_lowercase instead `cow_to_lowerc…
Browse files Browse the repository at this point in the history
…ase` (#8678)

`cow_to_lowercase` is slow as it deals with unicode.

closes #8659
  • Loading branch information
Boshen committed Jan 23, 2025
1 parent 883d25b commit 23b49a6
Show file tree
Hide file tree
Showing 16 changed files with 30 additions and 29 deletions.
2 changes: 1 addition & 1 deletion crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ impl Gen for RegExpLiteral<'_> {
let pattern_text = self.regex.pattern.source_text(p.source_text);
// Avoid forming a single-line comment or "</script" sequence
if last == Some(b'/')
|| (last == Some(b'<') && pattern_text.cow_to_lowercase().starts_with("script"))
|| (last == Some(b'<') && pattern_text.cow_to_ascii_lowercase().starts_with("script"))
{
p.print_hard_space();
}
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl<'a> RawNum<'a> {
impl NoLossOfPrecision {
fn not_base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {
let raw = node.raw.as_ref().unwrap().as_str().cow_replace('_', "");
let raw = raw.cow_to_uppercase();
let raw = raw.cow_to_ascii_uppercase();
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
// AST always store number as f64, need a cast to format in bin/oct/hex
let value = node.value as u64;
Expand All @@ -197,7 +197,7 @@ impl NoLossOfPrecision {
} else {
format!("{value:o}")
};
!raw.ends_with(&suffix.cow_to_uppercase().as_ref())
!raw.ends_with(&suffix.cow_to_ascii_uppercase().as_ref())
}

fn base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_script_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Rule for NoScriptUrl {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
AstKind::StringLiteral(literal)
if literal.value.cow_to_lowercase().starts_with("javascript:") =>
if literal.value.cow_to_ascii_lowercase().starts_with("javascript:") =>
{
emit_diagnostic(ctx, literal.span);
}
Expand All @@ -58,7 +58,7 @@ impl Rule for NoScriptUrl {
.unwrap()
.value
.raw
.cow_to_lowercase()
.cow_to_ascii_lowercase()
.starts_with("javascript:")
{
emit_diagnostic(ctx, literal.span);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ where
.with_label(symbol.span().label(format!("'{name}' is declared here")))
.with_help(format!(
"Consider renaming this {}{help_suffix}",
pronoun_singular.cow_to_lowercase()
pronoun_singular.cow_to_ascii_lowercase()
))
}
/// Variable 'x' is declared but never used.
Expand Down
8 changes: 4 additions & 4 deletions crates/oxc_linter/src/rules/eslint/sort_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ impl SortImports {

if self.ignore_case {
current_local_member_name = current_local_member_name
.map(|name| Cow::Owned(name.cow_to_lowercase().into_owned()));
.map(|name| Cow::Owned(name.cow_to_ascii_lowercase().into_owned()));
previous_local_member_name = previous_local_member_name
.map(|name| Cow::Owned(name.cow_to_lowercase().into_owned()));
.map(|name| Cow::Owned(name.cow_to_ascii_lowercase().into_owned()));
}

// "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
Expand Down Expand Up @@ -285,7 +285,7 @@ impl SortImports {
let b = window[1].local.name.as_str();

if self.ignore_case {
a.cow_to_lowercase() > b.cow_to_lowercase()
a.cow_to_ascii_lowercase() > b.cow_to_ascii_lowercase()
} else {
a > b
}
Expand Down Expand Up @@ -332,7 +332,7 @@ impl SortImports {
let b = b.local.name.as_str();

if self.ignore_case {
a.cow_to_lowercase().cmp(&b.cow_to_lowercase())
a.cow_to_ascii_lowercase().cmp(&b.cow_to_ascii_lowercase())
} else {
a.cmp(b)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/sort_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ impl Rule for SortKeys {
for group in &mut property_groups {
*group = group
.iter()
.map(|s| s.cow_to_lowercase().to_string())
.map(|s| s.cow_to_ascii_lowercase().to_string())
.collect::<Vec<String>>();
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/sort_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl SortVars {
};

if self.ignore_case {
return ident.name.as_str().cow_to_lowercase();
return ident.name.as_str().cow_to_ascii_lowercase();
}

Cow::Borrowed(ident.name.as_str()) // avoid string allocs in the default case
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Rule for AriaProps {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::JSXAttributeItem(JSXAttributeItem::Attribute(attr)) = node.kind() {
let name = get_jsx_attribute_name(&attr.name);
let name = name.cow_to_lowercase();
let name = name.cow_to_ascii_lowercase();
if name.starts_with("aria-") && !VALID_ARIA_PROPS.contains(&name) {
let suggestion = COMMON_TYPOS.get(&name).copied();
let diagnostic = aria_props_diagnostic(attr.span, &name, suggestion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl Rule for AriaUnsupportedElements {
JSXAttributeItem::SpreadAttribute(_) => continue,
};
let attr_name = get_jsx_attribute_name(&attr.name);
let attr_name = attr_name.cow_to_lowercase();
let attr_name = attr_name.cow_to_ascii_lowercase();
if INVALID_ATTRIBUTES.contains(&attr_name) {
ctx.diagnostic_with_fix(
aria_unsupported_elements_diagnostic(attr.span, &attr_name),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl Rule for RoleSupportsAriaProps {
for attr in &jsx_el.attributes {
if let JSXAttributeItem::Attribute(attr) = attr {
let name = get_jsx_attribute_name(&attr.name);
let name = name.cow_to_lowercase();
let name = name.cow_to_ascii_lowercase();
if invalid_props.contains(&&name.as_ref()) {
ctx.diagnostic(if is_implicit {
is_implicit_diagnostic(attr.span, &name, role_value, &el_type)
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/react/jsx_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn import_matcher<'a>(
actual_local_name: &'a str,
expected_module_name: &'a str,
) -> bool {
let expected_module_name = expected_module_name.cow_to_lowercase();
let expected_module_name = expected_module_name.cow_to_ascii_lowercase();
ctx.module_record().import_entries.iter().any(|import| {
import.module_request.name() == expected_module_name
&& import.local_name.name() == actual_local_name
Expand Down
15 changes: 8 additions & 7 deletions crates/oxc_linter/src/rules/react/no_unknown_property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,11 @@ const DOM_PROPERTIES_IGNORE_CASE: [&str; 5] = [
];

lazy_static! {
static ref DOM_PROPERTIES_LOWER_MAP: FxHashMap<String, &'static str> = DOM_PROPERTIES_NAMES
.iter()
.map(|it| (it.cow_to_lowercase().into_owned(), *it))
.collect::<FxHashMap<_, _>>();
static ref DOM_PROPERTIES_LOWER_MAP: FxHashMap<Cow<'static, str>, &'static str> =
DOM_PROPERTIES_NAMES
.iter()
.map(|it| (it.cow_to_ascii_lowercase(), *it))
.collect::<FxHashMap<_, _>>();
}

/// Checks if an attribute name is a valid `data-*` attribute:
Expand All @@ -442,7 +443,7 @@ fn is_valid_data_attr(name: &str) -> bool {
return false;
}

if name.cow_to_lowercase().starts_with("data-xml") {
if name.cow_to_ascii_lowercase().starts_with("data-xml") {
return false;
}

Expand Down Expand Up @@ -519,7 +520,7 @@ impl Rule for NoUnknownProperty {
if self.0.require_data_lowercase && has_uppercase(&actual_name) {
ctx.diagnostic(data_lowercase_required(
span,
&actual_name.cow_to_lowercase(),
&actual_name.cow_to_ascii_lowercase(),
));
}
return;
Expand All @@ -544,7 +545,7 @@ impl Rule for NoUnknownProperty {
}

DOM_PROPERTIES_LOWER_MAP
.get(&name.cow_to_lowercase().into_owned())
.get(&name.cow_to_ascii_lowercase())
.or_else(|| DOM_ATTRIBUTES_TO_CAMEL.get(name))
.map_or_else(
|| {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/typescript/ban_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl Rule for BanTypes {
"String" | "Boolean" | "Number" | "Symbol" | "BigInt" => {
ctx.diagnostic(type_diagnostic(
name.as_str(),
&name.as_str().cow_to_lowercase(),
&name.as_str().cow_to_ascii_lowercase(),
typ.span,
));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl Rule for NoWrapperObjectTypes {

if can_fix {
ctx.diagnostic_with_fix(no_wrapper_object_types(ident_span), |fixer| {
fixer.replace(ident_span, ident_name.cow_to_lowercase())
fixer.replace(ident_span, ident_name.cow_to_ascii_lowercase())
});
} else {
ctx.diagnostic(no_wrapper_object_types(ident_span));
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/src/rules/unicorn/number_literal_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn check_number_literal(number_literal: &str, raw_span: Span) -> Option<(OxcDiag
Span::new(raw_span.start + 1, raw_span.start + 2),
if number_literal.starts_with("0B") { "0b" } else { "0o" },
),
number_literal.cow_to_lowercase().into_owned(),
number_literal.cow_to_ascii_lowercase().into_owned(),
));
}
if number_literal.starts_with("0X") || number_literal.starts_with("0x") {
Expand Down Expand Up @@ -133,14 +133,14 @@ fn check_number_literal(number_literal: &str, raw_span: Span) -> Option<(OxcDiag
let char_position = raw_span.start + index as u32;
return Some((
uppercase_exponential_notation(Span::new(char_position, char_position + 1)),
number_literal.cow_to_lowercase().into_owned(),
number_literal.cow_to_ascii_lowercase().into_owned(),
));
}
None
}

fn digits_to_uppercase(digits: &str) -> String {
let mut result = digits.cow_to_uppercase().into_owned();
let mut result = digits.cow_to_ascii_uppercase().into_owned();
if result.ends_with('N') {
result.truncate(result.len() - 1);
result.push('n');
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_syntax/src/es_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl FromStr for ESTarget {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.cow_to_lowercase().as_ref() {
match s.cow_to_ascii_lowercase().as_ref() {
"es5" => Ok(Self::ES5),
"es6" | "es2015" => Ok(Self::ES2015),
"es2016" => Ok(Self::ES2016),
Expand Down

0 comments on commit 23b49a6

Please sign in to comment.