Skip to content

Commit

Permalink
feat(linter): implement @typescript-eslint/no-duplicate-enum-values (#…
Browse files Browse the repository at this point in the history
…726)

implement
[@typescript-eslint/no-duplicate-enum-values](https://typescript-eslint.io/rules/no-duplicate-enum-values)
Related issue: #503.
  • Loading branch information
Thiry1 authored Aug 12, 2023
1 parent 37efbd7 commit 4f5e4c1
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod typescript {
pub mod adjacent_overload_signatures;
pub mod consistent_type_exports;
pub mod isolated_declaration;
pub mod no_duplicate_enum_values;
pub mod no_empty_interface;
pub mod no_extra_non_null_assertion;
pub mod no_misused_new;
Expand Down Expand Up @@ -161,6 +162,7 @@ oxc_macros::declare_all_lint_rules! {
typescript::adjacent_overload_signatures,
typescript::consistent_type_exports,
typescript::isolated_declaration,
typescript::no_duplicate_enum_values,
typescript::no_empty_interface,
typescript::no_extra_non_null_assertion,
typescript::no_non_null_asserted_optional_chain,
Expand Down
203 changes: 203 additions & 0 deletions crates/oxc_linter/src/rules/typescript/no_duplicate_enum_values.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
use oxc_ast::ast::Expression;
use oxc_ast::AstKind;
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::{Atom, Span};
use rustc_hash::FxHashSet;

use crate::{context::LintContext, rule::Rule, AstNode};

#[derive(Debug, Error, Diagnostic)]
#[error("Disallow duplicate enum member values")]
#[diagnostic(severity(warning))]
struct NoDuplicateEnumValuesDiagnostic(#[label] pub Span);

#[derive(Debug, Default, Clone)]
pub struct NoDuplicateEnumValues;

declare_oxc_lint!(
/// ### What it does
/// Disallow duplicate enum member values.
///
/// ### Why is this bad?
/// Although TypeScript supports duplicate enum member values, people usually expect members to have unique values within the same enum. Duplicate values can lead to bugs that are hard to track down.
///
/// ### Example
/// ```javascript
/// enum E {
// A = 0,
// B = 0,
// }
/// ```
NoDuplicateEnumValues,
correctness
);

impl Rule for NoDuplicateEnumValues {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::TSEnumBody(enum_body) = node.kind() else { return };
let mut seen_number_values: Vec<f64> = Vec::new();
let mut seen_string_values: FxHashSet<&Atom> = FxHashSet::default();
for enum_member in &enum_body.members {
let Some(initializer) = &enum_member.initializer else { continue };
match initializer {
Expression::NumberLiteral(num) => {
if seen_number_values.contains(&num.value) {
ctx.diagnostic(NoDuplicateEnumValuesDiagnostic(num.span));
}
seen_number_values.push(num.value);
}
Expression::StringLiteral(str) => {
if seen_string_values.contains(&str.value) {
ctx.diagnostic(NoDuplicateEnumValuesDiagnostic(str.span));
}
seen_string_values.insert(&str.value);
}
_ => {}
}
}
}
}

#[allow(clippy::too_many_lines)]
#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
(
"
enum E {
A,
B,
}
",
None,
),
(
"
enum E {
A = 1,
B,
}
",
None,
),
(
"
enum E {
A = 1,
B = 2,
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'B',
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'B',
C,
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'B',
C = 2,
D = 1 + 1,
}
",
None,
),
(
"
enum E {
A = 3,
B = 2,
C,
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'B',
C = 2,
D = foo(),
}
",
None,
),
(
"
enum E {
A = '',
B = 0,
}
",
None,
),
(
"
enum E {
A = 0,
B = -0,
C = NaN,
}
",
None,
),
];

let fail = vec![
(
"
enum E {
A = 1,
B = 1,
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'A',
}
",
None,
),
(
"
enum E {
A = 'A',
B = 'A',
C = 1,
D = 1,
}
",
None,
),
];

Tester::new(NoDuplicateEnumValues::NAME, pass, fail).test_and_snapshot();
}
38 changes: 38 additions & 0 deletions crates/oxc_linter/src/snapshots/no_duplicate_enum_values.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
source: crates/oxc_linter/src/tester.rs
assertion_line: 80
expression: no_duplicate_enum_values
---
Disallow duplicate enum member values
╭─[no_duplicate_enum_values.tsx:3:1]
3 │ A = 1,
4 │ B = 1,
· ─
5 │ }
╰────

Disallow duplicate enum member values
╭─[no_duplicate_enum_values.tsx:3:1]
3 │ A = 'A',
4 │ B = 'A',
· ───
5 │ }
╰────

Disallow duplicate enum member values
╭─[no_duplicate_enum_values.tsx:3:1]
3 │ A = 'A',
4 │ B = 'A',
· ───
5 │ C = 1,
╰────

⚠ Disallow duplicate enum member values
╭─[no_duplicate_enum_values.tsx:5:1]
5 │ C = 1,
6 │ D = 1,
· ─
7 │ }
╰────


0 comments on commit 4f5e4c1

Please sign in to comment.