Skip to content

Commit

Permalink
refactor(linter): Add suggested file names for unicorn/filename-case (
Browse files Browse the repository at this point in the history
  • Loading branch information
camchenry committed Oct 13, 2024
1 parent d6a0d2e commit f960e9e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
35 changes: 28 additions & 7 deletions crates/oxc_linter/src/rules/unicorn/filename_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,27 @@ fn join_strings_disjunction(strings: &[String]) -> String {
list
}

fn filename_case_diagnostic(valid_cases: &[&str]) -> OxcDiagnostic {
let case_names = valid_cases.iter().map(|s| format!("{s} case")).collect::<Vec<_>>();
fn filename_case_diagnostic(filename: &str, valid_cases: &[(&str, Case)]) -> OxcDiagnostic {
let case_names = valid_cases.iter().map(|(name, _)| format!("{name} case")).collect::<Vec<_>>();
let message = format!("Filename should be in {}", join_strings_disjunction(&case_names));
OxcDiagnostic::warn(message).with_label(Span::default())

let trimmed_filename = filename.trim_matches('_');
let converted_filenames = valid_cases
.iter()
.map(|(_, case)| {
let converter =
Converter::new().remove_boundaries(&[Boundary::LowerDigit, Boundary::DigitLower]);
// get the leading characters that were trimmed, if any, else empty string
let leading = filename.chars().take_while(|c| c == &'_').collect::<String>();
let trailing = filename.chars().rev().take_while(|c| c == &'_').collect::<String>();
format!("'{leading}{}{trailing}'", converter.to_case(*case).convert(trimmed_filename))
})
.collect::<Vec<_>>();

let help_message =
format!("Rename the file to {}", join_strings_disjunction(&converted_filenames));

OxcDiagnostic::warn(message).with_label(Span::default()).with_help(help_message)
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -122,7 +139,8 @@ impl Rule for FilenameCase {
}

fn run_once<'a>(&self, ctx: &LintContext<'_>) {
let Some(filename) = ctx.file_path().file_stem().and_then(|s| s.to_str()) else {
let file_path = ctx.file_path();
let Some(filename) = file_path.file_stem().and_then(|s| s.to_str()) else {
return;
};

Expand All @@ -144,11 +162,14 @@ impl Rule for FilenameCase {
Converter::new().remove_boundaries(&[Boundary::LowerDigit, Boundary::DigitLower]);
converter.to_case(*case).convert(filename) == filename
}) {
let case_names = cases
let valid_cases = cases
.iter()
.filter_map(|(enabled, _, name)| if *enabled { Some(*name) } else { None })
.filter_map(
|(enabled, case, name)| if *enabled { Some((*name, *case)) } else { None },
)
.collect::<Vec<_>>();
ctx.diagnostic(filename_case_diagnostic(&case_names));
let filename = file_path.file_name().unwrap().to_string_lossy();
ctx.diagnostic(filename_case_diagnostic(&filename, &valid_cases));
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions crates/oxc_linter/src/snapshots/filename_case.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,111 +4,139 @@ source: crates/oxc_linter/src/tester.rs
eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'fooBar.test.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'fooBar.testUtils.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo_bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo_bar.test.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo_bar.test_utils.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo-bar.test.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo-bar.test-utils.js'

eslint-plugin-unicorn(filename-case): Filename should be in pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'FooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'FooBar.test.js'

eslint-plugin-unicorn(filename-case): Filename should be in pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'FooBar.testUtils.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_fooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '___fooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_foo_bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '___foo_bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '___foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_FooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '___FooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case, or pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to 'fooBar.js', or 'FooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case, kebab case, or pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_fooBar.js', '_foo-bar.js', or '_FooBar.js'

eslint-plugin-unicorn(filename-case): Filename should be in snake case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '_foo_bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '[foo-bar].js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '$foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in kebab case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '$foo-bar.js'

eslint-plugin-unicorn(filename-case): Filename should be in camel case, kebab case, or pascal case
╭─[filename_case.tsx:1:1]
╰────
help: Rename the file to '{fooBar}.js', '{foo-bar}.js', or '{fooBar}.js'

0 comments on commit f960e9e

Please sign in to comment.