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): noRestrictedImports add patterns option #4302

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
- Add [noImgElement](https://biomejs.dev/linter/rules/no-img-element/). Contributed by @kaioduarte
- Add [guardForIn](https://biomejs.dev/linter/rules/guard-for-in/). Contributed by @fireairforce
- Add [noUselessStringRaw](https://github.com/biomejs/biome/pull/4263). Contributed by @fireairforce
- Add an option `patterns` to [noRestrictedImports](https://biomejs.dev/linter/rules/no-restricted-imports/). Contributed by @nekocode

#### Bug Fixes

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/biome_js_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ biome_suppression = { workspace = true }
biome_unicode_table = { workspace = true }
bitvec = "1.0.1"
enumflags2 = { workspace = true }
ignore = { workspace = true }
natord = { workspace = true }
regex = { workspace = true }
roaring = "0.10.6"
Expand Down
43 changes: 38 additions & 5 deletions crates/biome_js_analyze/src/lint/nursery/no_restricted_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use biome_console::markup;
use biome_deserialize_macros::Deserializable;
use biome_js_syntax::{inner_string_text, AnyJsImportLike};
use biome_rowan::TextRange;
use ignore::gitignore::GitignoreBuilder;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};

Expand All @@ -19,7 +20,11 @@ declare_lint_rule! {
/// "paths": {
/// "lodash": "Using lodash is not encouraged",
/// "underscore": "Using underscore is not encouraged"
/// }
/// },
/// "patterns": [{
/// "group": ["lodash/*", "!lodash/get"],
/// "message": "Using specific lodash modules is not encouraged"
/// }]
/// }
/// }
/// }
Expand All @@ -44,6 +49,20 @@ pub struct RestrictedImportsOptions {
/// A list of names that should trigger the rule
#[serde(skip_serializing_if = "FxHashMap::is_empty")]
paths: FxHashMap<Box<str>, Box<str>>,

/// A list of gitignore-style patterns that should trigger the rule
#[serde(skip_serializing_if = "<[_]>::is_empty")]
patterns: Box<[RestrictedImportsPattern]>,
}

#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct RestrictedImportsPattern {
#[serde(skip_serializing_if = "<[_]>::is_empty")]
group: Box<[Box<str>]>,

message: String,
}

impl Rule for NoRestrictedImports {
Expand All @@ -60,10 +79,24 @@ impl Rule for NoRestrictedImports {
let module_name = node.module_name_token()?;
let inner_text = inner_string_text(&module_name);

ctx.options()
.paths
.get(inner_text.text())
.map(|message| (module_name.text_trimmed_range(), message.to_string()))
// Check against exact paths
if let Some(message) = ctx.options().paths.get(inner_text.text()) {
return Some((module_name.text_trimmed_range(), message.to_string()));
}

// Check against gitignore-style patterns
for pattern in ctx.options().patterns.iter() {
let mut builder = GitignoreBuilder::new("");
for path in pattern.group.iter() {
builder.add_line(None, path).unwrap();
}
let gitignore = builder.build().unwrap();
if gitignore.matched(inner_text.text(), false).is_ignore() {
return Some((module_name.text_trimmed_range(), pattern.message.clone()));
}
}

None
}

fn diagnostic(_ctx: &RuleContext<Self>, (span, text): &Self::State) -> Option<RuleDiagnostic> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import eslint from 'eslint';
const l = require('lodash');
const s = require('lodash/sortBy');
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ expression: invalid.js
```jsx
import eslint from 'eslint';
const l = require('lodash');
const s = require('lodash/sortBy');

```

Expand All @@ -18,7 +19,7 @@ invalid.js:1:20 lint/nursery/noRestrictedImports ━━━━━━━━━━
> 1 │ import eslint from 'eslint';
│ ^^^^^^^^
2 │ const l = require('lodash');
3 │
3 │ const s = require('lodash/sortBy');


```
Expand All @@ -31,9 +32,22 @@ invalid.js:2:19 lint/nursery/noRestrictedImports ━━━━━━━━━━
1 │ import eslint from 'eslint';
> 2 │ const l = require('lodash');
│ ^^^^^^^^
3 │
3 │ const s = require('lodash/sortBy');
4 │


```

```
invalid.js:3:19 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

! It's not recommended to use specific lodash functions

1 │ import eslint from 'eslint';
2 │ const l = require('lodash');
> 3 │ const s = require('lodash/sortBy');
│ ^^^^^^^^^^^^^^^
4 │


```
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"paths": {
"eslint": "Importing Eslint is forbidden",
"lodash": "It's not recommended to use lodash"
}
},
"patterns": [{
"group": ["lodash/*", "!lodash/get"],
"message": "It's not recommended to use specific lodash functions"
}]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
const path = require('lodash');
const path = require('lodash/get');
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ expression: valid.js
# Input
```jsx
const path = require('lodash');
const path = require('lodash/get');

```


Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
"options": {
"paths": {
"node:fs": "Importing from node:fs is forbidden"
}
},
"patterns": [{
"group": ["lodash/*", "!lodash/get"],
"message": "It's not recommended to use lodash"
}]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
declare module "node:fs" {}
declare module "node:fs" {}
declare module "lodash/get" {}
declare module "lodash/sortBy" {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ expression: valid.ts
# Input
```ts
declare module "node:fs" {}
declare module "lodash/get" {}
declare module "lodash/sortBy" {}
```
8 changes: 8 additions & 0 deletions packages/@biomejs/backend-jsonrpc/src/workspace.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions packages/@biomejs/biome/configuration_schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.