Valerii Smirnov 2024-03-16 06:14:07 +01:00 committed by GitHub
parent 9edda499aa
commit 26a8171b98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 0 deletions

View file

@ -13,6 +13,7 @@ mod import {
pub mod namespace;
pub mod no_amd;
pub mod no_cycle;
pub mod no_default_export;
pub mod no_deprecated;
pub mod no_duplicates;
pub mod no_named_as_default;
@ -582,6 +583,7 @@ oxc_macros::declare_all_lint_rules! {
import::no_unresolved,
import::no_unused_modules,
import::no_duplicates,
import::no_default_export,
jsx_a11y::alt_text,
jsx_a11y::anchor_has_content,
jsx_a11y::anchor_is_valid,

View file

@ -0,0 +1,101 @@
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{context::LintContext, rule::Rule};
#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-import(no-default-export): Prefer named exports")]
#[diagnostic(severity(warning))]
struct NoDefaultExportDiagnostic(#[label] Span);
#[derive(Debug, Default, Clone)]
pub struct NoDefaultExport;
declare_oxc_lint!(
/// ### What it does
///
/// Forbid a module to have a default exports. This help your editor to provide better auto imports.
///
/// ### Examples
///
/// ```javascript
/// // bad1.js
///
/// // There is a default export.
/// export const foo = 'foo';
/// const bar = 'bar';
/// export default 'bar';
/// ```
///
/// ```javascript
/// // bad2.js
///
/// // There is a default export.
/// const foo = 'foo';
/// export { foo as default }
/// ```
///
NoDefaultExport,
nursery
);
impl Rule for NoDefaultExport {
fn run_once(&self, ctx: &LintContext<'_>) {
let module_record = ctx.semantic().module_record();
write_diagnostic_optional(ctx, module_record.export_default);
module_record.export_default_duplicated.iter().for_each(|it| write_diagnostic(ctx, *it));
write_diagnostic_optional(ctx, module_record.exported_bindings.get("default").copied());
}
}
fn write_diagnostic(ctx: &LintContext<'_>, span: Span) {
ctx.diagnostic(NoDefaultExportDiagnostic(span));
}
fn write_diagnostic_optional(ctx: &LintContext<'_>, span_option: Option<Span>) {
if let Some(span) = span_option {
write_diagnostic(ctx, span);
}
}
#[test]
fn test() {
use crate::tester::Tester;
let pass = vec![
"export const foo = 'foo'; export const bar = 'bar';",
"export const foo = 'foo'; export function bar() {};",
"export const foo = 'foo';",
"const foo = 'foo'; export { foo };",
"let foo, bar; export { foo, bar }",
"export const { foo, bar } = item;",
"export const { foo, bar: baz } = item;",
"export const { foo: { bar, baz } } = item;",
"let item; export const foo = item; export { item };",
"export * from './foo';",
"export const { foo } = { foo: 'bar' };",
"export const { foo: { bar } } = { foo: { bar: 'baz' } };",
"export { a, b } from 'foo.js'",
"import * as foo from './foo';",
"import foo from './foo';",
"import {default as foo} from './foo';",
"export type UserId = number;",
];
let fail = vec![
"export default function bar() {};",
"export const foo = 'foo';\nexport default bar;",
"export default class Bar {};",
"export default function() {};",
"export default class {};",
"let foo; export { foo as default }",
// "export default from \"foo.js\"",
];
Tester::new(NoDefaultExport::NAME, pass, fail)
.with_import_plugin(true)
.change_rule_path("index.ts")
.test_and_snapshot();
}

View file

@ -0,0 +1,40 @@
---
source: crates/oxc_linter/src/tester.rs
expression: no_default_export
---
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:1:8]
1 │ export default function bar() {};
· ───────
╰────
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:2:8]
1 │ export const foo = 'foo';
2 │ export default bar;
· ───────
╰────
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:1:8]
1 │ export default class Bar {};
· ───────
╰────
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:1:8]
1 │ export default function() {};
· ───────
╰────
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:1:8]
1 │ export default class {};
· ───────
╰────
⚠ eslint-plugin-import(no-default-export): Prefer named exports
╭─[index.ts:1:26]
1 │ let foo; export { foo as default }
· ───────
╰────