From 675b8ed8133b55f4b8f27b7f004fd8987f6059f3 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Sun, 30 Jul 2023 12:21:08 +0200 Subject: [PATCH] refactor(rome_js_analyze): improve `useEnumInitializers` (#4733) --- CHANGELOG.md | 14 ++ .../analyzers/style/use_enum_initializers.rs | 177 +++++++++------ .../style/useEnumInitializers/invalid.ts | 7 + .../style/useEnumInitializers/invalid.ts.snap | 212 +++++++++++------- .../specs/style/useEnumInitializers/valid.ts | 12 +- .../style/useEnumInitializers/valid.ts.snap | 12 +- .../pages/lint/rules/useEnumInitializers.md | 58 +++-- 7 files changed, 332 insertions(+), 160 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3d0f585ffa..1089099f296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -201,6 +201,20 @@ if no error diagnostics are emitted. - Fix [`noDuplicateCase`](https://docs.rome.tools/lint/rules/noDuplicateCase/) rule that erroneously reported as equals the strings literals `"'"` and `'"'` [#4706](https://github.com/rome/tools/issues/4706). +- Improve [`useEnumInitializers`](https://docs.rome.tools/lint/rules/useEnumInitializers/) + + The rule now reports all uninitialized members of an enum in a single diagnostic. + + Moreover, ambient enum declarations are now ignored. + This avoids reporting ambient enum declarations in _TypeScript_ declaration files. + + ```ts + declare enum Weather { + Rainy, + Sunny, + } + ``` + - Relax [`noBannedTypes`](https://docs.rome.tools/lint/rules/nobannedtypes/) and improve documentation The rule no longer reports a user type that reuses a banned type name. diff --git a/crates/rome_js_analyze/src/analyzers/style/use_enum_initializers.rs b/crates/rome_js_analyze/src/analyzers/style/use_enum_initializers.rs index a01ab2efdc5..36c0ff6b791 100644 --- a/crates/rome_js_analyze/src/analyzers/style/use_enum_initializers.rs +++ b/crates/rome_js_analyze/src/analyzers/style/use_enum_initializers.rs @@ -4,15 +4,20 @@ use rome_analyze::{declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic}; use rome_console::markup; use rome_diagnostics::Applicability; use rome_js_factory::make; -use rome_js_syntax::{AnyJsExpression, AnyJsLiteralExpression, JsSyntaxKind, TsEnumMember}; -use rome_rowan::{AstNode, BatchMutationExt, Direction}; +use rome_js_syntax::{ + AnyJsExpression, AnyJsLiteralExpression, JsSyntaxKind, TsDeclareStatement, TsEnumDeclaration, + TsExportDeclareClause, +}; +use rome_rowan::{AstNode, BatchMutationExt}; declare_rule! { /// Require that each enum member value be explicitly initialized. /// - /// TypeScript enums are a practical way to organize semantically related constant values. Members of enums that don't have explicit values are by default given sequentially increasing numbers. + /// _TypeScript_ enums are a practical way to organize semantically related constant values. + /// Members of enums that don't have explicit values are by default given sequentially increasing numbers. /// - /// When the value of enum members are important, allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + /// When the value of enum members are important, + /// allowing implicit values for enum members can cause bugs if enum declarations are modified over time. /// /// Source: https://typescript-eslint.io/rules/prefer-enum-initializers /// @@ -58,6 +63,12 @@ declare_rule! { /// } /// ``` /// + /// ```ts + /// declare enum Weather { + /// Rainy, + /// Sunny, + /// } + /// ``` pub(crate) UseEnumInitializers { version: "11.0.0", name: "useEnumInitializers", @@ -66,92 +77,126 @@ declare_rule! { } impl Rule for UseEnumInitializers { - type Query = Ast; + // We apply the rule on an entire enum declaration to avoid reporting + // a diagnostic for every enum members without initializers. + type Query = Ast; type State = (); type Signals = Option; type Options = (); fn run(ctx: &RuleContext) -> Self::Signals { - let enum_member = ctx.query(); - enum_member.initializer().is_none().then_some(()) + let enum_declaration = ctx.query(); + if enum_declaration.parent::().is_some() + || enum_declaration.parent::().is_some() + { + // In ambient declarations, enum members without initializers are opaque types. + // They generally represent an enum with complex initializers. + return None; + } + for enum_member in enum_declaration.members() { + let enum_member = enum_member.ok()?; + if enum_member.initializer().is_none() { + return Some(()); + } + } + None } fn diagnostic(ctx: &RuleContext, _: &Self::State) -> Option { - let enum_member = ctx.query(); - Some(RuleDiagnostic::new( + let enum_declaration = ctx.query(); + let mut diagnostic = RuleDiagnostic::new( rule_category!(), - enum_member.range(), + enum_declaration.id().ok()?.range(), markup! { - "The ""enum member"" should be initialized." + "This ""enum declaration"" contains members that are implicitly initialized." }, - ).note( - "Allowing implicit values for enum members can cause bugs if enum declarations are modified over time." + ); + for enum_member in enum_declaration.members() { + let enum_member = enum_member.ok()?; + if enum_member.initializer().is_none() { + diagnostic = diagnostic.detail(enum_member.range(), markup! { + "This ""enum member"" should be explicitly initialized." + }); + } + } + Some(diagnostic.note( + "Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time." )) } fn action(ctx: &RuleContext, _: &Self::State) -> Option { - let enum_member = ctx.query(); - let prev_enum_members = enum_member - .syntax() - .siblings(Direction::Prev) - .skip(1) // consume enum_member - .filter_map(TsEnumMember::cast); - let mut count = 0; - let mut prev_enum_member_info = None; - for prev_enum_member in prev_enum_members { - count += 1; - if let Some(initializer) = prev_enum_member.initializer() { - prev_enum_member_info = Some((initializer, prev_enum_member.name().ok()?)); - break; - } - } - let expr = if let Some((prev_initializer, prev_name)) = prev_enum_member_info { - let expr = prev_initializer.expression().ok()?; - let expr = expr.as_any_js_literal_expression()?; - match expr { - AnyJsLiteralExpression::JsNumberLiteralExpression(expr) => { - Some(AnyJsLiteralExpression::JsNumberLiteralExpression( - make::js_number_literal_expression(make::js_number_literal( - expr.as_number()? + f64::from(count), - )), - )) + let enum_declaration = ctx.query(); + let mut mutation = ctx.root().begin(); + let mut has_mutations = false; + let mut next_member_value = EnumInitializer::Integer(0); + for enum_member in enum_declaration.members() { + let enum_member = enum_member.ok()?; + if let Some(initializer) = enum_member.initializer() { + next_member_value = EnumInitializer::Other; + let expr = initializer.expression().ok()?.omit_parentheses(); + if let Some(expr) = expr.as_any_js_literal_expression() { + match expr { + AnyJsLiteralExpression::JsNumberLiteralExpression(expr) => { + let n = expr.value_token().ok()?; + let n = n.text_trimmed(); + if let Ok(n) = n.parse::() { + next_member_value = EnumInitializer::Integer(n + 1); + } + } + AnyJsLiteralExpression::JsStringLiteralExpression(expr) => { + if enum_member.name().ok()?.name() == expr.inner_string_text().ok() { + next_member_value = EnumInitializer::EnumName; + } + } + _ => {} + } } - AnyJsLiteralExpression::JsStringLiteralExpression(expr) => { - let prev_enum_val = expr.inner_string_text().ok()?; - if prev_name.name() == Some(prev_enum_val) { - let enum_name = enum_member.name().ok()?.text(); + } else { + let x = match next_member_value { + EnumInitializer::Integer(n) => { + next_member_value = EnumInitializer::Integer(n + 1); + Some(AnyJsLiteralExpression::JsNumberLiteralExpression( + make::js_number_literal_expression(make::js_number_literal(n)), + )) + } + EnumInitializer::EnumName => { + let enum_name = enum_member.name().ok()?.name()?; + let enum_name = enum_name.text(); Some(AnyJsLiteralExpression::JsStringLiteralExpression( - make::js_string_literal_expression(make::js_string_literal(&enum_name)), + make::js_string_literal_expression(make::js_string_literal(enum_name)), )) - } else { - None } + EnumInitializer::Other => None, + }; + if let Some(x) = x { + has_mutations = true; + let new_enum_member = + enum_member + .clone() + .with_initializer(Some(make::js_initializer_clause( + make::token_decorated_with_space(JsSyntaxKind::EQ), + AnyJsExpression::AnyJsLiteralExpression(x), + ))); + mutation.replace_node_discard_trivia(enum_member, new_enum_member); } - _ => None, } - } else { - Some(AnyJsLiteralExpression::JsNumberLiteralExpression( - make::js_number_literal_expression(make::js_number_literal(count)), - )) - }; - if let Some(expr) = expr { - let new_enum_member = - enum_member - .to_owned() - .with_initializer(Some(make::js_initializer_clause( - make::token_decorated_with_space(JsSyntaxKind::EQ), - AnyJsExpression::AnyJsLiteralExpression(expr), - ))); - let mut mutation = ctx.root().begin(); - mutation.replace_node_discard_trivia(enum_member.to_owned(), new_enum_member); - Some(JsRuleAction { + } + if has_mutations { + return Some(JsRuleAction { category: ActionCategory::QuickFix, applicability: Applicability::MaybeIncorrect, - message: markup! { "" }.to_owned(), + message: markup! { "Initialize all enum members." }.to_owned(), mutation, - }) - } else { - None + }); } + None } } + +enum EnumInitializer { + // The member is initialized with an integer + Integer(i64), + /// The member name is equal to the member value + EnumName, + Other, +} diff --git a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts index f7b57e67667..9f87222a8f9 100644 --- a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts +++ b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts @@ -24,6 +24,13 @@ export enum Color { Blue, } +export enum Exotic { + A = 0.1, + B, + C = "Special", + D, +} + export enum IndexedColor { Red = "0", Green = "1", diff --git a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts.snap b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts.snap index 1858f2f97f0..76e3f37c670 100644 --- a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts.snap +++ b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/invalid.ts.snap @@ -30,6 +30,13 @@ export enum Color { Blue, } +export enum Exotic { + A = 0.1, + B, + C = "Special", + D, +} + export enum IndexedColor { Red = "0", Green = "1", @@ -39,9 +46,16 @@ export enum IndexedColor { # Diagnostics ``` -invalid.ts:2:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:1:13 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! The enum member should be initialized. + ! This enum declaration contains members that are implicitly initialized. + + > 1 │ export enum Status { + │ ^^^^^^ + 2 │ Close, + 3 │ MidClose = 1, + + i This enum member should be explicitly initialized. 1 │ export enum Status { > 2 │ Close, @@ -49,19 +63,7 @@ invalid.ts:2:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━ 3 │ MidClose = 1, 4 │ MidOpen = 10, - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. - - i Suggested fix: - - 2 │ → Close·=·0, - │ ++++ - -``` - -``` -invalid.ts:5:17 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! The enum member should be initialized. + i This enum member should be explicitly initialized. 3 │ MidClose = 1, 4 │ MidOpen = 10, @@ -70,19 +72,36 @@ invalid.ts:5:17 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 6 │ } 7 │ - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. + + i Suggested fix: Initialize all enum members. - i Suggested fix: + 1 1 │ export enum Status { + 2 │ - → Close, + 2 │ + → Close·=·0, + 3 3 │ MidClose = 1, + 4 4 │ MidOpen = 10, + 5 │ - → /*·implicit·*/·Open·/*·11·*/, + 5 │ + → /*·implicit·*/·Open·/*·11·*/·=·11, + 6 6 │ } + 7 7 │ - 5 │ → /*·implicit·*/·Open·/*·11·*/·=·11, - │ +++++ ``` ``` -invalid.ts:11:2 lint/style/useEnumInitializers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:8:13 lint/style/useEnumInitializers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! The enum member should be initialized. + ! This enum declaration contains members that are implicitly initialized. + + 6 │ } + 7 │ + > 8 │ export enum ComputedFlags { + │ ^^^^^^^^^^^^^ + 9 │ Flag1 = 1, + 10 │ Flag2 = 1 << 1, + + i This enum member should be explicitly initialized. 9 │ Flag1 = 1, 10 │ Flag2 = 1 << 1, @@ -91,15 +110,24 @@ invalid.ts:11:2 lint/style/useEnumInitializers ━━━━━━━━━━━ 12 │ } 13 │ - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. ``` ``` -invalid.ts:15:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:14:13 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! The enum member should be initialized. + ! This enum declaration contains members that are implicitly initialized. + + 12 │ } + 13 │ + > 14 │ export enum Direction { + │ ^^^^^^^^^ + 15 │ Down, + 16 │ Left, + + i This enum member should be explicitly initialized. 14 │ export enum Direction { > 15 │ Down, @@ -107,19 +135,7 @@ invalid.ts:15:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 16 │ Left, 17 │ Right, - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. - - i Suggested fix: - - 15 │ → Down·=·0, - │ ++++ - -``` - -``` -invalid.ts:16:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! The enum member should be initialized. + i This enum member should be explicitly initialized. 14 │ export enum Direction { 15 │ Down, @@ -128,19 +144,7 @@ invalid.ts:16:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 17 │ Right, 18 │ Up, - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. - - i Suggested fix: - - 16 │ → Left·=·1, - │ ++++ - -``` - -``` -invalid.ts:17:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! The enum member should be initialized. + i This enum member should be explicitly initialized. 15 │ Down, 16 │ Left, @@ -149,19 +153,7 @@ invalid.ts:17:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 18 │ Up, 19 │ } - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. - - i Suggested fix: - - 17 │ → Right·=·2, - │ ++++ - -``` - -``` -invalid.ts:18:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! The enum member should be initialized. + i This enum member should be explicitly initialized. 16 │ Left, 17 │ Right, @@ -170,19 +162,39 @@ invalid.ts:18:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 19 │ } 20 │ - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. + + i Suggested fix: Initialize all enum members. - i Suggested fix: + 13 13 │ + 14 14 │ export enum Direction { + 15 │ - → Down, + 16 │ - → Left, + 17 │ - → Right, + 18 │ - → Up, + 15 │ + → Down·=·0, + 16 │ + → Left·=·1, + 17 │ + → Right·=·2, + 18 │ + → Up·=·3, + 19 19 │ } + 20 20 │ - 18 │ → Up·=·3, - │ ++++ ``` ``` -invalid.ts:24:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:21:13 lint/style/useEnumInitializers FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! The enum member should be initialized. + ! This enum declaration contains members that are implicitly initialized. + + 19 │ } + 20 │ + > 21 │ export enum Color { + │ ^^^^^ + 22 │ Red = "Red", + 23 │ Green = "Green", + + i This enum member should be explicitly initialized. 22 │ Red = "Red", 23 │ Green = "Green", @@ -191,9 +203,9 @@ invalid.ts:24:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ 25 │ } 26 │ - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. - i Suggested fix: + i Suggested fix: Initialize all enum members. 24 │ → Blue·=·"Blue", │ +++++++++ @@ -201,17 +213,61 @@ invalid.ts:24:2 lint/style/useEnumInitializers FIXABLE ━━━━━━━ ``` ``` -invalid.ts:30:2 lint/style/useEnumInitializers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.ts:27:13 lint/style/useEnumInitializers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! The enum member should be initialized. + ! This enum declaration contains members that are implicitly initialized. + + 25 │ } + 26 │ + > 27 │ export enum Exotic { + │ ^^^^^^ + 28 │ A = 0.1, + 29 │ B, + + i This enum member should be explicitly initialized. + + 27 │ export enum Exotic { + 28 │ A = 0.1, + > 29 │ B, + │ ^ + 30 │ C = "Special", + 31 │ D, + + i This enum member should be explicitly initialized. + + 29 │ B, + 30 │ C = "Special", + > 31 │ D, + │ ^ + 32 │ } + 33 │ + + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. + + +``` + +``` +invalid.ts:34:13 lint/style/useEnumInitializers ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! This enum declaration contains members that are implicitly initialized. + + 32 │ } + 33 │ + > 34 │ export enum IndexedColor { + │ ^^^^^^^^^^^^ + 35 │ Red = "0", + 36 │ Green = "1", + + i This enum member should be explicitly initialized. - 28 │ Red = "0", - 29 │ Green = "1", - > 30 │ Blue, + 35 │ Red = "0", + 36 │ Green = "1", + > 37 │ Blue, │ ^^^^ - 31 │ } + 38 │ } - i Allowing implicit values for enum members can cause bugs if enum declarations are modified over time. + i Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time. ``` diff --git a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts index d281ef47ea5..6887ff6cc27 100644 --- a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts +++ b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts @@ -12,4 +12,14 @@ export enum Color { export enum Mix { Str = "Str", Number = 0, -} \ No newline at end of file +} + +export declare enum Weather { + Rainy, + Sunny, +} + +declare enum Weather2 { + Rainy, + Sunny, +} diff --git a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts.snap b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts.snap index 4b2e36d04e5..a9ecb08ed23 100644 --- a/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts.snap +++ b/crates/rome_js_analyze/tests/specs/style/useEnumInitializers/valid.ts.snap @@ -1,6 +1,5 @@ --- source: crates/rome_js_analyze/tests/spec_tests.rs -assertion_line: 74 expression: valid.ts --- # Input @@ -20,6 +19,17 @@ export enum Mix { Str = "Str", Number = 0, } + +export declare enum Weather { + Rainy, + Sunny, +} + +declare enum Weather2 { + Rainy, + Sunny, +} + ``` diff --git a/website/src/pages/lint/rules/useEnumInitializers.md b/website/src/pages/lint/rules/useEnumInitializers.md index 89909175eef..720364e0a25 100644 --- a/website/src/pages/lint/rules/useEnumInitializers.md +++ b/website/src/pages/lint/rules/useEnumInitializers.md @@ -9,9 +9,11 @@ parent: lint/rules/index Require that each enum member value be explicitly initialized. -TypeScript enums are a practical way to organize semantically related constant values. Members of enums that don't have explicit values are by default given sequentially increasing numbers. +_TypeScript_ enums are a practical way to organize semantically related constant values. +Members of enums that don't have explicit values are by default given sequentially increasing numbers. -When the value of enum members are important, allowing implicit values for enum members can cause bugs if enum declarations are modified over time. +When the value of enum members are important, +allowing implicit values for enum members can cause bugs if enum declarations are modified over time. Source: https://typescript-eslint.io/rules/prefer-enum-initializers @@ -25,9 +27,16 @@ enum Version { } ``` -
style/useEnumInitializers.js:2:5 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
+
style/useEnumInitializers.js:1:6 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   The enum member should be initialized.
+   This enum declaration contains members that are implicitly initialized.
+  
+  > 1 │ enum Version {
+        ^^^^^^^
+    2 │     V1,
+    3 │ }
+  
+   This enum member should be explicitly initialized.
   
     1 │ enum Version {
   > 2 │     V1,
@@ -35,9 +44,9 @@ enum Version {
     3 │ }
     4 │ 
   
-   Allowing implicit values for enum members can cause bugs if enum declarations are modified over time.
+   Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time.
   
-   Suggested fix: 
+   Suggested fix: Initialize all enum members.
   
     2 │ ····V1·=·0,
         ++++ 
@@ -50,9 +59,16 @@ enum Status {
 }
 ```
 
-
style/useEnumInitializers.js:3:5 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
+
style/useEnumInitializers.js:1:6 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   The enum member should be initialized.
+   This enum declaration contains members that are implicitly initialized.
+  
+  > 1 │ enum Status {
+        ^^^^^^
+    2 │     Open = 1,
+    3 │     Close,
+  
+   This enum member should be explicitly initialized.
   
     1 │ enum Status {
     2 │     Open = 1,
@@ -61,9 +77,9 @@ enum Status {
     4 │ }
     5 │ 
   
-   Allowing implicit values for enum members can cause bugs if enum declarations are modified over time.
+   Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time.
   
-   Suggested fix: 
+   Suggested fix: Initialize all enum members.
   
     3 │ ····Close·=·2,
            ++++ 
@@ -77,9 +93,16 @@ enum Color {
 }
 ```
 
-
style/useEnumInitializers.js:4:5 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
+
style/useEnumInitializers.js:1:6 lint/style/useEnumInitializers  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━
 
-   The enum member should be initialized.
+   This enum declaration contains members that are implicitly initialized.
+  
+  > 1 │ enum Color {
+        ^^^^^
+    2 │     Red = "Red",
+    3 │     Green = "Green",
+  
+   This enum member should be explicitly initialized.
   
     2 │     Red = "Red",
     3 │     Green = "Green",
@@ -88,9 +111,9 @@ enum Color {
     5 │ }
     6 │ 
   
-   Allowing implicit values for enum members can cause bugs if enum declarations are modified over time.
+   Allowing implicit initializations for enum members can cause bugs if enum declarations are modified over time.
   
-   Suggested fix: 
+   Suggested fix: Initialize all enum members.
   
     4 │ ····Blue·=·"Blue",
           +++++++++ 
@@ -113,6 +136,13 @@ enum Color {
 }
 ```
 
+```ts
+declare enum Weather {
+    Rainy,
+    Sunny,
+}
+```
+
 ## Related links
 
 - [Disable a rule](/linter/#disable-a-lint-rule)