feat(rome_js_analyze): `noConstEnum`
MODIFY
crates/rome_diagnostics_categories/src/categories.rs
crates/rome_diagnostics_categories/src/categories.rs
@@ -79,6 +79,7 @@ define_dategories! {
"lint/nursery/noBannedTypes":"https://docs.rome.tools/lint/rules/noBannedTypes",
"lint/nursery/noConditionalAssignment": "https://docs.rome.tools/lint/rules/noConditionalAssignment",
"lint/nursery/noConstAssign": "https://docs.rome.tools/lint/rules/noConstAssign",
+ "lint/nursery/noConstEnum": "https://docs.rome.tools/lint/rules/noConstEnum",
"lint/nursery/noDistractingElements": "https://docs.rome.tools/lint/rules/noDistractingElements",
"lint/nursery/noConstructorReturn": "https://docs.rome.tools/lint/rules/noConstructorReturn",
"lint/nursery/noSetterReturn": "https://docs.rome.tools/lint/rules/noSetterReturn",

MODIFY
crates/rome_js_analyze/src/analyzers/nursery.rs
crates/rome_js_analyze/src/analyzers/nursery.rs
@@ -4,6 +4,7 @@ use rome_analyze::declare_group;
mod no_access_key;
mod no_banned_types;
mod no_conditional_assignment;
+mod no_const_enum;
mod no_constructor_return;
mod no_distracting_elements;
mod no_dupe_keys;
@@ -21,4 +22,4 @@ mod use_default_switch_clause_last;
mod use_flat_map;
mod use_numeric_literals;
mod use_valid_for_direction;
-declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_access_key :: NoAccessKey , self :: no_banned_types :: NoBannedTypes , self :: no_conditional_assignment :: NoConditionalAssignment , self :: no_constructor_return :: NoConstructorReturn , self :: no_distracting_elements :: NoDistractingElements , self :: no_dupe_keys :: NoDupeKeys , self :: no_empty_interface :: NoEmptyInterface , self :: no_explicit_any :: NoExplicitAny , self :: no_extra_non_null_assertion :: NoExtraNonNullAssertion , self :: no_header_scope :: NoHeaderScope , self :: no_invalid_constructor_super :: NoInvalidConstructorSuper , self :: no_precision_loss :: NoPrecisionLoss , self :: no_setter_return :: NoSetterReturn , self :: no_string_case_mismatch :: NoStringCaseMismatch , self :: no_unsafe_finally :: NoUnsafeFinally , self :: no_void_type_return :: NoVoidTypeReturn , self :: use_default_switch_clause_last :: UseDefaultSwitchClauseLast , self :: use_flat_map :: UseFlatMap , self :: use_numeric_literals :: UseNumericLiterals , self :: use_valid_for_direction :: UseValidForDirection ,] } }
+declare_group! { pub (crate) Nursery { name : "nursery" , rules : [self :: no_access_key :: NoAccessKey , self :: no_banned_types :: NoBannedTypes , self :: no_conditional_assignment :: NoConditionalAssignment , self :: no_const_enum :: NoConstEnum , self :: no_constructor_return :: NoConstructorReturn , self :: no_distracting_elements :: NoDistractingElements , self :: no_dupe_keys :: NoDupeKeys , self :: no_empty_interface :: NoEmptyInterface , self :: no_explicit_any :: NoExplicitAny , self :: no_extra_non_null_assertion :: NoExtraNonNullAssertion , self :: no_header_scope :: NoHeaderScope , self :: no_invalid_constructor_super :: NoInvalidConstructorSuper , self :: no_precision_loss :: NoPrecisionLoss , self :: no_setter_return :: NoSetterReturn , self :: no_string_case_mismatch :: NoStringCaseMismatch , self :: no_unsafe_finally :: NoUnsafeFinally , self :: no_void_type_return :: NoVoidTypeReturn , self :: use_default_switch_clause_last :: UseDefaultSwitchClauseLast , self :: use_flat_map :: UseFlatMap , self :: use_numeric_literals :: UseNumericLiterals , self :: use_valid_for_direction :: UseValidForDirection ,] } }

ADD
crates/rome_js_analyze/src/analyzers/nursery/no_const_enum.rs
+use rome_analyze::context::RuleContext;
+use rome_analyze::{declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic};
+use rome_console::markup;
+use rome_diagnostics::Applicability;
+use rome_js_syntax::{JsSyntaxToken, TsEnumDeclaration};
+use rome_rowan::{AstNode, BatchMutationExt};
+
+use crate::JsRuleAction;
+
+declare_rule! {
+ /// Disallow TypeScript `const enum`
+ ///
+ /// Const enums are enums that should be inlined at use sites.
+ /// Const enums are not supported by bundlers and are incompatible with the `isolatedModules` mode.
+ /// Their use can lead to import inexistent values (because const enums are erased).
+ ///
+ /// Thus, library authors and bundler users should not use const enums.
+ ///
+ /// ## Examples
+ ///
+ /// ### Invalid
+ ///
+ /// ```ts,expect_diagnostic
+ /// const enum Status {
+ /// Open,
+ /// Close,
+ /// }
+ /// ```
+ ///
+ /// ### Valid
+ ///
+ /// ```ts
+ /// enum Status {
+ /// Open,
+ /// Close,
+ /// }
+ /// ```
+ pub(crate) NoConstEnum {
+ version: "11.0.0",
+ name: "noConstEnum",
+ recommended: false,
+ }
+}
+
+impl Rule for NoConstEnum {
+ type Query = Ast<TsEnumDeclaration>;
+ type State = JsSyntaxToken;
+ type Signals = Option<Self::State>;
+ type Options = ();
+
+ fn run(ctx: &RuleContext<Self>) -> Self::Signals {
+ let enum_decl = ctx.query();
+ enum_decl.const_token()
+ }
+
+ fn diagnostic(ctx: &RuleContext<Self>, _: &Self::State) -> Option<RuleDiagnostic> {
+ let enum_decl = ctx.query();
+ Some(RuleDiagnostic::new(
+ rule_category!(),
+ enum_decl.range(),
+ markup! {
+ "The "<Emphasis>"enum declaration"</Emphasis>" should not be "<Emphasis>"const"</Emphasis>
+ },
+ ).note(
+ "Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values."
+ ).note(markup! {
+ "See "<Hyperlink href="https://www.typescriptlang.org/docs/handbook/enums.html#const-enum-pitfalls">"TypeSCript Docs"</Hyperlink>" for more details."
+ }))
+ }
+
+ fn action(ctx: &RuleContext<Self>, const_token: &Self::State) -> Option<JsRuleAction> {
+ let mut mutation = ctx.root().begin();
+ mutation.remove_token(const_token.to_owned());
+ Some(JsRuleAction {
+ category: ActionCategory::QuickFix,
+ applicability: Applicability::Always,
+ message: markup! {
+ "Turn the "<Emphasis>"const enum"</Emphasis>" into a regular "<Emphasis>"enum"</Emphasis>"."
+ }.to_owned(),
+ mutation,
+ })
+ }
+}

ADD
crates/rome_js_analyze/tests/specs/nursery/noConstEnum.ts
+export /* const */ const /* enum */ enum Status {
+ Open,
+ Close,
+}
+
+export enum Direction {
+ Prev,
+ Next,
+}
\ No newline at end of file

MODIFY
crates/rome_service/src/configuration/linter/rules.rs
crates/rome_service/src/configuration/linter/rules.rs
@@ -737,6 +737,8 @@ struct NurserySchema {
no_conditional_assignment: Option<RuleConfiguration>,
#[doc = "Prevents from having const variables being re-assigned."]
no_const_assign: Option<RuleConfiguration>,
+ #[doc = "Disallow TypeScript const enum"]
+ no_const_enum: Option<RuleConfiguration>,
#[doc = "Disallow returning a value from a constructor"]
no_constructor_return: Option<RuleConfiguration>,
#[doc = "Enforces that no distracting elements are used."]
@@ -782,11 +784,12 @@ struct NurserySchema {
}
impl Nursery {
const CATEGORY_NAME: &'static str = "nursery";
- pub(crate) const CATEGORY_RULES: [&'static str; 25] = [
+ pub(crate) const CATEGORY_RULES: [&'static str; 26] = [
"noAccessKey",
"noBannedTypes",
"noConditionalAssignment",
"noConstAssign",
+ "noConstEnum",
"noConstructorReturn",
"noDistractingElements",
"noDupeKeys",

MODIFY
editors/vscode/configuration_schema.json
editors/vscode/configuration_schema.json
}
]
},
+ "noConstEnum": {
+ "description": "Disallow TypeScript const enum",
+ "anyOf": [
+ {
+ "$ref": "#/definitions/RuleConfiguration"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
"noConstructorReturn": {
"description": "Disallow returning a value from a constructor",
"anyOf": [

MODIFY
npm/backend-jsonrpc/src/workspace.ts
npm/backend-jsonrpc/src/workspace.ts
@@ -363,6 +363,10 @@ export interface Nursery {
* Prevents from having const variables being re-assigned.
*/
noConstAssign?: RuleConfiguration;
+ /**
+ * Disallow TypeScript const enum
+ */
+ noConstEnum?: RuleConfiguration;
/**
* Disallow returning a value from a constructor
*/
@@ -659,6 +663,7 @@ export type Category =
| "lint/nursery/noBannedTypes"
| "lint/nursery/noConditionalAssignment"
| "lint/nursery/noConstAssign"
+ | "lint/nursery/noConstEnum"
| "lint/nursery/noDistractingElements"
| "lint/nursery/noConstructorReturn"
| "lint/nursery/noSetterReturn"

MODIFY
npm/rome/configuration_schema.json
npm/rome/configuration_schema.json
}
]
},
+ "noConstEnum": {
+ "description": "Disallow TypeScript const enum",
+ "anyOf": [
+ {
+ "$ref": "#/definitions/RuleConfiguration"
+ },
+ {
+ "type": "null"
+ }
+ ]
+ },
"noConstructorReturn": {
"description": "Disallow returning a value from a constructor",
"anyOf": [

MODIFY
website/src/pages/lint/rules/index.mdx
website/src/pages/lint/rules/index.mdx
@@ -467,6 +467,12 @@ Disallow assignment operators in conditional expressions.
Prevents from having <code>const</code> variables being re-assigned.
</section>
<section class="rule">
+<h3 data-toc-exclude id="noConstEnum">
+ <a href="/lint/rules/noConstEnum">noConstEnum</a>
+</h3>
+Disallow TypeScript <code>const enum</code>
+</section>
+<section class="rule">
<h3 data-toc-exclude id="noConstructorReturn">
<a href="/lint/rules/noConstructorReturn">noConstructorReturn</a>
</h3>

feat(rome_js_analyze): `noConstEnum` (#3849)