This repository has been archived by the owner on Aug 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 657
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rome_js_analyze): noUselessEmptyExport (#4693)
- Loading branch information
Showing
29 changed files
with
597 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
125 changes: 125 additions & 0 deletions
125
crates/rome_js_analyze/src/analyzers/nursery/no_useless_empty_export.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
use rome_analyze::{context::RuleContext, declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic}; | ||
use rome_console::markup; | ||
use rome_diagnostics::Applicability; | ||
use rome_js_syntax::{AnyJsModuleItem, JsExport, JsModuleItemList, JsSyntaxToken}; | ||
use rome_rowan::{AstNode, AstSeparatedList, BatchMutationExt}; | ||
|
||
use crate::JsRuleAction; | ||
|
||
declare_rule! { | ||
/// Disallow empty exports that don't change anything in a module file. | ||
/// | ||
/// An empty `export {}` is sometimes useful to turn a file that would otherwise be a script into a module. | ||
/// Per the [TypeScript Handbook Modules page](https://www.typescriptlang.org/docs/handbook/modules.html): | ||
/// | ||
/// > In TypeScript, just as in ECMAScript 2015, | ||
/// > any file containing a top-level import or export is considered a module. | ||
/// > Conversely, a file without any top-level import or export declarations is treated as a script | ||
/// > whose contents are available in the global scope. | ||
/// | ||
/// However, an `export {}` statement does nothing if there are any other top-level import or export in the file. | ||
/// | ||
/// Source: https://typescript-eslint.io/rules/no-useless-empty-export/ | ||
/// | ||
/// ## Examples | ||
/// | ||
/// ### Invalid | ||
/// | ||
/// ```js,expect_diagnostic | ||
/// import { A } from "module"; | ||
/// export {}; | ||
/// ``` | ||
/// | ||
/// ```js,expect_diagnostic | ||
/// export const A = 0; | ||
/// export {}; | ||
/// ``` | ||
/// | ||
/// ## Valid | ||
/// | ||
/// ```js | ||
/// export {}; | ||
/// ``` | ||
/// | ||
pub(crate) NoUselessEmptyExport { | ||
version: "next", | ||
name: "noUselessEmptyExport", | ||
recommended: true, | ||
} | ||
} | ||
|
||
impl Rule for NoUselessEmptyExport { | ||
type Query = Ast<JsExport>; | ||
/// The first import or export that makes useless the empty export. | ||
type State = JsSyntaxToken; | ||
type Signals = Option<Self::State>; | ||
type Options = (); | ||
|
||
fn run(ctx: &RuleContext<Self>) -> Self::Signals { | ||
let node = ctx.query(); | ||
if is_empty_export(node) { | ||
let module_item_list = JsModuleItemList::cast(node.syntax().parent()?)?; | ||
// allow reporting an empty export that precedes another empty export. | ||
let mut ignore_empty_export = true; | ||
for module_item in module_item_list { | ||
match module_item { | ||
AnyJsModuleItem::AnyJsStatement(_) => {} | ||
AnyJsModuleItem::JsImport(import) => return import.import_token().ok(), | ||
AnyJsModuleItem::JsExport(export) => { | ||
if !is_empty_export(&export) { | ||
return export.export_token().ok(); | ||
} | ||
if !ignore_empty_export { | ||
return export.export_token().ok(); | ||
} | ||
if node == &export { | ||
ignore_empty_export = false | ||
} | ||
} | ||
} | ||
} | ||
} | ||
None | ||
} | ||
|
||
fn diagnostic(ctx: &RuleContext<Self>, token: &Self::State) -> Option<RuleDiagnostic> { | ||
Some( | ||
RuleDiagnostic::new( | ||
rule_category!(), | ||
ctx.query().range(), | ||
markup! { | ||
"This empty "<Emphasis>"export"</Emphasis>" is useless because there's another "<Emphasis>"export"</Emphasis>" or "<Emphasis>"import"</Emphasis>"." | ||
}, | ||
).detail(token.text_trimmed_range(), markup! { | ||
"This "<Emphasis>{token.text_trimmed()}</Emphasis>" makes useless the empty export." | ||
}), | ||
) | ||
} | ||
|
||
fn action(ctx: &RuleContext<Self>, _: &Self::State) -> Option<JsRuleAction> { | ||
let mut mutation = ctx.root().begin(); | ||
mutation.remove_node(ctx.query().clone()); | ||
Some(JsRuleAction { | ||
category: ActionCategory::QuickFix, | ||
applicability: Applicability::Always, | ||
message: markup! { "Remove this useless empty export." }.to_owned(), | ||
mutation, | ||
}) | ||
} | ||
} | ||
|
||
fn is_empty_export(export: &JsExport) -> bool { | ||
(|| -> Option<bool> { | ||
Some( | ||
export | ||
.export_clause() | ||
.ok()? | ||
.as_js_export_named_clause()? | ||
.specifiers() | ||
.iter() | ||
.count() | ||
== 0, | ||
) | ||
})() | ||
.unwrap_or(false) | ||
} |
2 changes: 2 additions & 0 deletions
2
...s/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_default_export.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export default {}; | ||
export {} |
35 changes: 35 additions & 0 deletions
35
...e_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_default_export.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
expression: invalid_with_default_export.js | ||
--- | ||
# Input | ||
```js | ||
export default {}; | ||
export {} | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid_with_default_export.js:2:1 lint/nursery/noUselessEmptyExport FIXABLE ━━━━━━━━━━━━━━━━━━━━━ | ||
! This empty export is useless because there's another export or import. | ||
1 │ export default {}; | ||
> 2 │ export {} | ||
│ ^^^^^^^^^ | ||
i This export makes useless the empty export. | ||
> 1 │ export default {}; | ||
│ ^^^^^^ | ||
2 │ export {} | ||
i Safe fix: Remove this useless empty export. | ||
1 1 │ export default {}; | ||
2 │ - export·{} | ||
``` | ||
|
||
|
2 changes: 2 additions & 0 deletions
2
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_empty_export.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export {} | ||
export {} |
34 changes: 34 additions & 0 deletions
34
...ome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_empty_export.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
expression: invalid_with_empty_export.js | ||
--- | ||
# Input | ||
```js | ||
export {} | ||
export {} | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid_with_empty_export.js:1:1 lint/nursery/noUselessEmptyExport FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━ | ||
! This empty export is useless because there's another export or import. | ||
> 1 │ export {} | ||
│ ^^^^^^^^^ | ||
2 │ export {} | ||
i This export makes useless the empty export. | ||
1 │ export {} | ||
> 2 │ export {} | ||
│ ^^^^^^ | ||
i Safe fix: Remove this useless empty export. | ||
1 │ export·{} | ||
│ --------- | ||
``` | ||
|
||
|
3 changes: 3 additions & 0 deletions
3
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_export.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function f() { return 0 } | ||
export const A = f(); | ||
export {} |
39 changes: 39 additions & 0 deletions
39
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_export.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
expression: invalid_with_export.js | ||
--- | ||
# Input | ||
```js | ||
function f() { return 0 } | ||
export const A = f(); | ||
export {} | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid_with_export.js:3:1 lint/nursery/noUselessEmptyExport FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! This empty export is useless because there's another export or import. | ||
1 │ function f() { return 0 } | ||
2 │ export const A = f(); | ||
> 3 │ export {} | ||
│ ^^^^^^^^^ | ||
i This export makes useless the empty export. | ||
1 │ function f() { return 0 } | ||
> 2 │ export const A = f(); | ||
│ ^^^^^^ | ||
3 │ export {} | ||
i Safe fix: Remove this useless empty export. | ||
1 1 │ function f() { return 0 } | ||
2 2 │ export const A = f(); | ||
3 │ - export·{} | ||
``` | ||
|
||
|
2 changes: 2 additions & 0 deletions
2
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_export_from.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "mod"; | ||
export {} |
35 changes: 35 additions & 0 deletions
35
...rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_export_from.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
expression: invalid_with_export_from.js | ||
--- | ||
# Input | ||
```js | ||
export * from "mod"; | ||
export {} | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid_with_export_from.js:2:1 lint/nursery/noUselessEmptyExport FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! This empty export is useless because there's another export or import. | ||
1 │ export * from "mod"; | ||
> 2 │ export {} | ||
│ ^^^^^^^^^ | ||
i This export makes useless the empty export. | ||
> 1 │ export * from "mod"; | ||
│ ^^^^^^ | ||
2 │ export {} | ||
i Safe fix: Remove this useless empty export. | ||
1 1 │ export * from "mod"; | ||
2 │ - export·{} | ||
``` | ||
|
||
|
3 changes: 3 additions & 0 deletions
3
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_import.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { A } from "mod" | ||
function f() { return 0 } | ||
export {} |
39 changes: 39 additions & 0 deletions
39
crates/rome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_import.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
expression: invalid_with_import.js | ||
--- | ||
# Input | ||
```js | ||
import { A } from "mod" | ||
function f() { return 0 } | ||
export {} | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
invalid_with_import.js:3:1 lint/nursery/noUselessEmptyExport FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
! This empty export is useless because there's another export or import. | ||
1 │ import { A } from "mod" | ||
2 │ function f() { return 0 } | ||
> 3 │ export {} | ||
│ ^^^^^^^^^ | ||
i This import makes useless the empty export. | ||
> 1 │ import { A } from "mod" | ||
│ ^^^^^^ | ||
2 │ function f() { return 0 } | ||
3 │ export {} | ||
i Safe fix: Remove this useless empty export. | ||
1 1 │ import { A } from "mod" | ||
2 2 │ function f() { return 0 } | ||
3 │ - export·{} | ||
``` | ||
|
||
|
3 changes: 3 additions & 0 deletions
3
...ome_js_analyze/tests/specs/nursery/noUselessEmptyExport/invalid_with_sideeffect_import.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import "mod" | ||
function f() { return 0 } | ||
export {} |
Oops, something went wrong.