perf(rust): use cow_utils instead (#5664)

Related to #5586 and #5662

---------

Co-authored-by: Boshen <boshenc@gmail.com>
This commit is contained in:
dalaoshu 2024-09-11 18:39:30 +08:00 committed by GitHub
parent a729b64380
commit d18c896a2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 146 additions and 78 deletions

View file

@ -1,6 +1,10 @@
ignore-interior-mutability = ["oxc_linter::rule::RuleWithSeverity"]
disallowed-methods = [
{ path = "str::to_ascii_lowercase", reason = "Avoid memory allocation. Use `cow_utils::CowUtils::cow_to_ascii_lowercase` instead." },
{ path = "str::to_ascii_uppercase", reason = "Avoid memory allocation. Use `cow_utils::CowUtils::cow_to_ascii_uppercase` instead." },
{ path = "str::to_ascii_lowercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_lowercase` instead." },
{ path = "str::to_ascii_uppercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_uppercase` instead." },
{ path = "str::to_lowercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_lowercase` instead." },
{ path = "str::to_uppercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_uppercase` instead." },
{ path = "str::replace", reason = "To avoid memory allocation, use `cow_utils::CowUtils::replace` instead." },
{ path = "str::replacen", reason = "To avoid memory allocation, use `cow_utils::CowUtils::replacen` instead." },
]

5
Cargo.lock generated
View file

@ -1525,6 +1525,7 @@ version = "0.28.0"
dependencies = [
"base64",
"bitflags 2.6.0",
"cow-utils",
"daachorse",
"insta",
"nonmax",
@ -1692,6 +1693,7 @@ dependencies = [
name = "oxc_minifier"
version = "0.28.0"
dependencies = [
"cow-utils",
"insta",
"num-bigint",
"num-traits",
@ -1738,6 +1740,7 @@ version = "0.28.0"
dependencies = [
"assert-unchecked",
"bitflags 2.6.0",
"cow-utils",
"memchr",
"num-bigint",
"num-traits",
@ -1871,6 +1874,7 @@ version = "0.28.0"
dependencies = [
"base64-simd",
"cfg-if",
"cow-utils",
"rayon",
"rustc-hash",
"serde",
@ -1927,6 +1931,7 @@ dependencies = [
name = "oxc_transform_conformance"
version = "0.0.0"
dependencies = [
"cow-utils",
"indexmap",
"oxc",
"oxc_tasks_common",

View file

@ -20,6 +20,7 @@ workspace = true
doctest = false
[dependencies]
cow-utils = { workspace = true }
oxc_allocator = { workspace = true }
oxc_ast = { workspace = true }
oxc_index = { workspace = true }

View file

@ -1,5 +1,6 @@
use std::{borrow::Cow, ops::Not};
use cow_utils::CowUtils;
use oxc_allocator::{Box, Vec};
#[allow(clippy::wildcard_imports)]
use oxc_ast::ast::*;
@ -1232,7 +1233,7 @@ impl<'a> Gen for RegExpLiteral<'a> {
);
// Avoid forming a single-line comment or "</script" sequence
if Some('/') == last
|| (Some('<') == last && pattern_text.to_lowercase().starts_with("script"))
|| (Some('<') == last && pattern_text.cow_to_lowercase().starts_with("script"))
{
p.print_hard_space();
}

View file

@ -318,6 +318,7 @@ impl<'a> Fixer<'a> {
#[cfg(test)]
mod test {
use cow_utils::CowUtils;
use std::borrow::Cow;
use oxc_diagnostics::OxcDiagnostic;
@ -417,7 +418,7 @@ mod test {
get_fix_result(vec![create_message(insert_at_middle(), Some(INSERT_AT_MIDDLE))]);
assert_eq!(
result.fixed_code,
TEST_CODE.replace("6 *", &format!("{}{}", INSERT_AT_MIDDLE.content, "6 *"))
TEST_CODE.cow_replace("6 *", &format!("{}{}", INSERT_AT_MIDDLE.content, "6 *"))
);
assert_eq!(result.messages.len(), 0);
}
@ -435,7 +436,7 @@ mod test {
format!(
"{}{}{}",
INSERT_AT_START.content,
TEST_CODE.replace("6 *", &format!("{}{}", INSERT_AT_MIDDLE.content, "6 *")),
TEST_CODE.cow_replace("6 *", &format!("{}{}", INSERT_AT_MIDDLE.content, "6 *")),
INSERT_AT_END.content
)
);
@ -452,7 +453,7 @@ mod test {
#[test]
fn replace_at_the_start() {
let result = get_fix_result(vec![create_message(replace_var(), Some(REPLACE_VAR))]);
assert_eq!(result.fixed_code, TEST_CODE.replace("var", "let"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("var", "let"));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -460,7 +461,7 @@ mod test {
#[test]
fn replace_at_the_middle() {
let result = get_fix_result(vec![create_message(replace_id(), Some(REPLACE_ID))]);
assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("answer", "foo"));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -468,7 +469,7 @@ mod test {
#[test]
fn replace_at_the_end() {
let result = get_fix_result(vec![create_message(replace_num(), Some(REPLACE_NUM))]);
assert_eq!(result.fixed_code, TEST_CODE.replace('6', "5"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace('6', "5"));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -489,7 +490,7 @@ mod test {
#[test]
fn remove_at_the_start() {
let result = get_fix_result(vec![create_message(remove_start(), Some(REMOVE_START))]);
assert_eq!(result.fixed_code, TEST_CODE.replace("var ", ""));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("var ", ""));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -500,7 +501,7 @@ mod test {
remove_middle(Span::default()),
Some(REMOVE_MIDDLE),
)]);
assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "a"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("answer", "a"));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -508,7 +509,7 @@ mod test {
#[test]
fn remove_at_the_end() {
let result = get_fix_result(vec![create_message(remove_end(), Some(REMOVE_END))]);
assert_eq!(result.fixed_code, TEST_CODE.replace(" * 7", ""));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace(" * 7", ""));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -531,7 +532,7 @@ mod test {
create_message(remove_middle(Span::default()), Some(REMOVE_MIDDLE)),
create_message(replace_id(), Some(REPLACE_ID)),
]);
assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("answer", "foo"));
assert_eq!(result.messages.len(), 1);
assert_eq!(result.messages[0].error.to_string(), "removemiddle");
assert!(result.fixed);
@ -543,7 +544,7 @@ mod test {
create_message(remove_start(), Some(REMOVE_START)),
create_message(replace_id(), Some(REPLACE_ID)),
]);
assert_eq!(result.fixed_code, TEST_CODE.replace("var answer", "foo"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("var answer", "foo"));
assert_eq!(result.messages.len(), 0);
assert!(result.fixed);
}
@ -555,7 +556,7 @@ mod test {
create_message(replace_id(), Some(REPLACE_ID)),
create_message(no_fix(Span::default()), None),
]);
assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("answer", "foo"));
assert_eq!(result.messages.len(), 2);
assert_eq!(result.messages[0].error.to_string(), "nofix");
assert_eq!(result.messages[1].error.to_string(), "removemiddle");
@ -591,7 +592,7 @@ mod test {
Message::new(no_fix_2(Span::new(1, 7)), None),
Message::new(no_fix_1(Span::new(1, 3)), None),
]);
assert_eq!(result.fixed_code, TEST_CODE.replace("answer", "foo"));
assert_eq!(result.fixed_code, TEST_CODE.cow_replace("answer", "foo"));
assert_eq!(result.messages.len(), 2);
assert_eq!(result.messages[0].error.to_string(), "nofix1");
assert_eq!(result.messages[1].error.to_string(), "nofix2");

View file

@ -196,7 +196,7 @@ impl NoLossOfPrecision {
} else {
format!("{value:o}")
};
!raw.ends_with(&suffix.to_uppercase())
!raw.ends_with(&suffix.cow_to_uppercase().as_ref())
}
fn base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::SymbolFlags;
use oxc_span::{GetSpan, Span};
@ -32,7 +33,7 @@ pub fn used_ignored(symbol: &Symbol<'_, '_>) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("{pronoun} '{name}' is marked as ignored but is used."))
.with_label(symbol.span().label(format!("'{name}' is declared here")))
.with_help(format!("Consider renaming this {}.", pronoun.to_lowercase()))
.with_help(format!("Consider renaming this {}.", pronoun.cow_to_lowercase()))
}
/// Variable 'x' is declared but never used.
pub fn declared(symbol: &Symbol<'_, '_>) -> OxcDiagnostic {

View file

@ -4,6 +4,7 @@ use std::{
str::FromStr,
};
use cow_utils::CowUtils;
use itertools::Itertools;
use oxc_ast::{
ast::{ImportDeclaration, ImportDeclarationSpecifier, Statement},
@ -210,10 +211,10 @@ impl SortImports {
let mut previous_local_member_name = get_first_local_member_name(previous);
if self.ignore_case {
current_local_member_name =
current_local_member_name.map(|name| name.to_lowercase().into());
previous_local_member_name =
previous_local_member_name.map(|name| name.to_lowercase().into());
current_local_member_name = current_local_member_name
.map(|name| Cow::Owned(name.cow_to_lowercase().into_owned()));
previous_local_member_name = previous_local_member_name
.map(|name| Cow::Owned(name.cow_to_lowercase().into_owned()));
}
// "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
@ -283,7 +284,7 @@ impl SortImports {
let b = window[1].local.name.as_str();
if self.ignore_case {
a.to_lowercase() > b.to_lowercase()
a.cow_to_lowercase() > b.cow_to_lowercase()
} else {
a > b
}
@ -330,7 +331,7 @@ impl SortImports {
let b = b.local.name.as_str();
if self.ignore_case {
a.to_lowercase().cmp(&b.to_lowercase())
a.cow_to_lowercase().cmp(&b.cow_to_lowercase())
} else {
a.cmp(b)
}

View file

@ -1,5 +1,6 @@
use std::{borrow::Cow, cmp::Ordering};
use cow_utils::CowUtils;
use oxc_ast::{
ast::{BindingPatternKind, VariableDeclarator},
AstKind,
@ -93,7 +94,7 @@ impl SortVars {
};
if self.ignore_case {
return Cow::Owned(ident.name.to_lowercase());
return ident.name.as_str().cow_to_lowercase();
}
Cow::Borrowed(ident.name.as_str()) // avoid string allocs in the default case

View file

@ -1,6 +1,7 @@
#![allow(clippy::cast_possible_truncation)]
use std::{ffi::OsStr, path::Component, sync::Arc};
use cow_utils::CowUtils;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, Span};
@ -142,12 +143,13 @@ impl Rule for NoCycle {
let help = stack
.iter()
.map(|(specifier, path)| {
let path = path
.strip_prefix(&cwd)
.unwrap_or(path)
.to_string_lossy()
.replace('\\', "/");
format!("-> {specifier} - {path}")
format!(
"-> {specifier} - {}",
path.strip_prefix(&cwd)
.unwrap_or(path)
.to_string_lossy()
.cow_replace('\\', "/")
)
})
.collect::<Vec<_>>()
.join("\n");

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{
ast::{CallExpression, Expression, Statement},
AstKind,
@ -273,7 +274,13 @@ fn convert_pattern(pattern: &str) -> String {
// request.**.expect* -> request.[a-z\\d\\.]*.expect[a-z\\d]*
let pattern = pattern
.split('.')
.map(|p| if p == "**" { String::from("[a-z\\d\\.]*") } else { p.replace('*', "[a-z\\d]*") })
.map(|p| {
if p == "**" {
String::from("[a-z\\d\\.]*")
} else {
p.cow_replace('*', "[a-z\\d]*").into_owned()
}
})
.collect::<Vec<_>>()
.join("\\.");

View file

@ -1,5 +1,6 @@
use std::{collections::HashMap, hash::Hash};
use cow_utils::CowUtils;
use oxc_ast::{
ast::{Argument, BinaryExpression, Expression},
AstKind,
@ -281,7 +282,7 @@ fn validate_title(
if !valid_title.disallowed_words.is_empty() {
let Ok(disallowed_words_reg) = regex::Regex::new(&format!(
r#"(?iu)\b(?:{})\b"#,
valid_title.disallowed_words.join("|").replace('.', r"\.")
valid_title.disallowed_words.join("|").cow_replace('.', r"\.")
)) else {
return;
};

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{ast::JSXAttributeItem, AstKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -52,7 +53,8 @@ declare_oxc_lint!(
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).to_lowercase();
let name = get_jsx_attribute_name(&attr.name);
let name = name.cow_to_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);

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{ast::JSXAttributeItem, AstKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -57,7 +58,8 @@ impl Rule for AriaUnsupportedElements {
JSXAttributeItem::Attribute(attr) => attr,
JSXAttributeItem::SpreadAttribute(_) => continue,
};
let attr_name = get_jsx_attribute_name(&attr.name).to_lowercase();
let attr_name = get_jsx_attribute_name(&attr.name);
let attr_name = attr_name.cow_to_lowercase();
if INVALID_ATTRIBUTES.contains(&attr_name) {
ctx.diagnostic_with_fix(
aria_unsupported_elements_diagnostic(attr.span, &attr_name),

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{
ast::{JSXAttributeItem, JSXOpeningElement},
AstKind,
@ -84,8 +85,9 @@ impl Rule for RoleSupportsAriaProps {
let invalid_props = get_invalid_aria_props_for_role(role_value);
for attr in &jsx_el.attributes {
if let JSXAttributeItem::Attribute(attr) = attr {
let name = get_jsx_attribute_name(&attr.name).to_lowercase();
if invalid_props.contains(&&name.as_str()) {
let name = get_jsx_attribute_name(&attr.name);
let name = name.cow_to_lowercase();
if invalid_props.contains(&&name.as_ref()) {
ctx.diagnostic(if is_implicit {
is_implicit_diagnostic(attr.span, &name, role_value, &el_type)
} else {

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{
ast::{Expression, JSXAttributeItem, JSXAttributeName, JSXElement, JSXFragment, Statement},
AstKind,
@ -91,7 +92,7 @@ pub fn import_matcher<'a>(
actual_local_name: &'a str,
expected_module_name: &'a str,
) -> bool {
let expected_module_name = expected_module_name.to_lowercase();
let expected_module_name = expected_module_name.cow_to_lowercase();
ctx.semantic().module_record().import_entries.iter().any(|import| {
import.module_request.name().as_str() == expected_module_name
&& import.local_name.name().as_str() == actual_local_name

View file

@ -1,5 +1,6 @@
use std::{borrow::Cow, collections::hash_map::HashMap};
use cow_utils::CowUtils;
use itertools::Itertools;
use once_cell::sync::Lazy;
use oxc_ast::{
@ -421,7 +422,10 @@ const DOM_PROPERTIES_IGNORE_CASE: [&str; 5] = [
];
static DOM_PROPERTIES_LOWER_MAP: Lazy<HashMap<String, &'static str>> = Lazy::new(|| {
DOM_PROPERTIES_NAMES.iter().map(|it| (it.to_lowercase(), *it)).collect::<HashMap<_, _>>()
DOM_PROPERTIES_NAMES
.iter()
.map(|it| (it.cow_to_lowercase().into_owned(), *it))
.collect::<HashMap<_, _>>()
});
///
@ -433,7 +437,7 @@ static DOM_PROPERTIES_LOWER_MAP: Lazy<HashMap<String, &'static str>> = Lazy::new
fn is_valid_data_attr(name: &str) -> bool {
static DATA_ATTR_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^data(-?[^:]*)$").unwrap());
!name.to_lowercase().starts_with("data-xml") && DATA_ATTR_REGEX.is_match(name)
!name.cow_to_lowercase().starts_with("data-xml") && DATA_ATTR_REGEX.is_match(name)
}
fn normalize_attribute_case(name: &str) -> &str {
@ -496,7 +500,10 @@ impl Rule for NoUnknownProperty {
};
if is_valid_data_attr(&actual_name) {
if self.0.require_data_lowercase && has_uppercase(&actual_name) {
ctx.diagnostic(data_lowercase_required(span, &actual_name.to_lowercase()));
ctx.diagnostic(data_lowercase_required(
span,
&actual_name.cow_to_lowercase(),
));
}
return;
};
@ -520,7 +527,7 @@ impl Rule for NoUnknownProperty {
}
DOM_PROPERTIES_LOWER_MAP
.get(&name.to_lowercase())
.get(&name.cow_to_lowercase().into_owned())
.or_else(|| DOM_ATTRIBUTES_TO_CAMEL.get(name))
.map_or_else(
|| {

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::CommentKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -178,7 +179,7 @@ impl Rule for BanTsComment {
|fixer| {
fixer.replace(
comm.span,
raw.replace("@ts-ignore", "@ts-expect-error"),
raw.cow_replace("@ts-ignore", "@ts-expect-error"),
)
},
);

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -65,7 +66,7 @@ impl Rule for BanTypes {
"String" | "Boolean" | "Number" | "Symbol" | "BigInt" => {
ctx.diagnostic(type_diagnostic(
name.as_str(),
&name.to_lowercase(),
&name.as_str().cow_to_lowercase(),
typ.span,
));
}

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::{
ast::{Expression, TSTypeName},
AstKind,
@ -91,7 +92,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.to_lowercase())
fixer.replace(ident_span, ident_name.cow_to_lowercase())
});
} else {
ctx.diagnostic(no_wrapper_object_types(ident_span));

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::CommentKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -58,7 +59,7 @@ impl Rule for PreferTsExpectError {
ctx.diagnostic_with_fix(prefer_ts_expect_error_diagnostic(comment_span), |fixer| {
fixer.replace(
comment_span,
format!("//{}", raw.replace("@ts-ignore", "@ts-expect-error")),
format!("//{}", raw.cow_replace("@ts-ignore", "@ts-expect-error")),
)
});
} else {
@ -66,7 +67,7 @@ impl Rule for PreferTsExpectError {
ctx.diagnostic_with_fix(prefer_ts_expect_error_diagnostic(comment_span), |fixer| {
fixer.replace(
comment_span,
format!("/*{}*/", raw.replace("@ts-ignore", "@ts-expect-error")),
format!("/*{}*/", raw.cow_replace("@ts-ignore", "@ts-expect-error")),
)
});
}

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@ -101,7 +102,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.to_lowercase(),
number_literal.cow_to_lowercase().into_owned(),
));
}
if number_literal.starts_with("0X") || number_literal.starts_with("0x") {
@ -131,14 +132,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.to_lowercase(),
number_literal.cow_to_lowercase().into_owned(),
));
}
None
}
fn digits_to_uppercase(digits: &str) -> String {
let mut result = digits.to_uppercase();
let mut result = digits.cow_to_uppercase().into_owned();
if result.ends_with('N') {
result.truncate(result.len() - 1);
result.push('n');

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use lazy_static::lazy_static;
use oxc_ast::{
ast::{BigIntLiteral, NumericLiteral},
@ -177,7 +178,7 @@ impl NumericSeparatorsStyle {
fn format_binary(&self, raw_number: &str) -> String {
let prefix = &raw_number[0..2];
let mut to_format = raw_number[2..].replace('_', "");
let mut to_format = raw_number[2..].cow_replace('_', "").into_owned();
add_separators(&mut to_format, &SeparatorDir::Right, &self.binary);
to_format.insert_str(0, prefix);
@ -187,7 +188,7 @@ impl NumericSeparatorsStyle {
fn format_hex(&self, number_raw: &str) -> String {
let prefix = &number_raw[0..2];
let mut to_format = number_raw[2..].replace('_', "");
let mut to_format = number_raw[2..].cow_replace('_', "").into_owned();
add_separators(&mut to_format, &SeparatorDir::Right, &self.hexadecimal);
to_format.insert_str(0, prefix);
@ -204,7 +205,7 @@ impl NumericSeparatorsStyle {
let prefix = &number_raw[0..2];
let mut to_format = number_raw[2..].replace('_', "");
let mut to_format = number_raw[2..].cow_replace('_', "").into_owned();
add_separators(&mut to_format, &SeparatorDir::Right, &self.octal);
to_format.insert_str(0, prefix);
@ -222,7 +223,7 @@ impl NumericSeparatorsStyle {
let mut out = String::new();
{
let number = caps.get(1).unwrap().as_str().replace('_', "");
let number = caps.get(1).unwrap().as_str().cow_replace('_', "").into_owned();
if let Some((whole, decimal)) = number.split_once('.') {
if !whole.is_empty() {
@ -251,7 +252,7 @@ impl NumericSeparatorsStyle {
out.push_str(sign.as_str());
}
if let Some(power) = caps.get(4) {
let mut s = power.as_str().replace('_', "");
let mut s = power.as_str().cow_replace('_', "").into_owned();
add_separators(&mut s, &SeparatorDir::Right, &self.number);
out.push_str(&s);
}

View file

@ -3,6 +3,7 @@ use std::{
path::{Path, PathBuf},
};
use cow_utils::CowUtils;
use oxc_allocator::Allocator;
use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler, GraphicalTheme, NamedSource};
use serde::Deserialize;
@ -185,7 +186,8 @@ impl Tester {
expect_pass: Vec<T>,
expect_fail: Vec<T>,
) -> Self {
let rule_path = PathBuf::from(rule_name.replace('-', "_")).with_extension("tsx");
let rule_path =
PathBuf::from(rule_name.cow_replace('-', "_").into_owned()).with_extension("tsx");
let expect_pass = expect_pass.into_iter().map(Into::into).collect::<Vec<_>>();
let expect_fail = expect_fail.into_iter().map(Into::into).collect::<Vec<_>>();
let current_working_directory =
@ -294,7 +296,7 @@ impl Tester {
}
fn snapshot(&self) {
let name = self.rule_name.replace('-', "_");
let name = self.rule_name.cow_replace('-', "_");
let mut settings = insta::Settings::clone_current();
settings.set_prepend_module_to_snapshot(false);
@ -304,7 +306,7 @@ impl Tester {
}
settings.bind(|| {
insta::assert_snapshot!(name, self.snapshot);
insta::assert_snapshot!(name.as_ref(), self.snapshot);
});
}

View file

@ -21,6 +21,7 @@ test = false
doctest = false
[dependencies]
cow-utils = { workspace = true }
oxc_allocator = { workspace = true }
oxc_ast = { workspace = true }
oxc_codegen = { workspace = true }

View file

@ -1,9 +1,9 @@
use std::sync::Arc;
use cow_utils::CowUtils;
use oxc_allocator::Allocator;
use oxc_ast::{ast::*, visit::walk_mut, AstBuilder, VisitMut};
use oxc_semantic::{ScopeTree, SymbolTable};
use oxc_span::{CompactStr, SPAN};
use std::sync::Arc;
use super::replace_global_defines::{DotDefine, ReplaceGlobalDefines};
@ -58,7 +58,7 @@ impl InjectImport {
fn replace_name(local: &str) -> Option<CompactStr> {
local
.contains('.')
.then(|| CompactStr::from(format!("$inject_{}", local.replace('.', "_"))))
.then(|| CompactStr::from(format!("$inject_{}", local.cow_replace('.', "_"))))
}
}

View file

@ -28,6 +28,7 @@ oxc_syntax = { workspace = true }
assert-unchecked = { workspace = true }
bitflags = { workspace = true }
cow-utils = { workspace = true }
num-bigint = { workspace = true }
num-traits = { workspace = true }
rustc-hash = { workspace = true }

View file

@ -1,3 +1,4 @@
use cow_utils::CowUtils;
use oxc_allocator::Box;
use oxc_ast::ast::*;
use oxc_diagnostics::Result;
@ -517,7 +518,7 @@ impl<'a> ParserImpl<'a> {
let cur_src = self.cur_src();
let raw = &cur_src[1..cur_src.len() - end_offset as usize];
let raw = Atom::from(if cooked.is_some() && raw.contains('\r') {
self.ast.str(raw.replace("\r\n", "\n").replace('\r', "\n").as_str())
self.ast.str(&raw.cow_replace("\r\n", "\n").cow_replace('\r', "\n"))
} else {
raw
});

View file

@ -5,6 +5,7 @@
use std::borrow::Cow;
use cow_utils::CowUtils;
use num_bigint::BigInt;
use num_traits::Num;
@ -40,7 +41,7 @@ pub fn parse_int(s: &str, kind: Kind, has_sep: bool) -> Result<f64, &'static str
}
pub fn parse_float(s: &str, has_sep: bool) -> Result<f64, &'static str> {
let s = if has_sep { Cow::Owned(s.replace('_', "")) } else { Cow::Borrowed(s) };
let s = if has_sep { s.cow_replace('_', "") } else { Cow::Borrowed(s) };
debug_assert!(!s.contains('_'));
s.parse::<f64>().map_err(|_| "invalid float")
}
@ -93,7 +94,7 @@ fn parse_decimal_with_underscores(s: &str) -> f64 {
debug_assert!(!s.is_empty());
if s.len() > MAX_FAST_DECIMAL_LEN {
return parse_decimal_slow(&s.replace('_', ""));
return parse_decimal_slow(&s.cow_replace('_', ""));
}
let mut result = 0_u64;
@ -391,7 +392,7 @@ fn parse_hex_with_underscores_slow(s: &str) -> f64 {
// ==================================== BIGINT ====================================
pub fn parse_big_int(s: &str, kind: Kind, has_sep: bool) -> Result<BigInt, &'static str> {
let s = if has_sep { Cow::Owned(s.replace('_', "")) } else { Cow::Borrowed(s) };
let s = if has_sep { s.cow_replace('_', "") } else { Cow::Borrowed(s) };
debug_assert!(!s.contains('_'));
parse_big_int_without_underscores(&s, kind)
}

View file

@ -21,6 +21,7 @@ doctest = false
[dependencies]
base64-simd = { workspace = true }
cfg-if = { workspace = true }
cow-utils = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }

View file

@ -1,6 +1,9 @@
use std::borrow::Cow;
use rustc_hash::FxHashMap;
use crate::SourceMap;
use cow_utils::CowUtils;
/// The `SourcemapVisualizer` is a helper for sourcemap testing.
/// It print the mapping of original content and final content tokens.
@ -151,16 +154,18 @@ impl<'a> SourcemapVisualizer<'a> {
tables
}
fn str_slice_by_token(buff: &[Vec<u16>], start: (u32, u32), end: (u32, u32)) -> String {
fn str_slice_by_token(buff: &[Vec<u16>], start: (u32, u32), end: (u32, u32)) -> Cow<'_, str> {
if start.0 == end.0 {
if start.1 <= end.1 {
return String::from_utf16(
&buff[start.0 as usize][start.1 as usize..end.1 as usize],
)
.unwrap();
return Cow::Owned(
String::from_utf16(&buff[start.0 as usize][start.1 as usize..end.1 as usize])
.unwrap(),
);
}
return String::from_utf16(&buff[start.0 as usize][end.1 as usize..start.1 as usize])
.unwrap();
return Cow::Owned(
String::from_utf16(&buff[start.0 as usize][end.1 as usize..start.1 as usize])
.unwrap(),
);
}
let mut s = String::new();
@ -175,8 +180,10 @@ impl<'a> SourcemapVisualizer<'a> {
}
}
let replaced: Cow<str> = s.cow_replace("\r", "");
// Windows: Replace "\r\n" and replace with "\n"
s.replace('\r', "")
Cow::Owned(replaced.into_owned())
}
}

View file

@ -1,3 +1,4 @@
#![allow(clippy::disallowed_methods)]
use std::{cell::RefCell, io::Read, path::PathBuf, rc::Rc};
use bpaf::{Bpaf, Parser};

View file

@ -1,3 +1,4 @@
#![allow(clippy::disallowed_methods)]
use oxc_allocator::Allocator;
use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion};
use oxc_parser::lexer::{Kind, Lexer};

View file

@ -1,4 +1,4 @@
#![allow(clippy::print_stdout)]
#![allow(clippy::print_stdout, clippy::disallowed_methods)]
use std::path::{Path, PathBuf};
mod diff;

View file

@ -1,4 +1,4 @@
#![allow(clippy::print_stdout, clippy::print_stderr)]
#![allow(clippy::print_stdout, clippy::print_stderr, clippy::disallowed_methods)]
// Core
mod runtime;
mod suite;

View file

@ -1,4 +1,4 @@
#![allow(clippy::print_stdout, clippy::print_stderr)]
#![allow(clippy::print_stdout, clippy::print_stderr, clippy::disallowed_methods)]
mod ignore_list;
mod spec;

View file

@ -1,4 +1,4 @@
#![allow(clippy::print_stdout, clippy::print_stderr)]
#![allow(clippy::print_stdout, clippy::print_stderr, clippy::disallowed_methods)]
use std::{
borrow::Cow,
collections::HashMap,

View file

@ -25,6 +25,7 @@ doctest = false
oxc = { workspace = true, features = ["full"] }
oxc_tasks_common = { workspace = true }
cow-utils = { workspace = true }
indexmap = { workspace = true }
pico-args = { workspace = true }
walkdir = { workspace = true }

View file

@ -3,6 +3,7 @@ use std::{
path::{Path, PathBuf},
};
use cow_utils::CowUtils;
use oxc::{
allocator::Allocator,
codegen::CodeGenerator,
@ -288,7 +289,7 @@ impl TestCase for ConformanceTestCase {
let output;
let passed = if let Some(throws) = &babel_options.throws {
output = throws.to_string().replace(" (1:6)", "");
output = throws.cow_replace(" (1:6)", "").into_owned();
!output.is_empty()
&& actual_errors.as_ref().is_some_and(|errors| errors.contains(&output))
} else {

View file

@ -1,3 +1,8 @@
#![allow(clippy::print_stdout, clippy::print_stderr, clippy::missing_panics_doc)]
#![allow(
clippy::print_stdout,
clippy::print_stderr,
clippy::missing_panics_doc,
clippy::disallowed_methods
)]
pub mod linter;