diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 1bec971e6..15bc9373a 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -10,11 +10,14 @@ mod import { pub mod default; pub mod export; pub mod named; + pub mod namespace; pub mod no_amd; pub mod no_cycle; + pub mod no_deprecated; pub mod no_named_as_default; pub mod no_named_as_default_member; pub mod no_self_import; + pub mod no_unused_modules; } mod deepscan { @@ -545,13 +548,16 @@ oxc_macros::declare_all_lint_rules! { react_perf::jsx_no_new_function_as_prop, react_perf::jsx_no_new_object_as_prop, import::default, - import::no_named_as_default_member, - import::no_named_as_default, - import::named, - import::no_cycle, - import::no_self_import, - import::no_amd, import::export, + import::named, + import::namespace, + import::no_amd, + import::no_cycle, + import::no_deprecated, + import::no_named_as_default, + import::no_named_as_default_member, + import::no_self_import, + import::no_unused_modules, jsx_a11y::alt_text, jsx_a11y::anchor_has_content, jsx_a11y::anchor_is_valid, diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs new file mode 100644 index 000000000..338c66507 --- /dev/null +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -0,0 +1,156 @@ +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::{Atom, Span}; + +use crate::{context::LintContext, rule::Rule}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-import(namespace): ")] +#[diagnostic(severity(warning), help(""))] +struct NamespaceDiagnostic(Atom, #[label] pub Span); + +/// +#[derive(Debug, Default, Clone)] +pub struct Namespace; + +declare_oxc_lint!( + /// ### What it does + /// TODO + Namespace, + nursery +); + +impl Rule for Namespace { + fn run_once(&self, _ctx: &LintContext<'_>) {} +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + r#"import "./malformed.js""#, + // r#"import * as foo from './empty-folder';"#, + // r#"import * as names from "./named-exports"; console.log((names.b).c);"#, + // r#"import * as names from "./named-exports"; console.log(names.a);"#, + // r#"import * as names from "./re-export-names"; console.log(names.foo);"#, + // r#"import * as elements from './jsx';"#, + // r#"import * as foo from "./jsx/re-export.js"; + // console.log(foo.jsxFoo);"#, + // r#"import * as foo from "./jsx/bar/index.js"; + // console.log(foo.Baz1); + // console.log(foo.Baz2); + // console.log(foo.Qux1); + // console.log(foo.Qux2);"#, + // r#"import * as foo from './common';"#, + // r#"import * as names from "./named-exports"; const { a } = names"#, + // r#"import * as names from "./named-exports"; const { d: c } = names"#, + // r#"import * as names from "./named-exports"; + // const { c } = foo, + // { length } = "names", + // alt = names;"#, + // r#"import * as names from "./named-exports"; const { ExportedClass: { length } } = names"#, + // r#"import * as names from "./named-exports"; function b(names) { const { c } = names }"#, + // r#"import * as names from "./named-exports"; function b() { let names = null; const { c } = names }"#, + // r#"import * as names from "./named-exports"; const x = function names() { const { c } = names }"#, + // r#"export * as names from "./named-exports""#, + // r#"export defport, * as names from "./named-exports""#, + // r#"export * as names from "./does-not-exist""#, + // r#"import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Users)"#, + // r#"function x() { console.log((names.b).c); } import * as names from "./named-exports";"#, + // r#"import * as names from './default-export';"#, + // r#"import * as names from './default-export'; console.log(names.default)"#, + // r#"export * as names from "./default-export""#, + // r#"export defport, * as names from "./default-export""#, + // r#"import * as names from './named-exports'; console.log(names['a']);"#, + // r#"import * as names from './named-exports'; const {a, b, ...rest} = names;"#, + // r#"import * as names from './named-exports'; const {a, b, ...rest} = names;"#, + // r#"import * as ns from './re-export-common'; const {foo} = ns;"#, + // r#"import * as Names from "./named-exports"; const Foo = "#, + // r#"import * as foo from "./typescript-declare-nested" + // foo.bar.MyFunction()"#, + // r#"import { foobar } from "./typescript-declare-interface""#, + // r#"export * from "typescript/lib/typescript.d""#, + // r#"export = function name() {}"#, + // r#"for (let { foo, bar } of baz) {}"#, + // r#"for (let [ foo, bar ] of baz) {}"#, + // r#"const { x, y } = bar"#, + // r#"const { x, y, ...z } = bar"#, + // r#"let x; export { x }"#, + // r#"let x; export { x as y }"#, + // r#"export const x = null"#, + // r#"export var x = null"#, + // r#"export let x = null"#, + // r#"export default x"#, + // r#"export default class x {}"#, + // r#"import json from "./data.json""#, + // r#"import foo from "./foobar.json";"#, + // r#"import foo from "./foobar";"#, + // r#"import { foo } from "./issue-370-commonjs-namespace/bar""#, + // r#"export * from "./issue-370-commonjs-namespace/bar""#, + // r#"import * as a from "./commonjs-namespace/a"; a.b"#, + // r#"import { foo } from "./ignore.invalid.extension""#, + // r#"import * as color from './color'; + // export const getBackgroundFromColor = (color) => color.bg; + // export const getExampleColor = () => color.example"#, + // r#"import * as middle from './middle'; + + // console.log(middle.myName);"#, + // r#"import * as names from './default-export-string';"#, + // r#"import * as names from './default-export-string'; console.log(names.default)"#, + // r#"import * as names from './default-export-namespace-string';"#, + // r#"import * as names from './default-export-namespace-string'; console.log(names.default)"#, + // r#"import { "b" as b } from "./deep/a"; console.log(b.c.d.e)"#, + // r#"import { "b" as b } from "./deep/a"; var {c:{d:{e}}} = b"#, + // r#"import * as a from "./deep/a"; console.log(a.b.c.d.e)"#, + // r#"import { b } from "./deep/a"; console.log(b.c.d.e)"#, + // r#"import * as a from "./deep/a"; console.log(a.b.c.d.e.f)"#, + // r#"import * as a from "./deep/a"; var {b:{c:{d:{e}}}} = a"#, + // r#"import { b } from "./deep/a"; var {c:{d:{e}}} = b"#, + // r#"import * as a from "./deep-es7/a"; console.log(a.b.c.d.e)"#, + // r#"import { b } from "./deep-es7/a"; console.log(b.c.d.e)"#, + // r#"import * as a from "./deep-es7/a"; console.log(a.b.c.d.e.f)"#, + // r#"import * as a from "./deep-es7/a"; var {b:{c:{d:{e}}}} = a"#, + // r#"import { b } from "./deep-es7/a"; var {c:{d:{e}}} = b"#, + ]; + + let fail = vec![ + // r#"import * as names from './named-exports'; console.log(names.c)"#, + // r#"import * as names from './named-exports'; console.log(names['a']);"#, + // r#"import * as foo from './bar'; foo.foo = 'y';"#, + // r#"import * as foo from './bar'; foo.x = 'y';"#, + // r#"import * as names from "./named-exports"; const { c } = names"#, + // r#"import * as names from "./named-exports"; function b() { const { c } = names }"#, + // r#"import * as names from "./named-exports"; const { c: d } = names"#, + // r#"import * as names from "./named-exports"; const { c: { d } } = names"#, + // r#"import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Foo)"#, + // r#"import * as namespace from './malformed.js';"#, + // r#"import b from './deep/default'; console.log(b.e)"#, + // r#"console.log(names.c); import * as names from './named-exports';"#, + // r#"function x() { console.log(names.c) } import * as names from './named-exports';"#, + // r#"import * as ree from "./re-export"; console.log(ree.default)"#, + // r#"import * as Names from "./named-exports"; const Foo = "#, + // r#"import { "b" as b } from "./deep/a"; console.log(b.e)"#, + // r#"import { "b" as b } from "./deep/a"; console.log(b.c.e)"#, + // r#"import * as a from "./deep/a"; console.log(a.b.e)"#, + // r#"import { b } from "./deep/a"; console.log(b.e)"#, + // r#"import * as a from "./deep/a"; console.log(a.b.c.e)"#, + // r#"import { b } from "./deep/a"; console.log(b.c.e)"#, + // r#"import * as a from "./deep/a"; var {b:{ e }} = a"#, + // r#"import * as a from "./deep/a"; var {b:{c:{ e }}} = a"#, + // r#"import * as a from "./deep-es7/a"; console.log(a.b.e)"#, + // r#"import { b } from "./deep-es7/a"; console.log(b.e)"#, + // r#"import * as a from "./deep-es7/a"; console.log(a.b.c.e)"#, + // r#"import { b } from "./deep-es7/a"; console.log(b.c.e)"#, + // r#"import * as a from "./deep-es7/a"; var {b:{ e }} = a"#, + // r#"import * as a from "./deep-es7/a"; var {b:{c:{ e }}} = a"#, + ]; + + Tester::new(Namespace::NAME, pass, fail) + .change_rule_path("index.js") + .with_import_plugin(true) + .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/rules/import/no_deprecated.rs b/crates/oxc_linter/src/rules/import/no_deprecated.rs new file mode 100644 index 000000000..fc22d2e94 --- /dev/null +++ b/crates/oxc_linter/src/rules/import/no_deprecated.rs @@ -0,0 +1,42 @@ +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::{Atom, Span}; + +use crate::{context::LintContext, rule::Rule}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-import(namespace): ")] +#[diagnostic(severity(warning), help(""))] +struct NoDeprecatedDiagnostic(Atom, #[label] pub Span); + +/// +#[derive(Debug, Default, Clone)] +pub struct NoDeprecated; + +declare_oxc_lint!( + /// ### What it does + /// TODO + NoDeprecated, + nursery +); + +impl Rule for NoDeprecated { + fn run_once(&self, _ctx: &LintContext<'_>) {} +} + +#[test] +fn test() { + // use crate::tester::Tester; + + // let pass = vec![]; + + // let fail = vec![]; + + // Tester::new(NoDeprecated::NAME, pass, fail) + // .change_rule_path("index.js") + // .with_import_plugin(true) + // .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/rules/import/no_unused_modules.rs b/crates/oxc_linter/src/rules/import/no_unused_modules.rs new file mode 100644 index 000000000..d558a430e --- /dev/null +++ b/crates/oxc_linter/src/rules/import/no_unused_modules.rs @@ -0,0 +1,42 @@ +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::{Atom, Span}; + +use crate::{context::LintContext, rule::Rule}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-import(namespace): ")] +#[diagnostic(severity(warning), help(""))] +struct NoUnusedModulesDiagnostic(Atom, #[label] pub Span); + +/// +#[derive(Debug, Default, Clone)] +pub struct NoUnusedModules; + +declare_oxc_lint!( + /// ### What it does + /// TODO + NoUnusedModules, + nursery +); + +impl Rule for NoUnusedModules { + fn run_once(&self, _ctx: &LintContext<'_>) {} +} + +#[test] +fn test() { + // use crate::tester::Tester; + + // let pass = vec![]; + + // let fail = vec![]; + + // Tester::new(NoUnusedModules::NAME, pass, fail) + // .change_rule_path("index.js") + // .with_import_plugin(true) + // .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/namespace.snap b/crates/oxc_linter/src/snapshots/namespace.snap new file mode 100644 index 000000000..b52f169a8 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/namespace.snap @@ -0,0 +1,5 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: namespace +--- +