Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(linter/import) change the rule path to index.ts and add snapshot in export rule #2732

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
157 changes: 85 additions & 72 deletions crates/oxc_linter/src/rules/import/export.rs
Expand Up @@ -44,9 +44,6 @@ impl Rule for Export {
let module_record = ctx.semantic().module_record();
let named_export = &module_record.exported_bindings;
let mut duplicated_named_export = FxHashMap::default();
if module_record.star_export_entries.is_empty() {
return;
}
for export_entry in &module_record.star_export_entries {
let Some(module_request) = &export_entry.module_request else {
continue;
Expand Down Expand Up @@ -79,6 +76,22 @@ impl Rule for Export {
for (span, name) in duplicated_named_export {
ctx.diagnostic(ExportDiagnostic::MultipleNamedExport(span, name));
}

for name_span in &module_record.exported_bindings_duplicated {
let name = name_span.name().clone();
if let Some(span) = module_record.exported_bindings.get(&name) {
ctx.diagnostic(ExportDiagnostic::MultipleNamedExport(*span, name.clone()));
}
ctx.diagnostic(ExportDiagnostic::MultipleNamedExport(name_span.span(), name));
}
if !module_record.export_default_duplicated.is_empty() {
if let Some(span) = module_record.export_default {
ctx.diagnostic(ExportDiagnostic::MultipleNamedExport(span, "default".into()));
}
}
for span in &module_record.export_default_duplicated {
ctx.diagnostic(ExportDiagnostic::MultipleNamedExport(*span, "default".into()));
}
}
}

Expand Down Expand Up @@ -140,12 +153,12 @@ fn test() {
export * as A from './named-export-collision/a';
export * as B from './named-export-collision/b';
"),
// ("
// export default function foo(param: string): boolean;
// export default function foo(param: string, param1: number): boolean;
// export default function foo(param: string, param1?: number): boolean {
// return param && param1;
// }
("
export default function foo(param: string): boolean;
export default function foo(param: string, param1: number): boolean;
export default function foo(param: string, param1?: number): boolean {
return param && param1;
}
// "),
// Typescript
("
Expand All @@ -156,15 +169,15 @@ fn test() {
export const Foo = 1;
export interface Foo {}
"),
// ("
// export function fff(a: string);
// export function fff(a: number);
// "),
// ("
// export function fff(a: string);
// export function fff(a: number);
// export function fff(a: string|number) {};
// "),
("
export function fff(a: string);
export function fff(a: number);
"),
("
export function fff(a: string);
export function fff(a: number);
export function fff(a: string|number) {};
"),
("
export const Bar = 1;
export namespace Foo {
Expand Down Expand Up @@ -203,19 +216,19 @@ fn test() {
export class Bar {}
}
"),
// ("
// export function Foo();
// export namespace Foo { }
// "),
// ("
// export function Foo(a: string);
// export namespace Foo { }
// "),
// ("
// export function Foo(a: string);
// export function Foo(a: number);
// export namespace Foo { }
// "),
("
export function Foo();
export namespace Foo { }
"),
("
export function Foo(a: string);
export namespace Foo { }
"),
("
export function Foo(a: string);
export function Foo(a: number);
export namespace Foo { }
"),
("
export enum Foo { }
export namespace Foo { }
Expand All @@ -225,24 +238,24 @@ fn test() {
export * as A from './named-export-collision/a';
export * as B from './named-export-collision/b';
"),
// (r#"
// declare module "a" {
// const Foo = 1;
// export {Foo as default};
// }
// declare module "b" {
// const Bar = 2;
// export {Bar as default};
// }
// "#),
// (r#"
// declare module "a" {
// const Foo = 1;
// export {Foo as default};
// }
// const Bar = 2;
// export {Bar as default};
// "#),
(r#"
declare module "a" {
const Foo = 1;
export {Foo as default};
}
declare module "b" {
const Bar = 2;
export {Bar as default};
}
"#),
(r#"
declare module "a" {
const Foo = 1;
export {Foo as default};
}
const Bar = 2;
export {Bar as default};
"#),
];
let fail = vec![
(r#"let foo; export { foo }; export * from "./export-all""#),
Expand All @@ -262,13 +275,13 @@ fn test() {
export const a = 3;
}
"),
("
declare module 'foo' {
const Foo = 1;
export default Foo;
export default Foo;
}
"),
// ("
// declare module 'foo' {
// const Foo = 1;
// export default Foo;
// export default Foo;
// }
// "),
("
export namespace Foo {
export namespace Bar {
Expand Down Expand Up @@ -301,25 +314,25 @@ fn test() {
export class Foo { }
export namespace Foo { }
"),
("
export function Foo();
export class Foo { }
export namespace Foo { }
"),
("
export const Foo = 'bar';
export function Foo();
export namespace Foo { }
"),
// ("
// export function Foo();
// export class Foo { }
// export namespace Foo { }
// "),
// ("
// export const Foo = 'bar';
// export function Foo();
// export namespace Foo { }
// "),
// ("
// export const Foo = 'bar';
// export namespace Foo { }
// "),
(r#"
declare module "a" {
const Foo = 1;
export {Foo as default};
}
// declare module "a" {
// const Foo = 1;
// export {Foo as default};
// }
const Bar = 2;
export {Bar as default};
const Baz = 3;
Expand All @@ -329,8 +342,8 @@ fn test() {

Tester::new(Export::NAME, pass, fail)
.with_import_plugin(true)
.change_rule_path("index.js")
.test();
.change_rule_path("index.ts")
.test_and_snapshot();
}

{
Expand Down
115 changes: 115 additions & 0 deletions crates/oxc_linter/src/snapshots/export.snap
@@ -0,0 +1,115 @@
---
source: crates/oxc_linter/src/tester.rs
expression: export
---
⚠ eslint-plugin-import(export): Multiple exports of name 'foo'.
╭─[index.ts:1:19]
1 │ let foo; export { foo }; export * from "./export-all"
· ───
╰────

⚠ eslint-plugin-import(export): Multiple exports of name 'foo'.
╭─[index.ts:1:26]
1 │ let foo; export { foo as "foo" }; export * from "./export-all"
· ─────
╰────

× Identifier `Foo` has already been declared
╭─[index.ts:2:29]
1 │
2 │ export type Foo = string;
· ─┬─
· ╰── `Foo` has already been declared here
3 │ export type Foo = number;
· ─┬─
· ╰── It can not be redeclared here
4 │
╰────

× Identifier `a` has already been declared
╭─[index.ts:4:30]
3 │ export namespace Foo {
4 │ export const a = 2;
· ┬
· ╰── `a` has already been declared here
5 │ export const a = 3;
· ┬
· ╰── It can not be redeclared here
6 │ }
╰────

× Identifier `Foo` has already been declared
╭─[index.ts:4:38]
3 │ export namespace Bar {
4 │ export const Foo = 1;
· ─┬─
· ╰── `Foo` has already been declared here
5 │ export const Foo = 2;
· ─┬─
· ╰── It can not be redeclared here
6 │ }
╰────

× Identifier `Bar` has already been declared
╭─[index.ts:8:38]
7 │ export namespace Baz {
8 │ export const Bar = 3;
· ─┬─
· ╰── `Bar` has already been declared here
9 │ export const Bar = 4;
· ─┬─
· ╰── It can not be redeclared here
10 │ }
╰────

× Identifier `Foo` has already been declared
╭─[index.ts:2:30]
1 │
2 │ export class Foo { }
· ─┬─
· ╰── `Foo` has already been declared here
3 │ export class Foo { }
· ─┬─
· ╰── It can not be redeclared here
4 │ export namespace Foo { }
╰────

× Identifier `Foo` has already been declared
╭─[index.ts:2:29]
1 │
2 │ export enum Foo { }
· ─┬─
· ╰── `Foo` has already been declared here
3 │ export class Foo { }
· ─┬─
· ╰── It can not be redeclared here
4 │ export namespace Foo { }
╰────

× Identifier `Foo` has already been declared
╭─[index.ts:2:30]
1 │
2 │ export const Foo = 'bar';
· ─┬─
· ╰── `Foo` has already been declared here
3 │ export class Foo { }
· ─┬─
· ╰── It can not be redeclared here
4 │ export namespace Foo { }
╰────

⚠ eslint-plugin-import(export): Multiple exports of name 'default'.
╭─[index.ts:9:32]
8 │ const Baz = 3;
9 │ export {Baz as default};
· ───────
10 │
╰────

⚠ eslint-plugin-import(export): Multiple exports of name 'default'.
╭─[index.ts:7:32]
6 │ const Bar = 2;
7 │ export {Bar as default};
· ───────
8 │ const Baz = 3;
╰────