Skip to content

Commit

Permalink
feat(lint): Add lint for usage of node globals (with autofix) (#25048)
Browse files Browse the repository at this point in the history
From upgrading `deno_lint`.

Previously if you had a node project that used a bunch of node globals
(`process.env`, etc), you would have to fix the errors by hand. This PR
includes a new lint that detects usages of node globals (`process`,
`setImmediate`, `Buffer`, etc.) and provides an autofix to import the
correct value. For instance:

```ts
// main.ts
const _foo = process.env.FOO;
```

`deno lint` gives you

```ts
error[no-node-globals]: NodeJS globals are not available in Deno
 --> /home/foo.ts:1:14
  |
1 | const _foo = process.env.FOO;
  |              ^^^^^^^
  = hint: Add `import process from "node:process";`

  docs: https://lint.deno.land/rules/no-node-globals


Found 1 problem (1 fixable via --fix)
Checked 1 file
```
And `deno lint --fix` adds the import for you:

```ts
// main.ts
import process from "node:process";
const _foo = process.env.FOO;
```
  • Loading branch information
nathanwhit authored Aug 15, 2024
1 parent e8d57cd commit 5ec3c5c
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 5 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"]
deno_doc = { version = "0.146.0", features = ["html", "syntect"] }
deno_emit = "=0.44.0"
deno_graph = { version = "=0.81.2" }
deno_lint = { version = "=0.62.0", features = ["docs"] }
deno_lint = { version = "=0.63.1", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "=0.21.4"
deno_package_json.workspace = true
Expand Down
14 changes: 12 additions & 2 deletions cli/tools/lint/linter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use std::collections::HashSet;
use std::path::Path;

use deno_ast::MediaType;
Expand Down Expand Up @@ -225,14 +226,23 @@ fn apply_lint_fixes(
if quick_fixes.is_empty() {
return None;
}

let mut import_fixes = HashSet::new();
// remove any overlapping text changes, we'll circle
// back for another pass to fix the remaining
quick_fixes.sort_by_key(|change| change.range.start);
for i in (1..quick_fixes.len()).rev() {
let cur = &quick_fixes[i];
let previous = &quick_fixes[i - 1];
let is_overlapping = cur.range.start < previous.range.end;
if is_overlapping {
// hack: deduplicate import fixes to avoid creating errors
if previous.new_text.trim_start().starts_with("import ") {
import_fixes.insert(previous.new_text.trim().to_string());
}
let is_overlapping = cur.range.start <= previous.range.end;
if is_overlapping
|| (cur.new_text.trim_start().starts_with("import ")
&& import_fixes.contains(cur.new_text.trim()))
{
quick_fixes.remove(i);
}
}
Expand Down
23 changes: 23 additions & 0 deletions tests/specs/lint/node_globals_no_duplicate_imports/__test__.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"tempDir": true,
"steps": [
{
"args": "run main.ts",
"output": "error.out",
"exitCode": 1
},
{
"args": "lint main.ts",
"output": "lint.out",
"exitCode": 1
},
{
"args": "lint --fix main.ts",
"output": "Checked 1 file\n"
},
{
"args": "run --allow-env main.ts",
"output": ""
}
]
}
4 changes: 4 additions & 0 deletions tests/specs/lint/node_globals_no_duplicate_imports/error.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: Uncaught (in promise) ReferenceError: process is not defined
const _foo = process.env.FOO;
^
at [WILDCARD]main.ts:3:14
22 changes: 22 additions & 0 deletions tests/specs/lint/node_globals_no_duplicate_imports/lint.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[no-node-globals]: NodeJS globals are not available in Deno
--> [WILDCARD]main.ts:3:14
|
3 | const _foo = process.env.FOO;
| ^^^^^^^
= hint: Add `import process from "node:process";`

docs: https://lint.deno.land/rules/no-node-globals


error[no-node-globals]: NodeJS globals are not available in Deno
--> [WILDCARD]main.ts:7:14
|
7 | const _bar = process.env.BAR;
| ^^^^^^^
= hint: Add `import process from "node:process";`

docs: https://lint.deno.land/rules/no-node-globals


Found 2 problems (2 fixable via --fix)
Checked 1 file
7 changes: 7 additions & 0 deletions tests/specs/lint/node_globals_no_duplicate_imports/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {} from "node:console";

const _foo = process.env.FOO;

import {} from "node:assert";

const _bar = process.env.BAR;

0 comments on commit 5ec3c5c

Please sign in to comment.