Skip to content

Commit

Permalink
feat(linter): implement noTemplateCurlyInString (#4069)
Browse files Browse the repository at this point in the history
  • Loading branch information
fireairforce authored Sep 25, 2024
1 parent 73ae493 commit cc4c867
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 36 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

### Linter

#### New features

- Add [noTemplateCurlyInString](https://biomejs.dev/linter/rules/no-template-curly-in-string/). Contributed by @fireairforce
- Add [NoOctalEscape](https://biomejs.dev/linter/rules/no-octal-escape/). Contributed by @fireairforce

#### Bug fixes

- [noUselessStringConcat](https://biomejs.dev/linter/rules/no-useless-string-concat/) no longer panics when it encounters malformed code. Contributed by @Conaclos
Expand Down Expand Up @@ -72,6 +77,8 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

- [useSemanticElements](https://biomejs.dev/linter/rules/use-semantic-elements/) now ignores `alert` and `alertdialog` roles ([#3858](https://github.com/biomejs/biome/issues/3858)). Contributed by @Conaclos

- [noUselessFragments](https://biomejs.dev/linter/rules/no-useless-fragments/) don't create invaild JSX code when Fragments children contains JSX Expression and in a LogicalExpression. Contributed by @fireairforce

### Parser

## v1.9.2 (2024-09-19)
Expand Down
10 changes: 10 additions & 0 deletions crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 56 additions & 36 deletions crates/biome_configuration/src/analyzer/linter/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3332,6 +3332,10 @@ pub struct Nursery {
#[doc = "Enforce the use of String.slice() over String.substr() and String.substring()."]
#[serde(skip_serializing_if = "Option::is_none")]
pub no_substr: Option<RuleFixConfiguration<biome_js_analyze::options::NoSubstr>>,
#[doc = "Disallow template literal placeholder syntax in regular strings."]
#[serde(skip_serializing_if = "Option::is_none")]
pub no_template_curly_in_string:
Option<RuleConfiguration<biome_js_analyze::options::NoTemplateCurlyInString>>,
#[doc = "Disallow unknown pseudo-class selectors."]
#[serde(skip_serializing_if = "Option::is_none")]
pub no_unknown_pseudo_class:
Expand Down Expand Up @@ -3429,6 +3433,7 @@ impl Nursery {
"noSecrets",
"noStaticElementInteractions",
"noSubstr",
"noTemplateCurlyInString",
"noUnknownPseudoClass",
"noUnknownPseudoElement",
"noUselessEscapeInRegex",
Expand Down Expand Up @@ -3464,13 +3469,13 @@ impl Nursery {
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]),
];
const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]),
Expand Down Expand Up @@ -3506,6 +3511,7 @@ impl Nursery {
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]),
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]),
];
#[doc = r" Retrieves the recommended rules"]
pub(crate) fn is_recommended_true(&self) -> bool {
Expand Down Expand Up @@ -3607,86 +3613,91 @@ impl Nursery {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]));
}
}
if let Some(rule) = self.no_unknown_pseudo_class.as_ref() {
if let Some(rule) = self.no_template_curly_in_string.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]));
}
}
if let Some(rule) = self.no_unknown_pseudo_element.as_ref() {
if let Some(rule) = self.no_unknown_pseudo_class.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]));
}
}
if let Some(rule) = self.no_useless_escape_in_regex.as_ref() {
if let Some(rule) = self.no_unknown_pseudo_element.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]));
}
}
if let Some(rule) = self.no_value_at_rule.as_ref() {
if let Some(rule) = self.no_useless_escape_in_regex.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]));
}
}
if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() {
if let Some(rule) = self.no_value_at_rule.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]));
}
}
if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() {
if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]));
}
}
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]));
}
}
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]));
}
}
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]));
}
}
if let Some(rule) = self.use_deprecated_reason.as_ref() {
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]));
}
}
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
if let Some(rule) = self.use_deprecated_reason.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]));
}
}
if let Some(rule) = self.use_import_restrictions.as_ref() {
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]));
}
}
if let Some(rule) = self.use_sorted_classes.as_ref() {
if let Some(rule) = self.use_import_restrictions.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]));
}
}
if let Some(rule) = self.use_strict_mode.as_ref() {
if let Some(rule) = self.use_sorted_classes.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]));
}
}
if let Some(rule) = self.use_trim_start_end.as_ref() {
if let Some(rule) = self.use_strict_mode.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]));
}
}
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
if let Some(rule) = self.use_trim_start_end.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]));
}
}
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
if rule.is_enabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]));
}
}
index_set
}
pub(crate) fn get_disabled_rules(&self) -> FxHashSet<RuleFilter<'static>> {
Expand Down Expand Up @@ -3776,86 +3787,91 @@ impl Nursery {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]));
}
}
if let Some(rule) = self.no_unknown_pseudo_class.as_ref() {
if let Some(rule) = self.no_template_curly_in_string.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]));
}
}
if let Some(rule) = self.no_unknown_pseudo_element.as_ref() {
if let Some(rule) = self.no_unknown_pseudo_class.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]));
}
}
if let Some(rule) = self.no_useless_escape_in_regex.as_ref() {
if let Some(rule) = self.no_unknown_pseudo_element.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]));
}
}
if let Some(rule) = self.no_value_at_rule.as_ref() {
if let Some(rule) = self.no_useless_escape_in_regex.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]));
}
}
if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() {
if let Some(rule) = self.no_value_at_rule.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]));
}
}
if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() {
if let Some(rule) = self.use_adjacent_overload_signatures.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]));
}
}
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
if let Some(rule) = self.use_aria_props_supported_by_role.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]));
}
}
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]));
}
}
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]));
}
}
if let Some(rule) = self.use_deprecated_reason.as_ref() {
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]));
}
}
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
if let Some(rule) = self.use_deprecated_reason.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]));
}
}
if let Some(rule) = self.use_import_restrictions.as_ref() {
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]));
}
}
if let Some(rule) = self.use_sorted_classes.as_ref() {
if let Some(rule) = self.use_import_restrictions.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]));
}
}
if let Some(rule) = self.use_strict_mode.as_ref() {
if let Some(rule) = self.use_sorted_classes.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]));
}
}
if let Some(rule) = self.use_trim_start_end.as_ref() {
if let Some(rule) = self.use_strict_mode.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]));
}
}
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
if let Some(rule) = self.use_trim_start_end.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]));
}
}
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
if rule.is_disabled() {
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]));
}
}
index_set
}
#[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"]
Expand Down Expand Up @@ -3960,6 +3976,10 @@ impl Nursery {
.no_substr
.as_ref()
.map(|conf| (conf.level(), conf.get_options())),
"noTemplateCurlyInString" => self
.no_template_curly_in_string
.as_ref()
.map(|conf| (conf.level(), conf.get_options())),
"noUnknownPseudoClass" => self
.no_unknown_pseudo_class
.as_ref()
Expand Down
1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ define_categories! {
"lint/nursery/noShorthandPropertyOverrides": "https://biomejs.dev/linter/rules/no-shorthand-property-overrides",
"lint/nursery/noStaticElementInteractions": "https://biomejs.dev/linter/rules/no-static-element-interactions",
"lint/nursery/noSubstr": "https://biomejs.dev/linter/rules/no-substr",
"lint/nursery/noTemplateCurlyInString": "https://biomejs.dev/linter/rules/no-template-curly-in-string",
"lint/nursery/noUndeclaredDependencies": "https://biomejs.dev/linter/rules/no-undeclared-dependencies",
"lint/nursery/noUnknownFunction": "https://biomejs.dev/linter/rules/no-unknown-function",
"lint/nursery/noUnknownMediaFeatureName": "https://biomejs.dev/linter/rules/no-unknown-media-feature-name",
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_js_analyze/src/lint/nursery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod no_restricted_types;
pub mod no_secrets;
pub mod no_static_element_interactions;
pub mod no_substr;
pub mod no_template_curly_in_string;
pub mod no_useless_escape_in_regex;
pub mod use_adjacent_overload_signatures;
pub mod use_aria_props_supported_by_role;
Expand Down Expand Up @@ -47,6 +48,7 @@ declare_lint_group! {
self :: no_secrets :: NoSecrets ,
self :: no_static_element_interactions :: NoStaticElementInteractions ,
self :: no_substr :: NoSubstr ,
self :: no_template_curly_in_string :: NoTemplateCurlyInString ,
self :: no_useless_escape_in_regex :: NoUselessEscapeInRegex ,
self :: use_adjacent_overload_signatures :: UseAdjacentOverloadSignatures ,
self :: use_aria_props_supported_by_role :: UseAriaPropsSupportedByRole ,
Expand Down
Loading

0 comments on commit cc4c867

Please sign in to comment.