Skip to content

Commit

Permalink
perf(js_analyze): use Box<str>/Box<[_]> to reduce memory usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed Oct 8, 2024
1 parent d7cc01f commit a08b0bf
Show file tree
Hide file tree
Showing 65 changed files with 364 additions and 300 deletions.
2 changes: 1 addition & 1 deletion crates/biome_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ where
suppression
.suppressed_instances
.iter()
.any(|(filter, v)| *filter == entry.rule && v == value)
.any(|(filter, v)| *filter == entry.rule && v == value.as_ref())
})
});

Expand Down
2 changes: 1 addition & 1 deletion crates/biome_analyze/src/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub struct SignalEntry<'phase, L: Language> {
/// Unique identifier for the rule that emitted this signal
pub rule: RuleKey,
/// Optional rule instances being suppressed
pub instances: Vec<String>,
pub instances: Box<[Box<str>]>,
/// Text range in the document this signal covers
pub text_range: TextRange,
}
Expand Down
4 changes: 2 additions & 2 deletions crates/biome_analyze/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,8 +800,8 @@ pub trait Rule: RuleMeta + Sized {
/// *Note: For `noUnusedVariables` the above may not seem very useful (and
/// indeed it's not implemented), but for rules such as
/// `useExhaustiveDependencies` this is actually desirable.*
fn instances_for_signal(_signal: &Self::State) -> Vec<String> {
Vec::new()
fn instances_for_signal(_signal: &Self::State) -> Box<[Box<str>]> {
Vec::new().into_boxed_slice()
}

/// Used by the analyzer to associate a range of source text to a signal in
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_cli/src/execute/migrate/eslint_eslint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl Deserializable for Rules {
#[derive(Debug, Default, Deserializable)]
pub struct NoConsoleOptions {
/// Allowed calls on the console object.
pub allow: Vec<String>,
pub allow: Box<[Box<str>]>,
}
impl From<NoConsoleOptions> for biome_js_analyze::lint::suspicious::no_console::NoConsoleOptions {
fn from(val: NoConsoleOptions) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_cli/src/execute/migrate/eslint_jsxa11y.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use biome_js_analyze::lint::a11y::use_valid_aria_role;

#[derive(Debug, Default, Deserializable)]
pub(crate) struct AriaRoleOptions {
allowed_invalid_roles: Vec<String>,
allowed_invalid_roles: Box<[Box<str>]>,
#[deserializable(rename = "ignoreNonDOM")]
ignore_non_dom: bool,
}
Expand Down
7 changes: 5 additions & 2 deletions crates/biome_cli/src/execute/migrate/eslint_to_biome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,16 @@ fn migrate_eslint_rule(
eslint_eslint::Rule::NoRestrictedGlobals(conf) => {
if migrate_eslint_any_rule(rules, &name, conf.severity(), opts, results) {
let severity = conf.severity();
let globals = conf.into_vec().into_iter().map(|g| g.into_name());
let globals = conf
.into_vec()
.into_iter()
.map(|g| g.into_name().into_boxed_str());
let group = rules.style.get_or_insert_with(Default::default);
group.no_restricted_globals = Some(biome_config::RuleConfiguration::WithOptions(
biome_config::RuleWithOptions {
level: severity.into(),
options: Box::new(no_restricted_globals::RestrictedGlobalsOptions {
denied_globals: globals.collect(),
denied_globals: globals.collect::<Vec<_>>().into_boxed_slice(),
}),
},
));
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_cli/src/execute/migrate/eslint_typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl From<NamingConventionOptions> for use_naming_convention::NamingConventionOp
use_naming_convention::NamingConventionOptions {
strict_case: false,
require_ascii: false,
conventions,
conventions: conventions.into_boxed_slice(),
enum_member_case: use_naming_convention::Format::default(),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ declare_lint_rule! {
impl Rule for NoInvalidPositionAtImportRule {
type Query = Ast<CssRuleList>;
type State = TextRange;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Vec<Self::State> {
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
let mut is_invalid_position = false;
let mut invalid_import_list = Vec::new();
Expand Down Expand Up @@ -73,7 +73,7 @@ impl Rule for NoInvalidPositionAtImportRule {
is_invalid_position = true;
}
}
invalid_import_list
invalid_import_list.into_boxed_slice()
}

fn diagnostic(_: &RuleContext<Self>, state: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fn find_descending_selector(
impl Rule for NoDescendingSpecificity {
type Query = Semantic<CssRoot>;
type State = DescendingSelector;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
Expand All @@ -180,8 +180,7 @@ impl Rule for NoDescendingSpecificity {
&mut descending_selectors,
);
}

descending_selectors
descending_selectors.into_boxed_slice()
}

fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ declare_lint_rule! {
impl Rule for NoIrregularWhitespace {
type Query = Ast<AnyCssRule>;
type State = TextRange;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
get_irregular_whitespace(node)
get_irregular_whitespace(node).into_boxed_slice()
}

fn diagnostic(_: &RuleContext<Self>, range: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
20 changes: 20 additions & 0 deletions crates/biome_deserialize/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,16 @@ impl Deserializable for String {
}
}

impl Deserializable for Box<str> {
fn deserialize(
value: &impl DeserializableValue,
name: &str,
diagnostics: &mut Vec<DeserializationDiagnostic>,
) -> Option<Self> {
String::deserialize(value, name, diagnostics).map(|s| s.into_boxed_str())
}
}

impl Deserializable for PathBuf {
fn deserialize(
value: &impl DeserializableValue,
Expand Down Expand Up @@ -556,6 +566,16 @@ impl<T: Deserializable> Deserializable for Vec<T> {
}
}

impl<T: Deserializable> Deserializable for Box<[T]> {
fn deserialize(
value: &impl DeserializableValue,
name: &str,
diagnostics: &mut Vec<DeserializationDiagnostic>,
) -> Option<Self> {
Deserializable::deserialize(value, name, diagnostics).map(Vec::into_boxed_slice)
}
}

#[cfg(feature = "smallvec")]
impl<T: Deserializable, const L: usize> Deserializable for smallvec::SmallVec<[T; L]> {
fn deserialize(
Expand Down
12 changes: 12 additions & 0 deletions crates/biome_deserialize/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@ impl IsEmpty for String {
}
}

impl IsEmpty for Box<str> {
fn is_empty(&self) -> bool {
str::is_empty(self)
}
}

impl<T> IsEmpty for Vec<T> {
fn is_empty(&self) -> bool {
Vec::is_empty(self)
}
}

impl<T> IsEmpty for Box<[T]> {
fn is_empty(&self) -> bool {
<[_]>::is_empty(self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ declare_lint_rule! {
impl Rule for NoDuplicatedFields {
type Query = Ast<AnyGraphqlOperationDefinition>;
type State = DuplicatedField;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Vec<Self::State> {
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let operation = ctx.query();
let mut duplicated_fields = vec![];
match operation {
Expand All @@ -68,8 +68,7 @@ impl Rule for NoDuplicatedFields {
duplicated_fields.extend(check_duplicated_selection_fields(selection_set))
}
};

duplicated_fields
duplicated_fields.into_boxed_slice()
}

fn diagnostic(_ctx: &RuleContext<Self>, state: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
4 changes: 2 additions & 2 deletions crates/biome_js_analyze/src/assists/source/sort_jsx_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ declare_source_rule! {
impl Rule for SortJsxProps {
type Query = Ast<JsxAttributeList>;
type State = PropGroup;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
Expand All @@ -72,7 +72,7 @@ impl Rule for SortJsxProps {
}
}
prop_groups.push(current_prop_group);
prop_groups
prop_groups.into_boxed_slice()
}

fn action(ctx: &RuleContext<Self>, state: &Self::State) -> Option<JsRuleAction> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ impl Rule for NoLabelWithoutControl {
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct NoLabelWithoutControlOptions {
/// Array of component names that should be considered the same as an `input` element.
pub input_components: Vec<String>,
pub input_components: Box<[Box<str>]>,
/// Array of attributes that should be treated as the `label` accessible text content.
pub label_attributes: Vec<String>,
pub label_attributes: Box<[Box<str>]>,
/// Array of component names that should be considered the same as a `label` element.
pub label_components: Vec<String>,
pub label_components: Box<[Box<str>]>,
}

impl NoLabelWithoutControlOptions {
Expand All @@ -175,7 +175,7 @@ impl NoLabelWithoutControlOptions {
&& !self
.label_attributes
.iter()
.any(|name| name == attribute_name)
.any(|name| name.as_ref() == attribute_name)
{
return false;
}
Expand Down Expand Up @@ -245,7 +245,7 @@ impl NoLabelWithoutControlOptions {
|| self
.input_components
.iter()
.any(|name| name == element_name)
.any(|name| name.as_ref() == element_name)
{
return true;
}
Expand All @@ -260,7 +260,7 @@ impl NoLabelWithoutControlOptions {
fn has_element_name(&self, element_name: &str) -> bool {
self.label_components
.iter()
.any(|label_component_name| label_component_name == element_name)
.any(|label_component_name| label_component_name.as_ref() == element_name)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ declare_lint_rule! {

#[derive(Default, Debug)]
pub struct UseAriaPropsForRoleState {
missing_aria_props: Vec<String>,
missing_aria_props: Box<[String]>,
attribute: Option<(JsxAttribute, String)>,
}

Expand Down Expand Up @@ -121,7 +121,7 @@ impl Rule for UseAriaPropsForRole {
if !missing_aria_props.is_empty() {
return Some(UseAriaPropsForRoleState {
attribute: Some((role_attribute, name.text().to_string())),
missing_aria_props,
missing_aria_props: missing_aria_props.into_boxed_slice(),
});
}
}
Expand Down
6 changes: 3 additions & 3 deletions crates/biome_js_analyze/src/lint/a11y/use_valid_aria_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ declare_lint_rule! {
impl Rule for UseValidAriaProps {
type Query = Aria<AnyJsxElement>;
type State = JsxAttribute;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
Expand All @@ -64,11 +64,11 @@ impl Rule for UseValidAriaProps {
}
})
.collect();

attributes
} else {
vec![]
Vec::new()
}
.into_boxed_slice()
}

fn diagnostic(ctx: &RuleContext<Self>, attribute: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
7 changes: 5 additions & 2 deletions crates/biome_js_analyze/src/lint/a11y/use_valid_aria_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ declare_lint_rule! {
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct ValidAriaRoleOptions {
pub allow_invalid_roles: Vec<String>,
pub allow_invalid_roles: Box<[Box<str>]>,
pub ignore_non_dom: bool,
}

Expand Down Expand Up @@ -107,7 +107,10 @@ impl Rule for UseValidAriaRole {

let is_valid = role_attribute_value.all(|val| {
let role_data = aria_roles.get_role(val);
allowed_invalid_roles.contains(&val.to_string()) || role_data.is_some()
allowed_invalid_roles
.iter()
.any(|role| role.as_ref() == val)
|| role_data.is_some()
});

if is_valid {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ declare_lint_rule! {
impl Rule for NoUselessSwitchCase {
type Query = Ast<JsDefaultClause>;
type State = JsCaseClause;
type Signals = Vec<Self::State>;
type Signals = Box<[Self::State]>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
Expand Down Expand Up @@ -107,10 +107,11 @@ impl Rule for NoUselessSwitchCase {
.filter_map(JsCaseClause::cast)
.find(|case| !case.consequent().is_empty()),
)
.collect()
.collect::<Vec<_>>()
} else {
it.collect()
it.collect::<Vec<_>>()
}
.into_boxed_slice()
}

fn diagnostic(ctx: &RuleContext<Self>, useless_case: &Self::State) -> Option<RuleDiagnostic> {
Expand Down
Loading

0 comments on commit a08b0bf

Please sign in to comment.