Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
feat(rome_js_analyze): noConstEnum (#3849)
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos authored Nov 28, 2022
1 parent fcdff03 commit 68ebebc
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 2 deletions.
1 change: 1 addition & 0 deletions crates/rome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_js_analyze/src/analyzers/nursery.rs

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

83 changes: 83 additions & 0 deletions crates/rome_js_analyze/src/analyzers/nursery/no_const_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
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,
})
}
}
9 changes: 9 additions & 0 deletions crates/rome_js_analyze/tests/specs/nursery/noConstEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export /* const */ const /* enum */ enum Status {
Open,
Close,
}

export enum Direction {
Prev,
Next,
}
45 changes: 45 additions & 0 deletions crates/rome_js_analyze/tests/specs/nursery/noConstEnum.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
source: crates/rome_js_analyze/tests/spec_tests.rs
assertion_line: 74
expression: noConstEnum.ts
---
# Input
```js
export /* const */ const /* enum */ enum Status {
Open,
Close,
}

export enum Direction {
Prev,
Next,
}
```

# Diagnostics
```
noConstEnum.ts:1:20 lint/nursery/noConstEnum FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! The enum declaration should not be const
> 1 │ export /* const */ const /* enum */ enum Status {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 2 │ Open,
> 3 │ Close,
> 4 │ }
│ ^
5 │
6 │ export enum Direction {
i Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
i See TypeSCript Docs for more details.
i Safe fix: Turn the const enum into a regular enum.
1 │ export·/*·const·*/·const·/*·enum·*/·enum·Status·{
│ -----------------
```


5 changes: 4 additions & 1 deletion crates/rome_service/src/configuration/linter/rules.rs

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

11 changes: 11 additions & 0 deletions editors/vscode/configuration_schema.json

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

5 changes: 5 additions & 0 deletions npm/backend-jsonrpc/src/workspace.ts

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

11 changes: 11 additions & 0 deletions npm/rome/configuration_schema.json

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

6 changes: 6 additions & 0 deletions website/src/pages/lint/rules/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
57 changes: 57 additions & 0 deletions website/src/pages/lint/rules/noConstEnum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: Lint Rule noConstEnum
parent: lint/rules/index
---

# noConstEnum (since v11.0.0)

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
const enum Status {
Open,
Close,
}
```

<pre class="language-text"><code class="language-text">nursery/noConstEnum.js:1:1 <a href="https://docs.rome.tools/lint/rules/noConstEnum">lint/nursery/noConstEnum</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

<strong><span style="color: Orange;"> </span></strong><strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">The </span><span style="color: Orange;"><strong>enum declaration</strong></span><span style="color: Orange;"> should not be </span><span style="color: Orange;"><strong>const</strong></span>

<strong><span style="color: Tomato;"> </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>1 │ </strong>const enum Status {
<strong> │ </strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong>
<strong><span style="color: Tomato;"> </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> Open,
<strong><span style="color: Tomato;"> </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong> Close,
<strong><span style="color: Tomato;"> </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>4 │ </strong>}
<strong> │ </strong><strong><span style="color: Tomato;">^</span></strong>
<strong>5 │ </strong>

<strong><span style="color: rgb(38, 148, 255);"> </span></strong><strong><span style="color: rgb(38, 148, 255);">ℹ</span></strong> <span style="color: rgb(38, 148, 255);">Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.</span>

<strong><span style="color: rgb(38, 148, 255);"> </span></strong><strong><span style="color: rgb(38, 148, 255);">ℹ</span></strong> <span style="color: rgb(38, 148, 255);">See </span><span style="color: rgb(38, 148, 255);"><a href="https://www.typescriptlang.org/docs/handbook/enums.html#const-enum-pitfalls">TypeSCript Docs</a></span><span style="color: rgb(38, 148, 255);"> for more details.</span>

<strong><span style="color: rgb(38, 148, 255);"> </span></strong><strong><span style="color: rgb(38, 148, 255);">ℹ</span></strong> <span style="color: rgb(38, 148, 255);">Safe fix</span><span style="color: rgb(38, 148, 255);">: </span><span style="color: rgb(38, 148, 255);">Turn the </span><span style="color: rgb(38, 148, 255);"><strong>const enum</strong></span><span style="color: rgb(38, 148, 255);"> into a regular </span><span style="color: rgb(38, 148, 255);"><strong>enum</strong></span><span style="color: rgb(38, 148, 255);">.</span>

<strong> </strong><strong> 1 │ </strong><span style="color: Tomato;">c</span><span style="color: Tomato;">o</span><span style="color: Tomato;">n</span><span style="color: Tomato;">s</span><span style="color: Tomato;">t</span><span style="opacity: 0.8;"><span style="color: Tomato;">·</span></span>enum<span style="opacity: 0.8;">·</span>Status<span style="opacity: 0.8;">·</span>{
<strong> </strong><strong> │ </strong><span style="color: Tomato;">-</span><span style="color: Tomato;">-</span><span style="color: Tomato;">-</span><span style="color: Tomato;">-</span><span style="color: Tomato;">-</span><span style="color: Tomato;">-</span>
</code></pre>

### Valid

```ts
enum Status {
Open,
Close,
}
```

0 comments on commit 68ebebc

Please sign in to comment.