Skip to content

Commit d9d7bd7

Browse files
authored
feat(noUndeclaredVariables): add checkTypes option (#4471)
1 parent 3ad6da5 commit d9d7bd7

File tree

7 files changed

+171
-3
lines changed

7 files changed

+171
-3
lines changed

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,48 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
8888

8989
Contributed by @Conaclos
9090

91+
- [noUndeclaredVariables](https://biomejs.dev/linter/rules/no-undeclared-variables/) now provides the `checkTypes` option ([#3998](https://github.com/biomejs/biome/issues/3998)).
92+
93+
`noUndeclaredVariables` is inspired by the [no-undef ESLint rule](https://eslint.org/docs/latest/rules/no-undef). It reports all references that are not bound to any declarations within a module.
94+
Node.js, JavaScript and TypeScript globals are ignored.
95+
Bioem provides the `javascript.globals` option to list additional globals that should be ignored by the rule.
96+
97+
In TypeScript projects, developers often use global declaration files to declare global types.
98+
Biome is currently unable to detect these global types.
99+
This creates many false positives for `noUndeclaredVariables`.
100+
101+
TypeScript is better suited to perform this kind of check.
102+
As proof of this, TypeScript ESLint doesn't provide any rule that extends the `no-undef` ESLint rule.
103+
104+
This is why we introduce today a new option `checkTypes` which, when it is set to `false`, ignores undeclared type references.
105+
Given the following configuration...
106+
107+
```json
108+
{
109+
"linter": {
110+
"rules": {
111+
"correctness": {
112+
"noUndeclaredVariables": {
113+
"level": "error",
114+
"options": { "checkTypes": false }
115+
}
116+
}
117+
}
118+
}
119+
}
120+
```
121+
122+
... `UndeclaredType` is not reported by the rule.
123+
124+
```ts
125+
export default function(): UndeclaredType {}
126+
```
127+
128+
We plan to turn off the option by default in Biome 2.0
129+
Also, this will bring the Biome rule closer to the [no-undef ESLint rule](https://eslint.org/docs/latest/rules/no-undef).
130+
131+
Contributed by @Conaclos
132+
91133
#### Enhancements
92134

93135
- `useExportType` and `useImportType` now ignore TypeScript declaration files ([#4416](https://github.com/biomejs/biome/pull/4416)). Contributed by @Conaclos

crates/biome_js_analyze/src/lint/correctness/no_undeclared_variables.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::services::semantic::SemanticServices;
33
use biome_analyze::context::RuleContext;
44
use biome_analyze::{declare_lint_rule, Rule, RuleDiagnostic, RuleSource};
55
use biome_console::markup;
6+
use biome_deserialize_macros::Deserializable;
67
use biome_js_syntax::{
78
AnyJsFunction, JsFileSource, Language, TextRange, TsAsExpression, TsReferenceType,
89
};
@@ -13,6 +14,19 @@ declare_lint_rule! {
1314
///
1415
/// If you need to allow-list some global bindings, you can use the [`javascript.globals`](/reference/configuration/#javascriptglobals) configuration.
1516
///
17+
/// ## Options (Since v2.0.0)
18+
///
19+
/// The rule provides a `checkTypes` option that make the rule checks undeclared types.
20+
/// The option defaults to `true`.
21+
///
22+
/// ```json
23+
/// {
24+
/// "options": {
25+
/// "checkTypes": true
26+
/// }
27+
/// }
28+
/// ```
29+
///
1630
/// ## Examples
1731
///
1832
/// ### Invalid
@@ -43,7 +57,7 @@ impl Rule for NoUndeclaredVariables {
4357
type Query = SemanticServices;
4458
type State = (TextRange, Box<str>);
4559
type Signals = Box<[Self::State]>;
46-
type Options = ();
60+
type Options = UndeclaredVariablesOptions;
4761

4862
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
4963
ctx.query()
@@ -87,6 +101,10 @@ impl Rule for NoUndeclaredVariables {
87101
return None;
88102
}
89103

104+
if !ctx.options().check_types && identifier.is_only_type() {
105+
return None;
106+
}
107+
90108
let span = token.text_trimmed_range();
91109
let text = text.to_string().into_boxed_str();
92110
Some((span, text))
@@ -108,6 +126,19 @@ impl Rule for NoUndeclaredVariables {
108126
}
109127
}
110128

129+
#[derive(Clone, Debug, Deserializable, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
130+
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
131+
#[serde(default, rename_all = "camelCase")]
132+
pub struct UndeclaredVariablesOptions {
133+
/// Check undeclared types.
134+
check_types: bool,
135+
}
136+
impl Default for UndeclaredVariablesOptions {
137+
fn default() -> Self {
138+
Self { check_types: true }
139+
}
140+
}
141+
111142
fn is_global(reference_name: &str, source_type: &JsFileSource) -> bool {
112143
match source_type.language() {
113144
Language::JavaScript => is_js_global(reference_name),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"linter": {
3+
"rules": {
4+
"correctness": {
5+
"noUndeclaredVariables": {
6+
"level": "error",
7+
"options": {
8+
"checkTypes": false
9+
}
10+
}
11+
}
12+
}
13+
}
14+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function f(): UndeclaredType {}
2+
3+
export const X = UndeclaredVariable;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
source: crates/biome_js_analyze/tests/spec_tests.rs
3+
expression: ignore-types.ts
4+
snapshot_kind: text
5+
---
6+
# Input
7+
```ts
8+
export function f(): UndeclaredType {}
9+
10+
export const X = UndeclaredVariable;
11+
```
12+
13+
# Diagnostics
14+
```
15+
ignore-types.ts:3:18 lint/correctness/noUndeclaredVariables ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16+
17+
! The UndeclaredVariable variable is undeclared.
18+
19+
1 │ export function f(): UndeclaredType {}
20+
2 │
21+
> 3 │ export const X = UndeclaredVariable;
22+
│ ^^^^^^^^^^^^^^^^^^
23+
24+
i By default, Biome recognizes browser and Node.js globals.
25+
You can ignore more globals using the javascript.globals configuration.
26+
27+
28+
```

packages/@biomejs/backend-jsonrpc/src/workspace.ts

Lines changed: 20 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@biomejs/biome/configuration_schema.json

Lines changed: 32 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)