mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf: replace some CompactStr usages with Cows (#4377)
Reduce memory allocations in semantic and linter by using `Cow<'a, str>` over `CompactStr`
This commit is contained in:
parent
7a3e92591f
commit
a207923af1
11 changed files with 96 additions and 55 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
use std::{cell::Cell, fmt, hash::Hash};
|
use std::{borrow::Cow, cell::Cell, fmt, hash::Hash};
|
||||||
|
|
||||||
use oxc_allocator::{Box, FromIn, Vec};
|
use oxc_allocator::{Box, FromIn, Vec};
|
||||||
use oxc_span::{Atom, CompactStr, GetSpan, SourceType, Span};
|
use oxc_span::{Atom, GetSpan, SourceType, Span};
|
||||||
use oxc_syntax::{
|
use oxc_syntax::{
|
||||||
operator::UnaryOperator,
|
operator::UnaryOperator,
|
||||||
reference::{ReferenceFlag, ReferenceId},
|
reference::{ReferenceFlag, ReferenceId},
|
||||||
|
|
@ -332,20 +332,20 @@ impl<'a> ObjectExpression<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PropertyKey<'a> {
|
impl<'a> PropertyKey<'a> {
|
||||||
pub fn static_name(&self) -> Option<CompactStr> {
|
pub fn static_name(&self) -> Option<Cow<'a, str>> {
|
||||||
match self {
|
match self {
|
||||||
Self::StaticIdentifier(ident) => Some(ident.name.to_compact_str()),
|
Self::StaticIdentifier(ident) => Some(Cow::Borrowed(ident.name.as_str())),
|
||||||
Self::StringLiteral(lit) => Some(lit.value.to_compact_str()),
|
Self::StringLiteral(lit) => Some(Cow::Borrowed(lit.value.as_str())),
|
||||||
Self::RegExpLiteral(lit) => Some(lit.regex.to_string().into()),
|
Self::RegExpLiteral(lit) => Some(Cow::Owned(lit.regex.to_string())),
|
||||||
Self::NumericLiteral(lit) => Some(lit.value.to_string().into()),
|
Self::NumericLiteral(lit) => Some(Cow::Owned(lit.value.to_string())),
|
||||||
Self::BigIntLiteral(lit) => Some(lit.raw.to_compact_str()),
|
Self::BigIntLiteral(lit) => Some(Cow::Borrowed(lit.raw.as_str())),
|
||||||
Self::NullLiteral(_) => Some("null".into()),
|
Self::NullLiteral(_) => Some(Cow::Borrowed("null")),
|
||||||
Self::TemplateLiteral(lit) => lit
|
Self::TemplateLiteral(lit) => lit
|
||||||
.expressions
|
.expressions
|
||||||
.is_empty()
|
.is_empty()
|
||||||
.then(|| lit.quasi())
|
.then(|| lit.quasi())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|quasi| quasi.to_compact_str()),
|
.map(std::convert::Into::into),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -369,9 +369,9 @@ impl<'a> PropertyKey<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> Option<CompactStr> {
|
pub fn name(&self) -> Option<Cow<'a, str>> {
|
||||||
if self.is_private_identifier() {
|
if self.is_private_identifier() {
|
||||||
self.private_name().map(|name| name.to_compact_str())
|
self.private_name().map(|name| Cow::Borrowed(name.as_str()))
|
||||||
} else {
|
} else {
|
||||||
self.static_name()
|
self.static_name()
|
||||||
}
|
}
|
||||||
|
|
@ -1237,7 +1237,7 @@ impl<'a> ClassElement<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn static_name(&self) -> Option<CompactStr> {
|
pub fn static_name(&self) -> Option<Cow<'a, str>> {
|
||||||
match self {
|
match self {
|
||||||
Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
|
Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
|
||||||
Self::MethodDefinition(def) => def.key.static_name(),
|
Self::MethodDefinition(def) => def.key.static_name(),
|
||||||
|
|
@ -1424,8 +1424,8 @@ impl<'a> ImportDeclarationSpecifier<'a> {
|
||||||
ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => &specifier.local,
|
ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => &specifier.local,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn name(&self) -> CompactStr {
|
pub fn name(&self) -> Cow<'a, str> {
|
||||||
self.local().name.to_compact_str()
|
Cow::Borrowed(self.local().name.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
||||||
self.scope.has_reference(&specifier.local.name)
|
self.scope.has_reference(&specifier.local.name)
|
||||||
}
|
}
|
||||||
ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => {
|
ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => {
|
||||||
self.scope.has_reference(specifier.name().as_str())
|
self.scope.has_reference(&specifier.name())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if specifiers.is_empty() {
|
if specifiers.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
fmt::{Display, Write},
|
fmt::{Display, Write},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
@ -10,7 +11,7 @@ use oxc_ast::{
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_span::{CompactStr, Span};
|
use oxc_span::Span;
|
||||||
|
|
||||||
use crate::{context::LintContext, rule::Rule};
|
use crate::{context::LintContext, rule::Rule};
|
||||||
|
|
||||||
|
|
@ -208,9 +209,9 @@ impl SortImports {
|
||||||
|
|
||||||
if self.ignore_case {
|
if self.ignore_case {
|
||||||
current_local_member_name =
|
current_local_member_name =
|
||||||
current_local_member_name.map(|name| name.to_lowercase()).map(CompactStr::from);
|
current_local_member_name.map(|name| name.to_lowercase().into());
|
||||||
previous_local_member_name =
|
previous_local_member_name =
|
||||||
previous_local_member_name.map(|name| name.to_lowercase()).map(CompactStr::from);
|
previous_local_member_name.map(|name| name.to_lowercase().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
|
// "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
|
||||||
|
|
@ -240,8 +241,6 @@ impl SortImports {
|
||||||
if let Some((current_name, previous_name)) =
|
if let Some((current_name, previous_name)) =
|
||||||
current_local_member_name.zip(previous_local_member_name)
|
current_local_member_name.zip(previous_local_member_name)
|
||||||
{
|
{
|
||||||
let current_name = current_name.as_str();
|
|
||||||
let previous_name = previous_name.as_str();
|
|
||||||
if current_name < previous_name {
|
if current_name < previous_name {
|
||||||
ctx.diagnostic(sort_imports_alphabetically_diagnostic(current.span));
|
ctx.diagnostic(sort_imports_alphabetically_diagnostic(current.span));
|
||||||
}
|
}
|
||||||
|
|
@ -443,7 +442,7 @@ impl Display for ImportKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_first_local_member_name(decl: &ImportDeclaration) -> Option<CompactStr> {
|
fn get_first_local_member_name<'a>(decl: &ImportDeclaration<'a>) -> Option<Cow<'a, str>> {
|
||||||
let specifiers = decl.specifiers.as_ref()?;
|
let specifiers = decl.specifiers.as_ref()?;
|
||||||
specifiers.first().map(ImportDeclarationSpecifier::name)
|
specifiers.first().map(ImportDeclarationSpecifier::name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ impl Rule for NoDanger {
|
||||||
for prop in &obj_expr.properties {
|
for prop in &obj_expr.properties {
|
||||||
if let ObjectPropertyKind::ObjectProperty(obj_prop) = prop {
|
if let ObjectPropertyKind::ObjectProperty(obj_prop) = prop {
|
||||||
if let Some(prop_name) = obj_prop.key.static_name() {
|
if let Some(prop_name) = obj_prop.key.static_name() {
|
||||||
if prop_name.as_str() == "dangerouslySetInnerHTML" {
|
if prop_name == "dangerouslySetInnerHTML" {
|
||||||
ctx.diagnostic(no_danger_diagnostic(obj_prop.key.span()));
|
ctx.diagnostic(no_danger_diagnostic(obj_prop.key.span()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{ArrowFunctionExpression, Function},
|
ast::{ArrowFunctionExpression, Function},
|
||||||
AstKind,
|
AstKind,
|
||||||
|
|
@ -8,7 +10,6 @@ use oxc_cfg::{
|
||||||
};
|
};
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_semantic::{AstNodeId, AstNodes};
|
use oxc_semantic::{AstNodeId, AstNodes};
|
||||||
use oxc_span::CompactStr;
|
|
||||||
use oxc_syntax::operator::AssignmentOperator;
|
use oxc_syntax::operator::AssignmentOperator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -191,7 +192,7 @@ impl Rule for RulesOfHooks {
|
||||||
// useState(0);
|
// useState(0);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if ident.is_some_and(|name| !is_react_component_or_hook_name(name.as_str()))
|
if ident.is_some_and(|name| !is_react_component_or_hook_name(&name))
|
||||||
|| is_export_default(nodes, parent_func.id())
|
|| is_export_default(nodes, parent_func.id())
|
||||||
{
|
{
|
||||||
return ctx.diagnostic(diagnostics::function_error(
|
return ctx.diagnostic(diagnostics::function_error(
|
||||||
|
|
@ -352,7 +353,9 @@ fn is_somewhere_inside_component_or_hook(nodes: &AstNodes, node_id: AstNodeId) -
|
||||||
(
|
(
|
||||||
node.id(),
|
node.id(),
|
||||||
match node.kind() {
|
match node.kind() {
|
||||||
AstKind::Function(func) => func.id.as_ref().map(|it| it.name.to_compact_str()),
|
AstKind::Function(func) => {
|
||||||
|
func.id.as_ref().map(|it| Cow::Borrowed(it.name.as_str()))
|
||||||
|
}
|
||||||
AstKind::ArrowFunctionExpression(_) => {
|
AstKind::ArrowFunctionExpression(_) => {
|
||||||
get_declaration_identifier(nodes, node.id())
|
get_declaration_identifier(nodes, node.id())
|
||||||
}
|
}
|
||||||
|
|
@ -362,8 +365,7 @@ fn is_somewhere_inside_component_or_hook(nodes: &AstNodes, node_id: AstNodeId) -
|
||||||
})
|
})
|
||||||
.any(|(id, ident)| {
|
.any(|(id, ident)| {
|
||||||
ident.is_some_and(|name| {
|
ident.is_some_and(|name| {
|
||||||
is_react_component_or_hook_name(name.as_str())
|
is_react_component_or_hook_name(&name) || is_memo_or_forward_ref_callback(nodes, id)
|
||||||
|| is_memo_or_forward_ref_callback(nodes, id)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -371,12 +373,12 @@ fn is_somewhere_inside_component_or_hook(nodes: &AstNodes, node_id: AstNodeId) -
|
||||||
fn get_declaration_identifier<'a>(
|
fn get_declaration_identifier<'a>(
|
||||||
nodes: &'a AstNodes<'a>,
|
nodes: &'a AstNodes<'a>,
|
||||||
node_id: AstNodeId,
|
node_id: AstNodeId,
|
||||||
) -> Option<CompactStr> {
|
) -> Option<Cow<'a, str>> {
|
||||||
nodes.ancestors(node_id).map(|id| nodes.kind(id)).find_map(|kind| {
|
nodes.ancestors(node_id).map(|id| nodes.kind(id)).find_map(|kind| {
|
||||||
match kind {
|
match kind {
|
||||||
// const useHook = () => {};
|
// const useHook = () => {};
|
||||||
AstKind::VariableDeclaration(decl) if decl.declarations.len() == 1 => {
|
AstKind::VariableDeclaration(decl) if decl.declarations.len() == 1 => {
|
||||||
decl.declarations[0].id.get_identifier().map(|id| id.to_compact_str())
|
decl.declarations[0].id.get_identifier().map(|id| Cow::Borrowed(id.as_str()))
|
||||||
}
|
}
|
||||||
// useHook = () => {};
|
// useHook = () => {};
|
||||||
AstKind::AssignmentExpression(expr)
|
AstKind::AssignmentExpression(expr)
|
||||||
|
|
@ -387,7 +389,7 @@ fn get_declaration_identifier<'a>(
|
||||||
// const {useHook = () => {}} = {};
|
// const {useHook = () => {}} = {};
|
||||||
// ({useHook = () => {}} = {});
|
// ({useHook = () => {}} = {});
|
||||||
AstKind::AssignmentPattern(patt) => {
|
AstKind::AssignmentPattern(patt) => {
|
||||||
patt.left.get_identifier().map(|id| id.to_compact_str())
|
patt.left.get_identifier().map(|id| Cow::Borrowed(id.as_str()))
|
||||||
}
|
}
|
||||||
// { useHook: () => {} }
|
// { useHook: () => {} }
|
||||||
// { useHook() {} }
|
// { useHook() {} }
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ impl GetMethod for ClassElement<'_> {
|
||||||
fn get_method(&self) -> Option<Method> {
|
fn get_method(&self) -> Option<Method> {
|
||||||
match self {
|
match self {
|
||||||
ClassElement::MethodDefinition(def) => def.key.static_name().map(|name| Method {
|
ClassElement::MethodDefinition(def) => def.key.static_name().map(|name| Method {
|
||||||
name,
|
name: name.into(),
|
||||||
r#static: def.r#static,
|
r#static: def.r#static,
|
||||||
call_signature: false,
|
call_signature: false,
|
||||||
kind: get_kind_from_key(&def.key),
|
kind: get_kind_from_key(&def.key),
|
||||||
|
|
@ -142,7 +142,7 @@ impl GetMethod for TSSignature<'_> {
|
||||||
fn get_method(&self) -> Option<Method> {
|
fn get_method(&self) -> Option<Method> {
|
||||||
match self {
|
match self {
|
||||||
TSSignature::TSMethodSignature(sig) => sig.key.static_name().map(|name| Method {
|
TSSignature::TSMethodSignature(sig) => sig.key.static_name().map(|name| Method {
|
||||||
name: name.clone(),
|
name: name.into(),
|
||||||
r#static: false,
|
r#static: false,
|
||||||
call_signature: false,
|
call_signature: false,
|
||||||
kind: get_kind_from_key(&sig.key),
|
kind: get_kind_from_key(&sig.key),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{error::Error, ops::Deref};
|
use std::{borrow::Cow, error::Error, ops::Deref};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
|
|
@ -11,7 +11,7 @@ use oxc_ast::{
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
use oxc_macros::declare_oxc_lint;
|
use oxc_macros::declare_oxc_lint;
|
||||||
use oxc_semantic::{Reference, SymbolId};
|
use oxc_semantic::{Reference, SymbolId};
|
||||||
use oxc_span::{CompactStr, GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::LintContext,
|
context::LintContext,
|
||||||
|
|
@ -231,7 +231,7 @@ impl Rule for ConsistentTypeImports {
|
||||||
|
|
||||||
// ['foo', 'bar', 'baz' ] => "foo, bar, and baz".
|
// ['foo', 'bar', 'baz' ] => "foo, bar, and baz".
|
||||||
let type_imports = format_word_list(&type_names);
|
let type_imports = format_word_list(&type_names);
|
||||||
let type_names = type_names.iter().map(CompactStr::as_str).collect::<Vec<_>>();
|
let type_names = type_names.iter().map(std::convert::AsRef::as_ref).collect::<Vec<_>>();
|
||||||
|
|
||||||
let fixer_fn = |fixer: RuleFixer<'_, 'a>| {
|
let fixer_fn = |fixer: RuleFixer<'_, 'a>| {
|
||||||
let fix_options = FixOptions {
|
let fix_options = FixOptions {
|
||||||
|
|
@ -272,13 +272,13 @@ impl Rule for ConsistentTypeImports {
|
||||||
// the `and` clause inserted before the last item.
|
// the `and` clause inserted before the last item.
|
||||||
//
|
//
|
||||||
// Example: ['foo', 'bar', 'baz' ] returns the string "foo, bar, and baz".
|
// Example: ['foo', 'bar', 'baz' ] returns the string "foo, bar, and baz".
|
||||||
fn format_word_list(words: &[CompactStr]) -> String {
|
fn format_word_list<'a>(words: &[Cow<'a, str>]) -> Cow<'a, str> {
|
||||||
match words.len() {
|
match words.len() {
|
||||||
0 => String::new(),
|
0 => Cow::Borrowed(""),
|
||||||
1 => words[0].to_string(),
|
1 => words[0].clone(),
|
||||||
2 => format!("{} and {}", words[0], words[1]),
|
2 => Cow::Owned(format!("{} and {}", words[0], words[1])),
|
||||||
_ => {
|
_ => {
|
||||||
let mut result = String::new();
|
let mut result = String::with_capacity(words.len() * 2);
|
||||||
for (i, word) in words.iter().enumerate() {
|
for (i, word) in words.iter().enumerate() {
|
||||||
if i == words.len() - 1 {
|
if i == words.len() - 1 {
|
||||||
result.push_str(&format!("and {word}"));
|
result.push_str(&format!("and {word}"));
|
||||||
|
|
@ -286,7 +286,7 @@ fn format_word_list(words: &[CompactStr]) -> String {
|
||||||
result.push_str(&format!("{word}, "));
|
result.push_str(&format!("{word}, "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
Cow::Owned(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,19 +316,19 @@ impl ExplicitFunctionReturnType {
|
||||||
let Some(name) = def.key.name() else { return false };
|
let Some(name) = def.key.name() else { return false };
|
||||||
def.key.is_identifier()
|
def.key.is_identifier()
|
||||||
&& !def.computed
|
&& !def.computed
|
||||||
&& self.allowed_names.contains(name.as_str())
|
&& self.allowed_names.contains(name.as_ref())
|
||||||
}
|
}
|
||||||
AstKind::PropertyDefinition(def) => {
|
AstKind::PropertyDefinition(def) => {
|
||||||
let Some(name) = def.key.name() else { return false };
|
let Some(name) = def.key.name() else { return false };
|
||||||
def.key.is_identifier()
|
def.key.is_identifier()
|
||||||
&& !def.computed
|
&& !def.computed
|
||||||
&& self.allowed_names.contains(name.as_str())
|
&& self.allowed_names.contains(name.as_ref())
|
||||||
}
|
}
|
||||||
AstKind::ObjectProperty(prop) => {
|
AstKind::ObjectProperty(prop) => {
|
||||||
let Some(name) = prop.key.name() else { return false };
|
let Some(name) = prop.key.name() else { return false };
|
||||||
prop.key.is_identifier()
|
prop.key.is_identifier()
|
||||||
&& !prop.computed
|
&& !prop.computed
|
||||||
&& self.allowed_names.contains(name.as_str())
|
&& self.allowed_names.contains(name.as_ref())
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ impl ClassTableBuilder {
|
||||||
self.classes.add_element(
|
self.classes.add_element(
|
||||||
class_id,
|
class_id,
|
||||||
Element::new(
|
Element::new(
|
||||||
name,
|
name.into(),
|
||||||
property.key.span(),
|
property.key.span(),
|
||||||
property.r#static,
|
property.r#static,
|
||||||
is_private,
|
is_private,
|
||||||
|
|
@ -83,7 +83,7 @@ impl ClassTableBuilder {
|
||||||
self.classes.add_element(
|
self.classes.add_element(
|
||||||
class_id,
|
class_id,
|
||||||
Element::new(
|
Element::new(
|
||||||
name,
|
name.into(),
|
||||||
property.key.span(),
|
property.key.span(),
|
||||||
property.r#static,
|
property.r#static,
|
||||||
is_private,
|
is_private,
|
||||||
|
|
@ -124,18 +124,14 @@ impl ClassTableBuilder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let is_private = method.key.is_private_identifier();
|
let is_private = method.key.is_private_identifier();
|
||||||
let name = if is_private {
|
let name = method.key.name();
|
||||||
method.key.private_name().map(|name| name.to_compact_str())
|
|
||||||
} else {
|
|
||||||
method.key.static_name()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
if let Some(class_id) = self.current_class_id {
|
if let Some(class_id) = self.current_class_id {
|
||||||
self.classes.add_element(
|
self.classes.add_element(
|
||||||
class_id,
|
class_id,
|
||||||
Element::new(
|
Element::new(
|
||||||
name,
|
name.into(),
|
||||||
method.key.span(),
|
method.key.span(),
|
||||||
method.r#static,
|
method.r#static,
|
||||||
is_private,
|
is_private,
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,13 @@ impl<'a> From<Atom<'a>> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Atom<'a>> for Cow<'a, str> {
|
||||||
|
#[inline]
|
||||||
|
fn from(value: Atom<'a>) -> Self {
|
||||||
|
Cow::Borrowed(value.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Deref for Atom<'a> {
|
impl<'a> Deref for Atom<'a> {
|
||||||
type Target = str;
|
type Target = str;
|
||||||
|
|
||||||
|
|
@ -147,6 +154,17 @@ impl<'a> PartialEq<str> for Atom<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> PartialEq<Atom<'a>> for Cow<'_, str> {
|
||||||
|
fn eq(&self, other: &Atom<'a>) -> bool {
|
||||||
|
self.as_ref() == other.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> PartialEq<&Atom<'a>> for Cow<'_, str> {
|
||||||
|
fn eq(&self, other: &&Atom<'a>) -> bool {
|
||||||
|
self.as_ref() == other.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> hash::Hash for Atom<'a> {
|
impl<'a> hash::Hash for Atom<'a> {
|
||||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||||
self.as_str().hash(hasher);
|
self.as_str().hash(hasher);
|
||||||
|
|
@ -265,6 +283,26 @@ impl From<String> for CompactStr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'s> From<&'s CompactStr> for Cow<'s, str> {
|
||||||
|
fn from(value: &'s CompactStr) -> Self {
|
||||||
|
Self::Borrowed(value.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CompactStr> for Cow<'_, str> {
|
||||||
|
fn from(value: CompactStr) -> Self {
|
||||||
|
value.0.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<Cow<'_, str>> for CompactStr {
|
||||||
|
fn from(value: Cow<'_, str>) -> Self {
|
||||||
|
match value {
|
||||||
|
Cow::Borrowed(s) => CompactStr::new(s),
|
||||||
|
Cow::Owned(s) => CompactStr::from(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for CompactStr {
|
impl Deref for CompactStr {
|
||||||
type Target = str;
|
type Target = str;
|
||||||
|
|
||||||
|
|
@ -309,6 +347,12 @@ impl PartialEq<str> for CompactStr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<CompactStr> for Cow<'_, str> {
|
||||||
|
fn eq(&self, other: &CompactStr) -> bool {
|
||||||
|
self.as_ref() == other.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Index<Span> for CompactStr {
|
impl Index<Span> for CompactStr {
|
||||||
type Output = str;
|
type Output = str;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,12 @@ impl VisitMut<'_> for SpecParser {
|
||||||
options.single_quote = literal.value;
|
options.single_quote = literal.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::NumericLiteral(literal) => match name.as_str() {
|
Expression::NumericLiteral(literal) => match name.as_ref() {
|
||||||
"printWidth" => options.print_width = literal.value as usize,
|
"printWidth" => options.print_width = literal.value as usize,
|
||||||
"tabWidth" => options.tab_width = literal.value as usize,
|
"tabWidth" => options.tab_width = literal.value as usize,
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Expression::StringLiteral(literal) => match name.as_str() {
|
Expression::StringLiteral(literal) => match name.as_ref() {
|
||||||
"trailingComma" => {
|
"trailingComma" => {
|
||||||
options.trailing_comma =
|
options.trailing_comma =
|
||||||
TrailingComma::from_str(literal.value.as_str()).unwrap();
|
TrailingComma::from_str(literal.value.as_str()).unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue