Skip to content

Commit

Permalink
feat(biome_js_analyzer): implement noImplicitAnyLet
Browse files Browse the repository at this point in the history
  • Loading branch information
b4s36t4 committed Sep 23, 2023
1 parent 9408601 commit 28a6349
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 30 deletions.
1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ define_categories! {
"lint/nursery/noFallthroughSwitchClause": "https://biomejs.dev/linter/rules/no-fallthrough-switch-clause",
"lint/nursery/noGlobalIsFinite": "https://biomejs.dev/linter/rules/no-global-is-finite",
"lint/nursery/noGlobalIsNan": "https://biomejs.dev/linter/rules/no-global-is-nan",
"lint/nursery/noImplicitAnyLet": "https://biomejs.dev/lint/rules/no-implicit-any-let",
"lint/nursery/noMisleadingInstantiator": "https://biomejs.dev/linter/rules/no-misleading-instantiator",
"lint/nursery/noUselessElse": "https://biomejs.dev/lint/rules/no-useless-else",
"lint/nursery/noVoid": "https://biomejs.dev/linter/rules/no-void",
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_js_analyze/src/analyzers/nursery.rs

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic};
use biome_console::markup;
use biome_js_syntax::{JsFileSource, JsVariableDeclaration, JsVariableDeclarator};

declare_rule! {
/// Restrict use of implicit any type in Typescript.
///
/// Typescript variable declaration without any `type` or `initialization` can cause issue later in the code.
///
///
///
/// Source: https://www.typescriptlang.org/tsconfig#noImplicitAny
///
/// ## Examples
///
/// ### Invalid
///
/// ```ts,expect_diagnostic
/// var a;
/// a = 2;
/// let b;
/// b = 1
/// ```
///
/// ## Valid
///
/// ```ts
/// var a = 1;
/// let a:number;
/// var b: number
/// var b =10;
/// ```
///
pub(crate) NoImplicitAnyLet {
version: "next",
name: "noImplicitAnyLet",
recommended: true,
}
}

impl Rule for NoImplicitAnyLet {
type Query = Ast<JsVariableDeclaration>;
type State = JsVariableDeclarator;
type Signals = Option<Self::State>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let source_type = ctx.source_type::<JsFileSource>().language();
let is_ts_source = source_type.is_typescript();
let node = ctx.query();
let is_declaration = source_type.is_definition_file();

if node.is_const() || is_declaration || !is_ts_source {
return None;
}

for declarator in node.declarators() {
let variable = declarator.ok()?;
let is_initialized = variable.initializer().is_some();
let is_type_annotated = variable.variable_annotation().is_some();
if !is_initialized && !is_type_annotated {
return Some(variable);
}
}

None
}

fn diagnostic(_: &RuleContext<Self>, node: &Self::State) -> Option<RuleDiagnostic> {
let variable = node
.id()
.ok()?
.as_any_js_binding()?
.as_js_identifier_binding()?
.name_token()
.ok()?;
Some(
RuleDiagnostic::new(
rule_category!(),
variable.text_range(),
markup! {
"Variable " <Emphasis>{variable.text()}</Emphasis> " has implicitly " <Emphasis>"any"</Emphasis> " type"
},
)
.note(markup! {
"Declare type or initialize the variable with some value"
}),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
let someVar1;
someVar1 = '123';
someVar1 = 123;


var someVar1;
someVar1 = '123';
someVar1 = 123;


function ex() {
let b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: invalid.ts
---
# Input
```js
let someVar1;
someVar1 = '123';
someVar1 = 123;


var someVar1;
someVar1 = '123';
someVar1 = 123;


function ex() {
let b;
}
```

# Diagnostics
```
invalid.ts:1:5 lint/nursery/noImplicitAnyLet ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Variable someVar1 has implicitly any type
> 1 │ let someVar1;
│ ^^^^^^^^
2 │ someVar1 = '123';
3 │ someVar1 = 123;
i Declare type or initialize the variable with some value
```

```
invalid.ts:6:5 lint/nursery/noImplicitAnyLet ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Variable someVar1 has implicitly any type
> 6 │ var someVar1;
│ ^^^^^^^^
7 │ someVar1 = '123';
8 │ someVar1 = 123;
i Declare type or initialize the variable with some value
```

```
invalid.ts:12:9 lint/nursery/noImplicitAnyLet ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Variable b has implicitly any type
11 │ function ex() {
> 12 │ let b;
│ ^
13 │ }
i Declare type or initialize the variable with some value
```


Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* should not generate diagnostics */

let a: number;
let b = 1
var c : string;
var d = "abn"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: valid.ts
---
# Input
```js
/* should not generate diagnostics */

let a: number;
let b = 1
var c : string;
var d = "abn"

```


Loading

0 comments on commit 28a6349

Please sign in to comment.