Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 291 additions & 6 deletions crates/oxc_linter/src/rules/eslint/no_restricted_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,28 +234,313 @@ declare_oxc_lint!(
/// It applies to static imports only, not dynamic ones.
///
/// ### Why is this bad?
///Some imports might not make sense in a particular environment. For example, Node.js’ fs module would not make sense in an environment that didn’t have a file system.
/// Some imports might not make sense in a particular environment.
/// For example, Node.js’ fs module would not make sense in an environment that didn’t have a file system.
///
/// Some modules provide similar or identical functionality, think lodash and underscore. Your project may have standardized on a module. You want to make sure that the other alternatives are not being used as this would unnecessarily bloat the project and provide a higher maintenance cost of two dependencies when one would suffice.
/// Some modules provide similar or identical functionality, think lodash and underscore. Your project may have standardized on a module.
/// You want to make sure that the other alternatives are not being used as this would unnecessarily bloat the project
/// and provide a higher maintenance cost of two dependencies when one would suffice.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```js
/// /*eslint no-restricted-imports: ["error", "disallowed-import"]"*/
///
/// import foo from 'disallowed-import';
/// export * from 'disallowed-import';
/// ```
///
/// Examples of **correct** code for this rule:
/// ```js
/// /*eslint no-restricted-imports: ["error", "fs"]*/
///
/// import crypto from 'crypto';
/// export * from "bar";
/// ```
///
/// ### Options
///
/// You may also specify a custom message for a particular module using the `name` and `message` properties inside an object,
/// where the value of the name is the `name` of the module and message property contains the custom message.
/// The custom message will be displayed as a help text for the user.
///
/// Examples of **incorrect** code for this rule:
/// ```js
/// /*eslint no-restricted-imports: ["error", {
/// "name": "disallowed-import",
/// "message": "Please use 'allowed-import' instead"
/// "name": "disallowed-import",
/// "message": "Please use 'allowed-import' instead"
/// }]*/
///
/// import foo from 'disallowed-import';
/// ```
///
/// #### paths
///
/// This is an object option whose value is an array containing the names of the modules you want to restrict.
///
/// ```json
/// {"rules: {"no-restricted-imports": ["error", { "paths": ["import1", "import2"] }]}}
/// ``
///
/// Examples of **incorrect** code for `paths`:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { "paths": ["cluster"] }]*/
///
/// import cluster from 'cluster';
/// ```
///
/// Custom messages for a particular module can also be specified in `paths` array using objects with `name` and `message`.
///
/// ```json
/// "no-restricted-imports": ["error", {
/// "paths": [{
/// "name": "import-foo",
/// "message": "Please use import-bar instead."
/// }, {
/// "name": "import-baz",
/// "message": "Please use import-quux instead."
/// }]
/// }]
/// ````
///
/// ##### importNames
///
/// This option in `paths` is an array and can be used to specify the names of certain bindings exported from a module.
/// Import names specified inside `paths` array affect the module specified in the `name` property of corresponding object,
/// so it is required to specify the `name` property first when you are using `importNames` or `message` option.
///
/// Specifying `"default"` string inside the `importNames` array will restrict the default export from being imported.
///
/// Examples of **incorrect** code for this rule:
/// ```js
/// /*eslint no-restricted-imports: ["error", { paths: [{
/// "name": "foo",
/// "importNames": ["default"]
/// }, {
/// "name": "bar",
/// "importNames": ["Baz"]
/// }]}]*/
///
/// import DisallowedObject from "foo";
/// import {Baz} from "far";
/// ```
///
/// ##### allowImportNames
///
/// This option is an array. Inverse of `importNames`, `allowImportNames` allows the imports that are specified inside this array.
/// So it restricts all imports from a module, except specified allowed ones.
///
/// Note: `allowImportNames` cannot be used in combination with `importNames`.
///
/// Examples of **incorrect** code for this rule:
/// ```js
/// /*eslint no-restricted-imports: ["error", { paths: [{
/// "name": "foo",
/// "allowImportNames": ["AllowedObject"],
/// "message": "Please use only 'AllowedObject' from 'foo'."
/// }]}]*/
///
/// import { DisallowedObject } from "foo";
/// ```
///
/// #### allowTypeImports
///
/// Whether to allow type-only imports for a path. Default: `false`.
///
/// Examples of **incorrect** code for this rule:
/// ```typescript
/// /*eslint no-restricted-imports: ["error", { paths: [{
/// "name": "foo",
/// "allowTypeImports": true
/// }]}]*/
///
/// import foo from 'import-foo';
/// export { Foo } from 'import-foo';
/// ```
///
/// Examples of **correct** code for this rule:
/// ```typescript
/// /*eslint no-restricted-imports: ["error", { paths: [{
/// "name": "foo",
/// "allowTypeImports": true
/// }]}]*/
///
/// import type foo from 'import-foo';
/// export type { Foo } from 'import-foo';
/// ```
///
/// #### patterns
///
/// This is also an object option whose value is an array.
/// This option allows you to specify multiple modules to restrict using `gitignore`-style patterns or regular expressions.
///
/// Where `paths` option takes exact import paths, `patterns` option can be used to specify the import paths with more flexibility,
/// allowing for the restriction of multiple modules within the same directory. For example:
///
/// ```json
/// "no-restricted-imports": ["error", {
/// "paths": [{
/// "name": "import-foo",
/// }]
/// }]
/// ```
/// This configuration restricts import of the `import-foo` module
/// but wouldn’t restrict the import of `import-foo/bar` or `import-foo/baz`. You can use `patterns` to restrict both:
///
/// ```json
/// "no-restricted-imports": ["error", {
/// "paths": [{
/// "name": "import-foo",
/// }],
/// "patterns": [{
/// "group": ["import-foo/ba*"],
/// }]
/// }]
/// ```
///
/// This configuration restricts imports not just from `import-foo` using path,
/// but also `import-foo/bar` and `import-foo/baz` using `patterns`.
///
/// You can also use regular expressions to restrict modules (see the `regex` option).
///
/// Examples of **incorrect** code for `patterns` option:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", {"name": "fs"}]*/
/// /*eslint no-restricted-imports: ["error", { "patterns": ["lodash/*"] }]*/
///
/// import pick from 'lodash/pick';
/// ```
///
/// Examples of **correct** code for `patterns` option:
/// ```js
/// /*eslint no-restricted-imports: ["error", { "patterns": ["crypto/*"] }]*/
///
/// import crypto from 'crypto';
/// export { foo } from "bar";
/// ```
///
/// ##### group
///
/// The `patterns` array can also include objects. The `group` property is used to specify the `gitignore`-style patterns
/// for restricting modules and the `message` property is used to specify a custom message.
///
/// Either of the `group` or `regex` properties is required when using the `patterns` option.
///
/// Examples of **incorrect** code for `group` option:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// group: ["lodash/*"],
/// message: "Please use the default import from 'lodash' instead."
/// }]}]*/
///
/// import pick from 'lodash/pick';
/// ```
///
/// ##### regex
///
/// The `regex` property is used to specify the regex patterns for restricting modules.
///
/// Note: `regex` cannot be used in combination with `group`.
///
/// **Warning**: This rule uses the [Rust-Regex](https://docs.rs/regex/latest/regex/), which supports not all features of JS-Regex,
/// like Lookahead and Lookbehinds.
///
/// Examples of **incorrect** code for `regex` option:
/// ````js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// regex: "@app/(api|enums).*",
/// }]}]*/
///
/// import Foo from '@app/api';
/// import Bar from '@app/api/bar';
/// import Baz from '@app/api/baz';
/// import Bux from '@app/api/enums/foo';
/// ```
///
/// ##### caseSensitive
///
/// This is a boolean option and sets the patterns specified in the `group` property to be case-sensitive when `true`. Default is `false`.
///
/// **Warning**: It will not apply case-sensitive checks to `regex`. `regex` uses Rust-RegEx which has its own implementation of case-sensitive.
///
/// ##### importNames
///
/// You can also specify `importNames` within objects inside the `patterns` array.
/// In this case, the specified names apply only to the associated `group` or `regex` property.
///
/// Examples of **incorrect** code for `importNames` in `patterns`:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// group: ["utils/*"],
/// importNames: ['isEmpty'],
/// message: "Use 'isEmpty' from lodash instead."
/// }]}]*/
///
/// import { isEmpty } from 'utils/collection-utils';
/// ```
///
/// ##### allowImportNames
///
/// You can also specify `allowImportNames` within objects inside the `patterns` array.
/// In this case, the specified names apply only to the associated `group` or `regex` property.
///
/// Note: `allowImportNames` cannot be used in combination with `importNames`, `importNamePattern` or `allowImportNamePattern`.
///
/// ##### importNamePattern
///
/// This option allows you to use regex patterns to restrict import names.
///
/// Examples of **incorrect** code for `importNamePattern` option:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// group: ["foo/*"],
/// importNamePattern: '^(is|has)',
/// message: "Use 'is*' and 'has*' functions from baz/bar instead"
/// }]}]*/
///
/// import { isSomething, hasSomething } from 'foo/bar';
/// ```
///
/// ##### allowImportNamePattern
///
/// This is a string option. Inverse of `importNamePattern`, this option allows imports that matches the specified regex pattern.
/// So it restricts all imports from a module, except specified allowed patterns.
///
/// Note: `allowImportNamePattern` cannot be used in combination with `importNames`, `importNamePattern` or `allowImportNames`.
///
/// ```json
/// "no-restricted-imports": ["error", {
/// "patterns": [{
/// "group": ["import-foo/*"],
/// "allowImportNamePattern": "^foo",
/// }]
/// }]
/// ```
///
/// Examples of **incorrect** code for `allowImportNamePattern` option:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// group: ["utils/*"],
/// allowImportNamePattern: '^has'
/// }]}]*/
///
/// import { isEmpty } from 'utils/collection-utils';
/// ```
///
/// Examples of **correct** code for `allowImportNamePattern` option:
///
/// ```js
/// /*eslint no-restricted-imports: ["error", { patterns: [{
/// group: ["utils/*"],
/// allowImportNamePattern: '^is'
/// }]}]*/
///
/// import { isEmpty } from 'utils/collection-utils';
/// ```
NoRestrictedImports,
eslint,
Expand Down
Loading