-
-
Notifications
You must be signed in to change notification settings - Fork 470
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(linter): typescript-eslint no-useless-empty-export (#3605)
partof: #2180 docs: https://typescript-eslint.io/rules/no-useless-empty-export/ code: https://github.com/typescript-eslint/typescript-eslint/blob/584db29ec44ce4e9cb71afac35d48994889168e6/packages/eslint-plugin/src/rules/no-useless-empty-export.ts test: https://github.com/typescript-eslint/typescript-eslint/blob/ac397f18176a9defd8c189b5b6b4e5d0b7582210/packages/eslint-plugin/tests/rules/no-useless-empty-export.test.ts --------- Co-authored-by: Boshen <[email protected]>
- Loading branch information
1 parent
0c4ccb4
commit 21d3425
Showing
3 changed files
with
188 additions
and
0 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
129 changes: 129 additions & 0 deletions
129
crates/oxc_linter/src/rules/typescript/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,129 @@ | ||
use oxc_ast::AstKind; | ||
use oxc_diagnostics::OxcDiagnostic; | ||
use oxc_macros::declare_oxc_lint; | ||
use oxc_span::Span; | ||
|
||
use crate::{context::LintContext, rule::Rule, AstNode}; | ||
|
||
fn no_useless_empty_export_diagnostic(span0: Span) -> OxcDiagnostic { | ||
OxcDiagnostic::warn( | ||
"typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file", | ||
) | ||
.with_help("Empty export does nothing and can be removed.") | ||
.with_labels([span0.into()]) | ||
} | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct NoUselessEmptyExport; | ||
|
||
declare_oxc_lint!( | ||
/// ### What it does | ||
/// | ||
/// Disallow empty exports that don't change anything in a module file. | ||
/// | ||
/// ### Example | ||
/// | ||
/// ### Bad | ||
/// ```javascript | ||
/// export const value = 'Hello, world!'; | ||
/// export {}; | ||
/// ``` | ||
/// | ||
/// ### Good | ||
/// ```javascript | ||
/// export const value = 'Hello, world!'; | ||
/// ``` | ||
/// | ||
NoUselessEmptyExport, | ||
correctness | ||
); | ||
|
||
impl Rule for NoUselessEmptyExport { | ||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { | ||
let AstKind::ExportNamedDeclaration(decl) = node.kind() else { return }; | ||
if decl.declaration.is_some() || !decl.specifiers.is_empty() { | ||
return; | ||
} | ||
let module_record = ctx.semantic().module_record(); | ||
if module_record.exported_bindings.is_empty() | ||
&& module_record.local_export_entries.is_empty() | ||
&& module_record.indirect_export_entries.is_empty() | ||
&& module_record.star_export_entries.is_empty() | ||
&& module_record.export_default.is_none() | ||
{ | ||
return; | ||
} | ||
ctx.diagnostic_with_fix(no_useless_empty_export_diagnostic(decl.span), |fixer| { | ||
fixer.delete(&decl.span) | ||
}); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test() { | ||
use crate::tester::Tester; | ||
|
||
let pass = vec![ | ||
"declare module '_'", | ||
"import {} from '_';", | ||
"import * as _ from '_';", | ||
"export = {};", | ||
"export = 3;", | ||
"export const _ = {};", | ||
" | ||
const _ = {}; | ||
export default _; | ||
", | ||
" | ||
export * from '_'; | ||
export = {}; | ||
", | ||
"export {};", | ||
]; | ||
|
||
let fail = vec![ | ||
" | ||
export const _ = {}; | ||
export {}; | ||
", | ||
" | ||
export * from '_'; | ||
export {}; | ||
", | ||
" | ||
export {}; | ||
export * from '_'; | ||
", | ||
" | ||
const _ = {}; | ||
export default _; | ||
export {}; | ||
", | ||
" | ||
export {}; | ||
const _ = {}; | ||
export default _; | ||
", | ||
" | ||
const _ = {}; | ||
export { _ }; | ||
export {}; | ||
", | ||
// " | ||
// import _ = require('_'); | ||
// export {}; | ||
// ", | ||
]; | ||
|
||
let fix = vec![ | ||
("export const _ = {};export {};", "export const _ = {};"), | ||
("export * from '_';export {};", "export * from '_';"), | ||
("export {};export * from '_';", "export * from '_';"), | ||
("const _ = {};export default _;export {};", "const _ = {};export default _;"), | ||
("export {};const _ = {};export default _;", "const _ = {};export default _;"), | ||
("const _ = {};export { _ };export {};", "const _ = {};export { _ };"), | ||
// ("import _ = require('_');export {};", "import _ = require('_');"), | ||
]; | ||
|
||
Tester::new(NoUselessEmptyExport::NAME, pass, fail).expect_fix(fix).test_and_snapshot(); | ||
} |
57 changes: 57 additions & 0 deletions
57
crates/oxc_linter/src/snapshots/no_useless_empty_export.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,57 @@ | ||
--- | ||
source: crates/oxc_linter/src/tester.rs | ||
expression: no_useless_empty_export | ||
--- | ||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:3:13] | ||
2 │ export const _ = {}; | ||
3 │ export {}; | ||
· ────────── | ||
4 │ | ||
╰──── | ||
help: Empty export does nothing and can be removed. | ||
|
||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:3:13] | ||
2 │ export * from '_'; | ||
3 │ export {}; | ||
· ────────── | ||
4 │ | ||
╰──── | ||
help: Empty export does nothing and can be removed. | ||
|
||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:2:13] | ||
1 │ | ||
2 │ export {}; | ||
· ────────── | ||
3 │ export * from '_'; | ||
╰──── | ||
help: Empty export does nothing and can be removed. | ||
|
||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:4:13] | ||
3 │ export default _; | ||
4 │ export {}; | ||
· ────────── | ||
5 │ | ||
╰──── | ||
help: Empty export does nothing and can be removed. | ||
|
||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:2:13] | ||
1 │ | ||
2 │ export {}; | ||
· ────────── | ||
3 │ const _ = {}; | ||
╰──── | ||
help: Empty export does nothing and can be removed. | ||
|
||
⚠ typescript-eslint(no-useless-empty-export): Disallow empty exports that don't change anything in a module file | ||
╭─[no_useless_empty_export.tsx:4:13] | ||
3 │ export { _ }; | ||
4 │ export {}; | ||
· ────────── | ||
5 │ | ||
╰──── | ||
help: Empty export does nothing and can be removed. |