docs(linter): improve docs for eslint-plugin-import rules (#6131)

Related to #6050
This commit is contained in:
dalaoshu 2024-09-28 20:45:02 +08:00 committed by GitHub
parent 375bebea06
commit 14ba263506
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 292 additions and 63 deletions

View file

@ -18,10 +18,19 @@ pub struct Default;
declare_oxc_lint!(
/// ### What it does
///
/// If a default import is requested, this rule will report if there is no default export in the imported module.
/// If a default import is requested, this rule will report if there is no
/// default export in the imported module.
///
/// ### Example
/// ### Why is this bad?
///
/// Using a default import when there is no default export can lead to
/// confusion and runtime errors. It can make the code harder to understand
/// and maintain, as it may suggest that a module has a default export
/// when it does not, leading to unexpected behavior.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// // ./bar.js
/// export function bar() { return null }
@ -29,6 +38,15 @@ declare_oxc_lint!(
/// // ./foo.js
/// import bar from './bar' // no default export found in ./bar
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // ./bar.js
/// export default function bar() { return null }
///
/// // ./foo.js
/// import { bar } from './bar' // correct usage of named import
/// ```
Default,
correctness
);

View file

@ -8,7 +8,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use crate::{context::LintContext, rule::Rule};
fn no_named_export(span: Span, module_name: &str) -> OxcDiagnostic {
fn no_named_export(module_name: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("No named exports found in module '{module_name}'"))
.with_label(span)
}
@ -19,13 +19,29 @@ pub struct Export;
declare_oxc_lint!(
/// ### What it does
///
/// Reports funny business with exports, like repeated exports of names or defaults.
///
/// ### Example
/// ### Why is this bad?
///
/// Having multiple exports of the same name can lead to ambiguity and confusion
/// in the codebase. It makes it difficult to track which export is being used
/// and can result in runtime errors if the wrong export is referenced.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// let foo;
/// export { foo }; // Multiple exports of name 'foo'.
/// export * from "./export-all" // export-all.js also export foo
/// export * from "./export-all"; // Conflicts if export-all.js also exports foo
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// let foo;
/// export { foo as foo1 }; // Renamed export to avoid conflict
/// export * from "./export-all"; // No conflict if export-all.js also exports foo
/// ```
Export,
nursery
@ -58,7 +74,7 @@ impl Rule for Export {
);
if export_names.is_empty() {
ctx.diagnostic(no_named_export(module_request.span(), module_request.name()));
ctx.diagnostic(no_named_export(module_request.name(), module_request.span()));
} else {
all_export_names.insert(star_export_entry.span, export_names);
}

View file

@ -9,11 +9,11 @@ use crate::{context::LintContext, rule::Rule};
fn max_dependencies_diagnostic<S: Into<Cow<'static, str>>>(
message: S,
span1: Span,
span: Span,
) -> OxcDiagnostic {
OxcDiagnostic::warn(message)
.with_help("Reduce the number of dependencies in this file")
.with_label(span1)
.with_label(span)
}
/// <https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/max-dependencies.md>
@ -47,19 +47,26 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// This is a useful rule because a module with too many dependencies is a code smell, and
/// usually indicates the module is doing too much and/or should be broken up into smaller
/// modules.
/// This is a useful rule because a module with too many dependencies is a code smell,
/// and usually indicates the module is doing too much and/or should be broken up into
/// smaller modules.
///
/// ### Example
/// ### Examples
///
/// Given `{"max": 2}`
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// import a from './a';
/// import b from './b';
/// import c from './c';
/// import c from './c'; // Too many dependencies: 3 (max: 2)
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// import a from './a';
/// import b from './b'; // Allowed: 2 dependencies (max: 2)
/// ```
MaxDependencies,
pedantic,
);

View file

@ -35,15 +35,33 @@ declare_oxc_lint!(
///
/// ### Why is this bad?
///
/// ### Example
/// Importing or exporting names that do not exist in the referenced module
/// can lead to runtime errors and confusion. It may suggest that certain
/// functionality is available when it is not, making the code harder to
/// maintain and understand. This rule helps ensure that your code
/// accurately reflects the available exports, improving reliability.
///
/// ### Examples
///
/// Given
/// ```js
/// // ./foo.js
/// export const foo = "I'm so foo"
/// export const foo = "I'm so foo";
/// ```
///
/// The following is considered valid:
/// Examples of **incorrect** code for this rule:
/// ```js
/// // ./baz.js
/// import { notFoo } from './foo'
///
/// // ES7 proposal
/// export { notFoo as defNotBar } from './foo'
///
/// // will follow 'jsnext:main', if available
/// import { dontCreateStore } from 'redux'
/// ```
///
/// Examples of **correct** code for this rule:
/// ```js
/// // ./bar.js
/// import { foo } from './foo'
@ -55,19 +73,6 @@ declare_oxc_lint!(
/// // (import/ignore setting)
/// import { SomeNonsenseThatDoesntExist } from 'react'
/// ```
///
/// ...and the following are reported:
///
/// ```js
/// // ./baz.js
/// import { notFoo } from './foo'
///
/// // ES7 proposal
/// export { notFoo as defNotBar } from './foo'
///
/// // will follow 'jsnext:main', if available
/// import { dontCreateStore } from 'redux'
/// ```
Named,
correctness
);

View file

@ -50,12 +50,54 @@ pub struct Namespace {
declare_oxc_lint!(
/// ### What it does
///
/// Enforces names exist at the time they are dereferenced, when imported as
/// a full namespace (i.e. `import * as foo from './foo'; foo.bar();` will
/// report if bar is not exported by `./foo.`). Will report at the import
/// declaration if there are no exported names found. Also, will report for
/// computed references (i.e. `foo["bar"]()`). Reports on assignment to a
/// member of an imported namespace.
///
/// ### Why is this bad?
///
/// Dereferencing a name that does not exist can lead to runtime errors and
/// unexpected behavior in your code. It makes the code less reliable and
/// harder to maintain, as it may not be clear which names are valid. This
/// rule helps ensure that all referenced names are defined, improving
/// the clarity and robustness of your code.
///
/// ### Examples
///
/// Given
/// ```javascript
/// // ./foo.js
/// export const bar = "I'm bar";
/// ```
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// // ./qux.js
/// import * as foo from './foo';
/// foo.notExported(); // Error: notExported is not exported
///
/// // Assignment to a member of an imported namespace
/// foo.bar = "new value"; // Error: bar cannot be reassigned
///
/// // Computed reference to a non-existent export
/// const method = "notExported";
/// foo[method](); // Error: notExported does not exist
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // ./baz.js
/// import * as foo from './foo';
/// console.log(foo.bar); // Valid: bar is exported
///
/// // Computed reference
/// const method = "bar";
/// foo[method](); // Valid: method refers to an exported function
/// ```
Namespace,
correctness
);

View file

@ -20,14 +20,20 @@ pub struct NoAmd;
declare_oxc_lint!(
/// ### What it does
///
/// Forbid AMD `require` and `define` calls.
/// Forbids the use of AMD `require` and `define` calls.
///
/// ### Why is this bad?
///
/// AMD (Asynchronous Module Definition) is an older module format
/// that is less common in modern JavaScript development, especially
/// with the widespread use of ES6 modules and CommonJS in Node.js.
/// AMD introduces unnecessary complexity and is often considered outdated.
/// This rule enforces the use of more modern module systems to improve
/// maintainability and consistency across the codebase.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
///
/// ```javascript
/// require([a, b], function() {} );
/// ```

View file

@ -55,20 +55,37 @@ declare_oxc_lint!(
/// ### Why is this bad?
///
/// Dependency cycles lead to confusing architectures where bugs become hard to find.
///
/// It is common to import an `undefined` value that is caused by a cyclic dependency.
///
/// ### Example
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// // dep-b.js
/// import './dep-a.js'
/// export function b() { /* ... */ }
/// ```
///
/// ```javascript
/// // dep-a.js
/// import { b } from './dep-b.js' // reported: Dependency cycle detected.
/// export function a() { /* ... */ }
/// ```
///
/// In this example, `dep-a.js` and `dep-b.js` import each other, creating a circular
/// dependency, which is problematic.
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // dep-b.js
/// export function b() { /* ... */ }
/// ```
/// ```javascript
/// // dep-a.js
/// import { b } from './dep-b.js' // no circular dependency
/// export function a() { /* ... */ }
/// ```
///
/// In this corrected version, `dep-b.js` no longer imports `dep-a.js`, breaking the cycle.
NoCycle,
restriction
);

View file

@ -14,7 +14,15 @@ 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.
/// Forbids a module from having default exports. This helps your editor
/// provide better auto-import functionality, as named exports offer more
/// explicit and predictable imports compared to default exports.
///
/// ### Why is this bad?
///
/// Default exports can lead to confusion, as the name of the imported value
/// can vary based on how it's imported. This can make refactoring and
/// auto-imports less reliable.
///
/// ### Examples
///
@ -31,7 +39,6 @@ declare_oxc_lint!(
/// export const foo = 'foo';
/// export const bar = 'bar';
/// ```
///
NoDefaultExport,
restriction
);
@ -48,6 +55,7 @@ impl Rule for NoDefaultExport {
fn write_diagnostic(ctx: &LintContext<'_>, span: Span) {
ctx.diagnostic(no_default_export_diagnostic(span));
}
fn write_diagnostic_optional(ctx: &LintContext<'_>, span_option: Option<Span>) {
if let Some(span) = span_option {
write_diagnostic(ctx, span);
@ -77,6 +85,7 @@ fn test() {
"import {default as foo} from './foo';",
"export type UserId = number;",
];
let fail = vec![
"export default function bar() {};",
"export const foo = 'foo';\nexport default bar;",

View file

@ -2,7 +2,10 @@ use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_macros::declare_oxc_lint;
// use oxc_span::{CompactStr, Span};
use crate::{context::{LintContext, ContextHost}, rule::Rule};
use crate::{
context::{ContextHost, LintContext},
rule::Rule,
};
// #[derive(Debug, Error, Diagnostic)]
// #[error("")]
@ -16,7 +19,20 @@ pub struct NoDeprecated;
declare_oxc_lint!(
/// ### What it does
///
/// Reports use of a deprecated name, as indicated by a JSDoc block with a @deprecated tag or TomDoc Deprecated: comment.
/// Reports use of a deprecated name, as indicated by a JSDoc block with
/// a @deprecated tag or TomDoc Deprecated: comment.
///
/// ### Why is this bad?
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// ```
NoDeprecated,
nursery
);

View file

@ -14,7 +14,27 @@ pub struct NoDuplicates {
declare_oxc_lint!(
/// ### What it does
///
/// Reports if a resolved path is imported more than once.
/// Reports if a resolved path is imported more than once in the same module.
/// This helps avoid unnecessary duplicate imports and keeps the code clean.
///
/// ### Why is this bad?
///
/// Importing the same module multiple times can lead to redundancy and
/// unnecessary complexity. It also affects maintainability, as it might
/// confuse developers and result in inconsistent usage of imports across the code.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// import { foo } from './module';
/// import { bar } from './module';
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// import { foo, bar } from './module';
/// ```
NoDuplicates,
suspicious
);

View file

@ -19,12 +19,15 @@ pub struct NoDynamicRequire {
declare_oxc_lint!(
/// ### What it does
///
/// Forbid imports which use an expression for the module argument.
/// Forbids imports that use an expression for the module argument. This includes
/// dynamically resolved paths in `require` or `import` statements.
///
/// ### Why is this bad?
///
/// Import statements which use an expression resolved at runtime makes it to find where the
/// import comes from and some static code analysis tools might not be able to resolve them.
/// Using expressions that are resolved at runtime in import statements makes it
/// difficult to determine where the module is being imported from. This can complicate
/// code navigation and hinder static analysis tools, which rely on predictable module paths
/// for linting, bundling, and other optimizations.
///
/// ### Examples
///

View file

@ -23,23 +23,37 @@ declare_oxc_lint!(
/// ### What it does
///
/// Reports use of an exported name as the locally imported name of a default export.
/// This happens when an imported default export is assigned a name that conflicts
/// with a named export from the same module.
///
/// ### Example
/// ### Why is this bad?
///
/// Using a named export's identifier for a default export can cause confusion
/// and errors in understanding which value is being imported. It also reduces
/// code clarity, making it harder for other developers to understand the intended
/// imports.
///
///
/// ### Examples
///
/// Given
/// ```javascript
/// // foo.js
/// export default 'foo';
/// export const bar = 'baz';
/// ```
/// Valid:
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// import foo from './foo.js';
/// ```
/// Invalid:
/// ```javascript
/// // using exported name 'bar' as identifier for default export.
/// // Invalid: using exported name 'bar' as the identifier for default export.
/// import bar from './foo.js';
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // Valid: correctly importing default export with a non-conflicting name.
/// import foo from './foo.js';
/// ```
NoNamedAsDefault,
suspicious
);

View file

@ -29,18 +29,37 @@ pub struct NoNamedAsDefaultMember;
declare_oxc_lint!(
/// ### What it does
///
/// Reports use of an exported name as a property on the default export.
/// Reports the use of an exported name (named export) as a property on the
/// default export. This occurs when trying to access a named export through
/// the default export, which is incorrect.
///
/// ### Example
/// ### Why is this bad?
///
/// Accessing a named export via the default export is incorrect and will not
/// work as expected. Named exports should be imported directly, while default
/// exports are accessed without properties. This mistake can lead to runtime
/// errors or undefined behavior.
///
/// ### Examples
///
/// Given
/// ```javascript
/// // ./bar.js
/// export function bar() { return null }
/// export default () => { return 1 }
/// ```
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// // ./foo.js
/// import bar from './bar'
/// const bar = foo.bar // trying to access named export via default
/// import foo from './bar'
/// const bar = foo.bar; // Incorrect: trying to access named export via default
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // ./foo.js
/// import { bar } from './bar'; // Correct: accessing named export directly
/// ```
NoNamedAsDefaultMember,
suspicious

View file

@ -14,14 +14,27 @@ pub struct NoSelfImport;
declare_oxc_lint!(
/// ### What it does
///
/// Forbid a module from importing itself. This can sometimes happen during refactoring.
/// Forbids a module from importing itself. This can sometimes happen accidentally,
/// especially during refactoring.
///
/// ### Example
/// ### Why is this bad?
///
/// Importing a module into itself creates a circular dependency, which can cause
/// runtime issues, including infinite loops, unresolved imports, or `undefined` values.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// // foo.js
/// import foo from './foo.js'
/// const foo = require('./foo')
/// import foo from './foo.js'; // Incorrect: module imports itself
/// const foo = require('./foo'); // Incorrect: module imports itself
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// // foo.js
/// import bar from './bar.js'; // Correct: module imports another module
/// ```
NoSelfImport,
suspicious

View file

@ -1,11 +1,13 @@
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{context::{LintContext, ContextHost}, rule::Rule};
use crate::{
context::{ContextHost, LintContext},
rule::Rule,
};
fn no_exports_found(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("No exports found")
.with_label(span)
OxcDiagnostic::warn("No exports found").with_label(span)
}
/// <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unused-modules.md>
@ -23,6 +25,17 @@ declare_oxc_lint!(
/// * individual exports not being statically imported or requireed from other modules in the same project
/// * dynamic imports are supported if argument is a literal string
///
/// ### Why is this bad?
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// ```
NoUnusedModules,
nursery
);

View file

@ -21,14 +21,16 @@ pub struct NoWebpackLoaderSyntax;
declare_oxc_lint!(
/// ### What it does
///
/// Forbid Webpack loader syntax in imports.
/// Forbids using Webpack loader syntax directly in import or require statements.
///
/// ### Why is this bad?
///
/// This loader syntax is non-standard, so it couples the code to Webpack. The recommended way to
/// specify Webpack loader configuration is in a [Webpack configuration file](https://webpack.js.org/concepts/loaders/#configuration).
///
/// ### Example
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```javascript
/// import myModule from 'my-loader!my-module';
/// import theme from 'style!css!./theme.css';
@ -36,6 +38,15 @@ declare_oxc_lint!(
/// var myModule = require('my-loader!./my-module');
/// var theme = require('style!css!./theme.css');
/// ```
///
/// Examples of **correct** code for this rule:
/// ```javascript
/// import myModule from './my-module';
/// import theme from './theme.css';
///
/// var myModule = require('./my-module');
/// var theme = require('./theme.css');
/// ```
NoWebpackLoaderSyntax,
restriction,
);