fix(linter): rule no-restricted-imports support missing options (#8076)

> The regex property is used to specify the regex patterns for
restricting modules.
> Note: regex cannot be used in combination with group.

_https://eslint.org/docs/latest/rules/no-restricted-imports#regex_

> This option allows you to use regex patterns to restrict import names:


_https://eslint.org/docs/latest/rules/no-restricted-imports#importnamepattern_

> 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.


_https://eslint.org/docs/latest/rules/no-restricted-imports#allowimportnamepattern_

Needed to install `regress` to support JS Sntax like Lookaheads and
Lookbehinds

Next Goals:
- https://github.com/oxc-project/oxc/pull/7894
- Improve spans
- Error for wrong configurations
- update documentation
- Output messages like
[eslint](https://github.com/eslint/eslint/blob/main/lib/rules/no-restricted-imports.js#L140-L184)
This commit is contained in:
Alexander S. 2025-01-18 04:50:36 +01:00 committed by GitHub
parent 8c6e0a6fa3
commit 41f2070895
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 659 additions and 367 deletions

View file

@ -2,9 +2,11 @@ use ignore::gitignore::GitignoreBuilder;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{CompactStr, Span};
use regex::Regex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde::{de::Error, Deserialize, Deserializer};
use serde_json::Value;
use std::borrow::Cow;
use crate::{
context::LintContext,
@ -48,21 +50,51 @@ pub struct NoRestrictedImportsConfig {
#[serde(rename_all = "camelCase")]
struct RestrictedPath {
name: CompactStr,
import_names: Option<Box<[CompactStr]>>,
allow_import_names: Option<Box<[CompactStr]>>,
import_names: Option<Vec<CompactStr>>,
allow_import_names: Option<Vec<CompactStr>>,
message: Option<CompactStr>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct RestrictedPattern {
group: Vec<CompactStr>,
import_names: Option<Box<[CompactStr]>>,
allow_import_names: Option<Box<[CompactStr]>>,
group: Option<Vec<CompactStr>>,
regex: Option<SerdeRegexWrapper<Regex>>,
import_names: Option<Vec<CompactStr>>,
import_name_pattern: Option<SerdeRegexWrapper<Regex>>,
allow_import_names: Option<Vec<CompactStr>>,
allow_import_name_pattern: Option<SerdeRegexWrapper<Regex>>,
case_sensitive: Option<bool>,
message: Option<CompactStr>,
}
/// A wrapper type which implements `Serialize` and `Deserialize` for
/// types involving `Regex`
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub struct SerdeRegexWrapper<T>(pub T);
impl std::ops::Deref for SerdeRegexWrapper<Regex> {
type Target = Regex;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'de> Deserialize<'de> for SerdeRegexWrapper<Regex> {
fn deserialize<D>(d: D) -> Result<SerdeRegexWrapper<Regex>, D::Error>
where
D: Deserializer<'de>,
{
let s = <Cow<str>>::deserialize(d)?;
match s.parse() {
Ok(regex) => Ok(SerdeRegexWrapper(regex)),
Err(err) => Err(D::Error::custom(err)),
}
}
}
#[derive(Debug)]
enum GlobResult {
Found,
@ -148,8 +180,31 @@ fn add_configuration_patterns_from_object(
add_configuration_patterns_from_string(patterns, module_name);
}
Value::Object(_) => {
if let Ok(path) = serde_json::from_value::<RestrictedPattern>(path_value.clone()) {
patterns.push(path);
if let Ok(pattern) = serde_json::from_value::<RestrictedPattern>(path_value.clone())
{
if pattern.group.is_some() && pattern.regex.is_some() {
// ToDo: not allowed
}
// allowImportNames cannot be used in combination with importNames, importNamePattern or allowImportNamePattern.
if pattern.allow_import_names.is_some()
&& (pattern.import_names.is_some()
|| pattern.import_name_pattern.is_some()
|| pattern.allow_import_name_pattern.is_some())
{
// ToDo: not allowed
}
// allowImportNamePattern cannot be used in combination with importNames, importNamePattern or allowImportNames.
if pattern.allow_import_name_pattern.is_some()
&& (pattern.import_names.is_some()
|| pattern.import_name_pattern.is_some()
|| pattern.allow_import_names.is_some())
{
// ToDo: not allowed
}
patterns.push(pattern);
}
}
_ => (),
@ -159,9 +214,12 @@ fn add_configuration_patterns_from_object(
fn add_configuration_patterns_from_string(paths: &mut Vec<RestrictedPattern>, module_name: &str) {
paths.push(RestrictedPattern {
group: vec![CompactStr::new(module_name)],
group: Some(vec![CompactStr::new(module_name)]),
regex: None,
import_names: None,
import_name_pattern: None,
allow_import_names: None,
allow_import_name_pattern: None,
case_sensitive: None,
message: None,
});
@ -193,8 +251,13 @@ fn is_name_span_allowed_in_pattern(name: &CompactStr, pattern: &RestrictedPatter
return true;
}
// when no importNames option is provided, no import in general is allowed
if pattern.import_names.as_ref().is_none() {
// fast check if this name is allowed
if pattern.get_allow_import_name_pattern_result(name) {
return true;
}
// when no importNames or importNamePattern option is provided, no import in general is allowed
if pattern.import_names.as_ref().is_none() && pattern.import_name_pattern.is_none() {
return false;
}
@ -203,6 +266,11 @@ fn is_name_span_allowed_in_pattern(name: &CompactStr, pattern: &RestrictedPatter
return false;
}
// the name is found is the importNamePattern
if pattern.get_import_name_pattern_result(name) {
return false;
}
// we allow it
true
}
@ -246,12 +314,16 @@ impl RestrictedPattern {
}
}
fn get_gitignore_glob_result(&self, name: &NameSpan) -> GlobResult {
fn get_group_glob_result(&self, name: &NameSpan) -> GlobResult {
let Some(groups) = &self.group else {
return GlobResult::None;
};
let mut builder = GitignoreBuilder::new("");
// returns always OK, will be fixed in the next version
let _ = builder.case_insensitive(!self.case_sensitive.unwrap_or(false));
for group in &self.group {
for group in groups {
// returns always OK
let _ = builder.add_line(None, group.as_str());
}
@ -274,6 +346,18 @@ impl RestrictedPattern {
GlobResult::Found
}
fn get_regex_result(&self, name: &NameSpan) -> bool {
self.regex.as_ref().is_some_and(|regex| regex.is_match(name.name()))
}
fn get_import_name_pattern_result(&self, name: &CompactStr) -> bool {
self.import_name_pattern.as_ref().is_some_and(|regex| regex.is_match(name))
}
fn get_allow_import_name_pattern_result(&self, name: &CompactStr) -> bool {
self.allow_import_name_pattern.as_ref().is_some_and(|regex| regex.is_match(name))
}
}
impl Rule for NoRestrictedImports {
@ -397,7 +481,7 @@ impl NoRestrictedImports {
continue;
}
match pattern.get_gitignore_glob_result(&entry.module_request) {
match pattern.get_group_glob_result(&entry.module_request) {
GlobResult::Whitelist => {
whitelist_found = true;
break;
@ -409,6 +493,12 @@ impl NoRestrictedImports {
}
GlobResult::None => (),
};
if pattern.get_regex_result(&entry.module_request) {
let span = entry.module_request.span();
no_restricted_imports_diagnostic(ctx, span, pattern.message.clone(), source);
}
}
if !whitelist_found && !found_errors.is_empty() {
@ -450,7 +540,7 @@ impl NoRestrictedImports {
continue;
};
match pattern.get_gitignore_glob_result(module_request) {
match pattern.get_group_glob_result(module_request) {
GlobResult::Whitelist => {
whitelist_found = true;
break;
@ -462,6 +552,12 @@ impl NoRestrictedImports {
}
GlobResult::None => (),
};
if pattern.get_regex_result(module_request) {
let span = module_request.span();
no_restricted_imports_diagnostic(ctx, span, pattern.message.clone(), source);
}
}
if !whitelist_found && !found_errors.is_empty() {
@ -710,99 +806,99 @@ fn test() {
}]
}])),
),
// (
// "import Foo from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import Foo from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import Foo from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Bar as Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Bar as Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import Foo, { Baz as Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^(Foo|Bar)"
// }]
// }])),
// ),
// (
// "import Foo, { Baz as Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Bar"
// }]
// }])),
// ),
// (
// "export { Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export { Bar as Foo } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
(
"import Foo from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import Foo from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import Foo from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Bar as Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Bar as Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import Foo, { Baz as Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^(Foo|Bar)"
}]
}])),
),
(
"import Foo, { Baz as Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Bar"
}]
}])),
),
(
"export { Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"export { Bar as Foo } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
r#"import { AllowedObject } from "foo";"#,
Some(serde_json::json!([{
@ -849,21 +945,21 @@ fn test() {
}]
}])),
),
// (
// "import { Foo } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "allowImportNamePattern": "^Foo"
// }]
// }])),
// ),
(
r#"import withPatterns from "foo/bar";"#,
Some(
serde_json::json!([{ "patterns": [{ "regex": "foo/(?!bar)", "message": "foo is forbidden, use bar instead" }] }]),
),
"import { Foo } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"allowImportNamePattern": "^Foo"
}]
}])),
),
// (
// r#"import withPatterns from "foo/bar";"#,
// Some(
// serde_json::json!([{ "patterns": [{ "regex": "foo/(?!bar)", "message": "foo is forbidden, use bar instead" }] }]),
// ),
// ),
(
"import withPatternsCaseSensitive from 'foo';",
Some(serde_json::json!([{
@ -1475,214 +1571,214 @@ fn test() {
}]
}])),
),
// (
// "import { Foo } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Foo as Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import Foo, { Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^(Foo|Bar)"
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { FooBar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import Foo, { Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo|^Bar"
// }]
// }])),
// ),
// (
// "import { Foo, Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^(Foo|Bar)"
// }]
// }])),
// ),
// (
// "import * as Foo from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import * as All from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import * as AllWithCustomMessage from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo",
// "message": "Import from @/utils instead."
// }]
// }])),
// ),
// (
// "import * as AllWithCustomMessage from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo",
// "message": "Import from @/utils instead."
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo", "Bar"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Bar"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Bar"
// }]
// }])),
// ),
// (
// "import { Foo, Bar } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Foo"],
// "group": ["**/my/relative-module"],
// "importNamePattern": "^Bar"
// }]
// }])),
// ),
// (
// "export { Foo } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export { Foo as Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export { Foo } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "importNames": ["Bar"],
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export * from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export { Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "allowImportNamePattern": "^Foo"
// }]
// }])),
// ),
// (
// "export { Bar } from 'foo';",
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo"],
// "allowImportNamePattern": "^Foo",
// "message": r#"Only imports that match the pattern "/^Foo/u" are allowed to be imported from "foo"."#
// }]
// }])),
// ),
(
"import { Foo } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Foo as Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import Foo, { Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^(Foo|Bar)"
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { FooBar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import Foo, { Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo|^Bar"
}]
}])),
),
(
"import { Foo, Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^(Foo|Bar)"
}]
}])),
),
(
"import * as Foo from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import * as All from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import * as AllWithCustomMessage from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo",
"message": "Import from @/utils instead."
}]
}])),
),
(
"import * as AllWithCustomMessage from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo",
"message": "Import from @/utils instead."
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo", "Bar"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Bar"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Bar"
}]
}])),
),
(
"import { Foo, Bar } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Foo"],
"group": ["**/my/relative-module"],
"importNamePattern": "^Bar"
}]
}])),
),
(
"export { Foo } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"export { Foo as Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"export { Foo } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"importNames": ["Bar"],
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"export * from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"importNamePattern": "^Foo"
}]
}])),
),
(
"export { Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"allowImportNamePattern": "^Foo"
}]
}])),
),
(
"export { Bar } from 'foo';",
Some(serde_json::json!([{
"patterns": [{
"group": ["foo"],
"allowImportNamePattern": "^Foo",
"message": r#"Only imports that match the pattern "/^Foo/u" are allowed to be imported from "foo"."#
}]
}])),
),
(
r#"import { AllowedObject, DisallowedObject } from "foo";"#,
Some(serde_json::json!([{
@ -1759,50 +1855,50 @@ fn test() {
}]
}])),
),
// (
// r#"import * as AllowedObject from "foo/bar";"#,
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo/*"],
// "allowImportNamePattern": "^Allow"
// }]
// }])),
// ),
// (
// r#"import * as AllowedObject from "foo/bar";"#,
// Some(serde_json::json!([{
// "patterns": [{
// "group": ["foo/*"],
// "allowImportNamePattern": "^Allow",
// "message": r#"Only import names starting with "Allow" are allowed to be imported from "foo"."#
// }]
// }])),
// ),
(
r#"import * as AllowedObject from "foo/bar";"#,
Some(serde_json::json!([{
"patterns": [{
"group": ["foo/*"],
"allowImportNamePattern": "^Allow"
}]
}])),
),
(
r#"import * as AllowedObject from "foo/bar";"#,
Some(serde_json::json!([{
"patterns": [{
"group": ["foo/*"],
"allowImportNamePattern": "^Allow",
"message": r#"Only import names starting with "Allow" are allowed to be imported from "foo"."#
}]
}])),
),
// (
// r#"import withPatterns from "foo/baz";"#,
// Some(
// serde_json::json!([{ "patterns": [{ "regex": "foo/(?!bar)", "message": "foo is forbidden, use bar instead" }] }]),
// ),
// ),
// (
// "import withPatternsCaseSensitive from 'FOO';",
// Some(serde_json::json!([{
// "patterns": [{
// "regex": "FOO",
// "message": "foo is forbidden, use bar instead",
// "caseSensitive": true
// }]
// }])),
// ),
// (
// "import { Foo } from '../../my/relative-module';",
// Some(serde_json::json!([{
// "patterns": [{
// "regex": "my/relative-module",
// "importNamePattern": "^Foo"
// }]
// }])),
// ),
(
"import withPatternsCaseSensitive from 'FOO';",
Some(serde_json::json!([{
"patterns": [{
"regex": "FOO",
"message": "foo is forbidden, use bar instead",
"caseSensitive": true
}]
}])),
),
(
"import { Foo } from '../../my/relative-module';",
Some(serde_json::json!([{
"patterns": [{
"regex": "my/relative-module",
"importNamePattern": "^Foo"
}]
}])),
),
(
"import withPatternsCaseSensitive from 'foo';",
Some(serde_json::json!([{

View file

@ -597,6 +597,174 @@ snapshot_kind: text
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:28]
1 │ import { Foo as Bar } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import Foo, { Bar } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:24]
1 │ import { FooBar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import Foo, { Bar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import { Foo, Bar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import { Foo, Bar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:22]
1 │ import * as Foo from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:22]
1 │ import * as All from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): Import from @/utils instead.
╭─[no_restricted_imports.tsx:1:39]
1 │ import * as AllWithCustomMessage from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): Import from @/utils instead.
╭─[no_restricted_imports.tsx:1:39]
1 │ import * as AllWithCustomMessage from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import { Foo, Bar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:26]
1 │ import { Foo, Bar } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ export { Foo } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:28]
1 │ export { Foo as Bar } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ export { Foo } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:15]
1 │ export * from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ export { Bar } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): Only imports that match the pattern "/^Foo/u" are allowed to be imported from "foo".
╭─[no_restricted_imports.tsx:1:21]
1 │ export { Bar } from 'foo';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:49]
1 │ import { AllowedObject, DisallowedObject } from "foo";
@ -653,6 +821,34 @@ snapshot_kind: text
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): 'foo/bar' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:32]
1 │ import * as AllowedObject from "foo/bar";
· ─────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): Only import names starting with "Allow" are allowed to be imported from "foo".
╭─[no_restricted_imports.tsx:1:32]
1 │ import * as AllowedObject from "foo/bar";
· ─────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): foo is forbidden, use bar instead
╭─[no_restricted_imports.tsx:1:39]
1 │ import withPatternsCaseSensitive from 'FOO';
· ─────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): '../../my/relative-module' import is restricted from being used.
╭─[no_restricted_imports.tsx:1:21]
1 │ import { Foo } from '../../my/relative-module';
· ──────────────────────────
╰────
help: Remove the import statement.
⚠ eslint(no-restricted-imports): foo is forbidden, use bar instead
╭─[no_restricted_imports.tsx:1:39]
1 │ import withPatternsCaseSensitive from 'foo';