Skip to content

Commit

Permalink
feat(useNamingConvention): options for custom conventions (#2770)
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos authored May 12, 2024
1 parent 0b68e30 commit 06a587e
Show file tree
Hide file tree
Showing 88 changed files with 3,218 additions and 1,459 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,40 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

#### New features

- [useNamingConvention](https://biomejs.dev/linter/rules/use-naming-convention/) now supports an option to enforce custom conventions ([#1900](https://github.com/biomejs/biome/issues/1900)).

For example, you can enforce the use of a prefix for private class members:

```json
{
"linter": {
"rules": {
"style": {
"useNamingConvention": {
"level": "error",
"options": {
"conventions": [
{
"selector": {
"kind": "classMember",
"modifiers": ["private"]
},
"match": "_(.*)",
"formats": ["camelCase"]
}
]
}
}
}
}
}
}
```

Please, find more details in the [rule documentation](https://biomejs.dev/linter/rules/use-naming-convention/#conventions).

Contributed by @Conaclos

- Add [nursery/useThrowNewError](https://biomejs.dev/linter/rules/use-throw-new-error/).
Contributed by @minht11

Expand Down
30 changes: 30 additions & 0 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ bpaf = { version = "0.9.9", features = ["derive"] }
countme = "3.0.1"
crossbeam = "0.8.4"
dashmap = "5.4.0"
enumflags2 = "0.7.3"
getrandom = "0.2.14"
ignore = "0.4.21"
indexmap = { version = "2.2.6", features = ["serde"] }
Expand All @@ -170,12 +171,12 @@ quote = "1.0.36"
rayon = "1.8.1"
regex = "1.10.4"
rustc-hash = "1.1.0"
schemars = "0.8.17"
schemars = { version = "0.8.17", features = ["indexmap2", "smallvec"] }
serde = { version = "1.0.200", features = ["derive"] }
serde_json = "1.0.116"
similar = "2.5.0"
slotmap = "1.0.7"
smallvec = { version = "1.10.0", features = ["union", "const_new"] }
smallvec = { version = "1.10.0", features = ["union", "const_new", "serde"] }
syn = "1.0.109"
termcolor = "1.4.1"
tokio = "1.36.0"
Expand Down
7 changes: 4 additions & 3 deletions crates/biome_cli/src/execute/migrate/eslint_typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,18 @@ impl From<NamingConventionOptions> for use_naming_convention::NamingConventionOp
Some(NamingConventionCase::StrictCamel | NamingConventionCase::StrictPascal)
),
require_ascii: false,
conventions: Vec::new(),
enum_member_case: enum_member_format
.and_then(|format| {
match format {
NamingConventionCase::Camel | NamingConventionCase::StrictCamel => {
Some(use_naming_convention::EnumMemberCase::Camel)
Some(use_naming_convention::Format::Camel)
}
NamingConventionCase::Pascal | NamingConventionCase::StrictPascal => {
Some(use_naming_convention::EnumMemberCase::Pascal)
Some(use_naming_convention::Format::Pascal)
}
NamingConventionCase::Upper => {
Some(use_naming_convention::EnumMemberCase::Constant)
Some(use_naming_convention::Format::Constant)
}
// Biome doesn't support `snake_case` for enum member
NamingConventionCase::Snake => None,
Expand Down
4 changes: 3 additions & 1 deletion crates/biome_deserialize/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ bitflags = { workspace = true }
indexmap = { workspace = true, features = ["serde"] }
schemars = { workspace = true, optional = true }
serde = { workspace = true }
smallvec = { workspace = true, optional = true }

[features]
schema = ["schemars", "schemars/indexmap"]
schema = ["schemars", "schemars/indexmap"]
smallvec = ["dep:smallvec"]

[lints]
workspace = true
30 changes: 30 additions & 0 deletions crates/biome_deserialize/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::{
num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize},
ops::Deref,
path::PathBuf,
u8,
};

/// Type that allows deserializing a string without heap-allocation.
Expand Down Expand Up @@ -531,6 +532,35 @@ impl<T: Deserializable> Deserializable for Vec<T> {
}
}

#[cfg(feature = "smallvec")]
impl<T: Deserializable, const L: usize> Deserializable for smallvec::SmallVec<[T; L]> {
fn deserialize(
value: &impl DeserializableValue,
name: &str,
diagnostics: &mut Vec<DeserializationDiagnostic>,
) -> Option<Self> {
struct Visitor<T, const L: usize>(PhantomData<T>);
impl<T: Deserializable, const L: usize> DeserializationVisitor for Visitor<T, L> {
type Output = smallvec::SmallVec<[T; L]>;
const EXPECTED_TYPE: VisitableType = VisitableType::ARRAY;
fn visit_array(
self,
values: impl Iterator<Item = Option<impl DeserializableValue>>,
_range: TextRange,
_name: &str,
diagnostics: &mut Vec<DeserializationDiagnostic>,
) -> Option<Self::Output> {
Some(
values
.filter_map(|value| Deserializable::deserialize(&value?, "", diagnostics))
.collect(),
)
}
}
value.deserialize(Visitor(PhantomData), name, diagnostics)
}
}

impl<T: Deserializable + Eq + Hash, S: BuildHasher + Default> Deserializable for HashSet<T, S> {
fn deserialize(
value: &impl DeserializableValue,
Expand Down
5 changes: 4 additions & 1 deletion crates/biome_js_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ biome_analyze = { workspace = true }
biome_aria = { workspace = true }
biome_console = { workspace = true }
biome_control_flow = { workspace = true }
biome_deserialize = { workspace = true }
biome_deserialize = { workspace = true, features = ["smallvec"] }
biome_deserialize_macros = { workspace = true }
biome_diagnostics = { workspace = true }
biome_js_factory = { workspace = true }
Expand All @@ -26,8 +26,11 @@ biome_rowan = { workspace = true }
biome_string_case = { workspace = true }
biome_suppression = { workspace = true }
biome_unicode_table = { workspace = true }
bitflags = { workspace = true }
enumflags2 = { workspace = true }
lazy_static = { workspace = true }
natord = "1.0.9"
regex = { workspace = true }
roaring = "0.10.4"
rustc-hash = { workspace = true }
schemars = { workspace = true, optional = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ impl Rule for NoUnusedVariables {
let new_name = format!("_{}", name_trimmed);

let model = ctx.model();
mutation.rename_node_declaration(model, binding.clone(), &new_name);
mutation.rename_node_declaration(model, binding, &new_name);

Some(JsRuleAction {
mutation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use biome_analyze::{
use biome_console::markup;
use biome_deserialize_macros::Deserializable;
use biome_rowan::TextRange;
use biome_string_case::Case;
use biome_string_case::{Case, Cases};
use rustc_hash::FxHashSet;
use serde::{Deserialize, Serialize};
use std::{hash::Hash, str::FromStr};
Expand Down Expand Up @@ -129,10 +129,8 @@ impl Rule for UseFilenamingConvention {
if !allowed_cases.is_empty() {
let trimmed_name = name.trim_matches('_');
let case = Case::identify(trimmed_name, options.strict_case);
for allowed_case in allowed_cases {
if case.is_compatible_with(allowed_case) {
return None;
}
if allowed_cases.contains(case) {
return None;
}
}
if options.filename_cases.0.contains(&FilenameCase::Export) {
Expand Down Expand Up @@ -167,7 +165,7 @@ impl Rule for UseFilenamingConvention {
},
FileNamingConventionState::Filename => {
let allowed_cases = options.filename_cases.cases();
let allowed_case_names = allowed_cases.iter().map(|style| style.to_string());
let allowed_case_names = allowed_cases.into_iter().map(|case| case.to_string());
let allowed_case_names = if options.filename_cases.0.contains(&FilenameCase::Export) {
allowed_case_names
.chain(["equal to the name of an export".to_string()])
Expand Down Expand Up @@ -210,7 +208,7 @@ impl Rule for UseFilenamingConvention {
}
}
let suggested_filenames = allowed_cases
.iter()
.into_iter()
.map(|case| file_name.replacen(trimmed_name, &case.convert(trimmed_name), 1))
// Deduplicate suggestions
.collect::<FxHashSet<_>>()
Expand Down Expand Up @@ -300,11 +298,11 @@ impl Default for FilenamingConventionOptions {
pub struct FilenameCases(FxHashSet<FilenameCase>);

impl FilenameCases {
fn cases(&self) -> SmallVec<[Case; 3]> {
fn cases(&self) -> Cases {
self.0
.iter()
.filter_map(|case| Case::try_from(*case).ok())
.collect()
.fold(Cases::empty(), |acc, case| acc | case)
}
}

Expand Down
Loading

0 comments on commit 06a587e

Please sign in to comment.