Denoでlintする! Deno@v1.1.0で実装されたdeno lintコマンドの紹介

## はじめに

Denoの[v1.1.0](https://github.com/denoland/deno/releases/tag/v1.1.0)がリリースされました。
本記事では、その新機能である`deno lint`コマンドについて紹介します。

## `deno lint`コマンドについて

- linterがDenoに組み込まれています。そのため、Denoがインストールされていればすぐに使用できます。
- Rustで記述されているためとても速いです。
  - [deno_lint](https://github.com/denoland/deno_lint/tree/v0.1.10)の`README.md`にベンチマークの結果が記載されています。詳しくはそちらを参照ください。
- 現時点では、eslintほどの機能や拡張性はありません

## 使い方

`deno lint`コマンドはまだ[unstable](https://deno.land/manual@v1.1.0/runtime/stability)という扱いなので、使用する際は`--unstable`フラグが必要です。

#### 指定したファイルに対してlintを実行する

```shell
$ deno lint --unstable ./application.ts ./mod.ts
```

#### カレントディレクトリ配下から再帰的にファイルを探してlintを実行する

```shell
$ deno lint --unstable
```

#### 指定したディレクトリ配下から再帰的にファイルを探してlintを実行する

```shell
$ deno lint --unstable ./tests
```

## 出力例

ルール違反があると、以下のように出力されます。

```shell
(no-explicit-any) `any` type is not allowed
  evaluate(expression: string): Promise<any>;
                                        ~~~
    at ./application.ts:5:40

(no-explicit-any) `any` type is not allowed
  exposeFunction(name: string, binding: (...args: any[]) => any): Promise<void>;
                                                  ~~~
    at ./application.ts:7:50

(no-explicit-any) `any` type is not allowed
  exposeFunction(name: string, binding: (...args: any[]) => any): Promise<void>;
                                                            ~~~
    at ./application.ts:7:60

(no-explicit-any) `any` type is not allowed
    evaluate(expression: string): Promise<any> {
                                          ~~~
    at ./application.ts:18:42

(no-explicit-any) `any` type is not allowed
    exposeFunction(name: string, binding: (...args: any[]) => any) {
                                                    ~~~
    at ./application.ts:24:52

(no-explicit-any) `any` type is not allowed
    exposeFunction(name: string, binding: (...args: any[]) => any) {
                                                              ~~~
    at ./application.ts:24:62

Found 6 problems
```

## ルール

eslint同様、いくつかのルールが定義されています。

#### 例

|ルール|説明|
|:---:|:---:|
|`no-explicit-any`|明示的な`any`の使用を許可しない|
|`constructor-super`|サブクラスの`constructor`は`super()`を呼ばなければならない|
|`no-delete-var`|変数の`delete`を許可しない|
|`no-this-alias`|`this`の他の変数への割当(`const self = this;`)を許可しない|
|`prefer-namespace-keyword`|`module`キーワードではなく`namespace`キーワードの使用を推奨する|

#### ルールを一覧表示する

以下のコマンドを実行すると、サポートされているルールを一覧表示できます。

```shell
$ deno lint --unstable --rules
```

## ディレクティブ

linterの挙動を制御するためのディレクティブがいくつか提供されています。

#### `deno-lint-ignore-file`

このディレクティブをファイルの先頭付近で宣言しておくと、そのファイルはlint対象から除外されます。
`import`宣言や関数定義よりも前に指定する必要があります。

```typescript
// deno-lint-ignore-file
```

#### `deno-lint-ignore`

eslintの`eslint-disable-next-line`に相当します。
特定のルールを無効化したいときに使います。

```typescript
export interface Evaluator {
  // deno-lint-ignore no-explicit-any
  evaluate(expression: string): Promise<any>;
}
```

## `deno lint`でできないこと

以下のような機能はまだサポートされていません。

- 設定ファイル
- 適用するルールのカスタマイズ

## おわりに

`deno lint`コマンドが利用しているリンターについては、[deno_lintリポジトリ](https://github.com/denoland/deno_lint)にて開発が行われています。
このリポジトリでは、毎日のように活発にコミットが行われており、これからもどんどん拡張されていくと思われます。

興味があれば、ぜひ試してみてください。

## 参考

- [公式マニュアル](https://deno.land/manual/tools/linter)
- [deno_lint](https://github.com/denoland/deno_lint)