コード編集

このプラグインは、ReScript コードの記述をより生産的にする豊富な編集機能を提供します。

コード折りたたみ

Native

ブロックを折りたたんだり展開したりして、重要なコードに集中できます。

折りたたみ可能な要素

  • モジュール宣言module Name = { ... }

  • Let バインディング{ ... } を含む複数行の let

  • 型定義 — 複数行の type 宣言

  • ブロックコメント/* ... */

  • カスタムリージョン//#region ... //#endregion

カスタムリージョン

//#region//#endregion マーカーを使用してカスタムの折りたたみ可能なセクションを作成できます:

//#region Helper functions
let add = (a, b) => a + b
let multiply = (a, b) => a * b
//#endregion

コード折りたたみにより実装の詳細を隠して重要な宣言に集中でき、大きなファイルを分割せずにナビゲーション可能にします。

コードフォーマット

LSP Required

Ctrl+Alt+L(macOS では Cmd+Option+L)を押して、rescript format CLI を使用して現在のファイルをフォーマットします。

仕組み

プラグインは現在のドキュメント内容を rescript format --stdin .<ext> に stdin 経由でパイプし、フォーマットされた出力でドキュメントテキストを置き換えます。.res.resi の両方のファイルに対応しています。フォーマットは IntelliJ の AsyncDocumentFormattingService を通じて非同期で実行されるため、操作中もエディターの応答性が維持されます。

要件

ReScript コンパイラ(rescript)がプロジェクトの node_modules にインストールされている必要があります。プラグインはファイルのディレクトリからプロジェクトルートまで CLI を検索します。CLI が見つからない場合は、通知が表示されます。

エラーハンドリング

  • CLI が見つからない --- rescriptnode_modules に見つからなかったことを示す通知が表示されます

  • タイムアウト --- フォーマットに 10 秒以上かかった場合、プロセスが終了しエラー通知が表示されます

  • フォーマッターエラー --- フォーマッターがゼロ以外のコードで終了した場合(例: ファイル内の構文エラー)、stderr 出力が通知として表示されます

保存時フォーマット

保存時に ReScript ファイルを自動フォーマットするには、Settings > Tools > Actions on SaveReformat code を有効にします。

参考

コード分析 --- Format Check はフォーマットされていないファイルをハイライトし、フォーマットのクイックフィックスを提供できます。

ショートカット一つでファイル全体を公式 ReScript スタイルにフォーマットでき、手動のスペース調整を排除してチーム全体で一貫したコードスタイルを確保します。

括弧のマッチング

Native

エディターは対応する括弧のペアをハイライトします:

  • {}

  • []

  • ()

ブレースマッチングによりブロックの開始と終了を即座に確認でき、深くネストされたコードでのデリミタの不一致を防ぎます。

スマート引用符

Native

", ', または ` を入力すると、閉じ引用符が自動的に挿入されます。

自動ペアリング引用符によりキーストロークを節約し、文字列デリミタの不一致による一般的な構文エラーを防ぎます。

Smart Enter

Native

Shift+Enter を押すと、現在の文をインテリジェントに補完し、新しい行を開始します:

  • 閉じられていない括弧やブレースを閉じます

  • 不足している switch の本体ブレースを追加します

  • カーソルを適切な位置に移動します

Smart Enter は開いた構文をインテリジェントに閉じてカーソルを配置するため、デリミタを手動でバランスさせることなく次の文を入力し続けられます。

コメントの切り替え

Native

  • Ctrl+/ — 行コメントの切り替え(//

  • Ctrl+Shift+/ — ブロックコメントの切り替え(/* */

コメントデリミタを手動で入力・削除することなく、デバッグやコードの一時的な無効化のためにコメントを素早くオン・オフ切り替えできます。

ステートメントの移動

Native

トップレベル宣言を上下に移動します:

  • Alt+Shift+Up — 宣言を上に移動

  • Alt+Shift+Down — 宣言を下に移動

これにより、宣言全体(デコレーターを含む)がひとつの単位として移動されます。

カット&ペーストなしで宣言を並べ替えられます — ムーバーはデコレータを含む宣言ブロック全体を処理するため、アノテーションを置き忘れたり複数行の定義を壊すことがありません。

インテンションアクション

Native

式の上で Alt+Enter を押すと、利用可能なインテンションが表示されます:

インテンション

説明

Some(...) でラップ

式を Some() でラップ

Ok(...) でラップ

式を Ok() でラップ

Error(...) でラップ

式を Error() でラップ

@genType を追加

宣言に @genType アノテーションを追加

ドキュメントコメントの生成

宣言の上に /** */ ドキュメントコメントのスタブを挿入

パイプを関数呼び出しに変換

arr->Array.map(f)Array.map(arr, f) に変換

関数呼び出しをパイプに変換

Array.map(arr, f)arr->Array.map(f) に変換

インターフェースに公開

.res の宣言を対応する .resi インターフェースファイルに追加

インターフェースから非公開

.resi インターフェースファイルから宣言を削除

ラベル付き引数を挿入

関数呼び出しのすべてのラベル付き引数を挿入

Switch ケースの統合

同じボディを持つ switch ケースを | A | B => body に統合

ケースの分割

パターン変数をすべてのコンストラクターケースに展開

ラベル付き引数に変換

位置引数をラベル付き引数に変換

不要な括弧を削除

式を囲む冗長な括弧を削除

冗長な修飾子を削除

不要なモジュールパスの修飾子を削除

filter+map を filterMap に変換

->Array.filter(f)->Array.map(g)->Array.filterMap(...) に変換

型注釈を追加

LSP hover の情報を使用して let バインディングに明示的な型注釈を追加

->ignore を追加

式の戻り値を破棄するために ->ignore を末尾に追加

_ プレフィックスを追加

未使用変数の警告を抑制するためにアンダースコアプレフィックスを追加

冗長なブレースを削除

単一式を囲む不要な { } を削除

識別子のケースを修正

識別子のケースを修正(例: 値は小文字開始、モジュールは大文字開始)

分割代入の展開

let {a, b} = x を個別の let バインディングに展開

呼び出しを uncurried 形式に変換

f が uncurried 構文 let f = (. x) => ... で定義されている場合、f(x)f(. x) に書き換えます

モジュールをファイルに抽出

トップレベルの module M = {{ ... }} 宣言を、隣接する M.res ファイルに移動します

Intention アクションは一般的なコード変換をワンクリック操作に変えます — 手動でコードを再構成する代わりに、Alt+Enter を押して IDE に機械的な変更を任せ、ロジックに集中できます。

参考

Code Analysis では、問題を自動的に検出するインスペクションと、ワンクリックで解決できるクイックフィックスを提供しています。

Some(...) でラップ

選択した式を Some() でラップします。プレーンな値を option 型に変換する必要がある場合に便利です。

式を選択し、Alt+Enter を押して、Wrap with Some(...) を選択します。

name を選択してから:

let name = "Alice"
let greeting = getGreeting(name)
let name = "Alice"
let greeting = getGreeting(Some(name))

Ok(...) でラップ

選択した式を Ok() でラップします。result 型を使用する関数から成功値を返す場合に便利です。

value を選択してから:

let value = computeResult()
let response = processResponse(value)
let value = computeResult()
let response = processResponse(Ok(value))

Error(...) でラップ

選択した式を Error() でラップします。result 型を使用する関数からエラー値を返す場合に便利です。

2行目の message を選択してから:

let message = "Something went wrong"
let result = message
let message = "Something went wrong"
let result = Error(message)

@genType を追加

let, type, または module 宣言の上に @genType アノテーションを追加します。このアノテーションは ReScript コンパイラに宣言の TypeScript 型定義を生成するよう指示し、TypeScript コードとのシームレスな相互運用を可能にします。

このインテンションは、まだ @genType アノテーションが付与されていない宣言でのみ利用可能です。

let greet = (name: string) => `Hello, ${name}!`
@genType
let greet = (name: string) => `Hello, ${name}!`

これは型宣言やモジュール宣言にも使用できます:

type user = {
  name: string,
  age: int,
}
@genType
type user = {
  name: string,
  age: int,
}

ドキュメントコメントの生成

現在の宣言の上に /** ... */ ドキュメントコメントのスタブを挿入します。関数宣言の場合、各パラメーターに対して @param タグが自動的に生成されます。

このインテンションは、まだドキュメントコメントが付与されていない lettypemoduleexternalexception 宣言で利用可能です。

let add = (~a: int, ~b: int) => a + b
/**
 *
 * @param a
 * @param b
 */
let add = (~a: int, ~b: int) => a + b

パイプ ⇔ 関数呼び出しの変換

パイプファースト構文と通常の関数呼び出し構文を相互変換します。パイプ式または関数呼び出しにキャレットを置いて Alt+Enter を押します。

パイプから関数呼び出しへ:

// Before
arr->Array.map(x => x + 1)

// After
Array.map(arr, x => x + 1)

関数呼び出しからパイプへ:

// Before
Array.map(arr, x => x + 1)

// After
arr->Array.map(x => x + 1)

インターフェースの公開/非公開

.res 実装から直接、.resi インターフェースファイルで公開する宣言を制御します。

Publish to interface: .res ファイルの lettypemodule、または external 宣言にキャレットを置いて Alt+Enter を押し、Publish to interface を選択します。宣言のシグネチャが対応する .resi ファイルに追加されます。

Unpublish from interface: .resi ファイルに存在する宣言にキャレットを置いて Alt+Enter を押し、Unpublish from interface を選択します。対応する宣言が .resi ファイルから削除されます。

注釈

これらのインテンションには対応する .resi ファイルが必要です。必要に応じて、先に Create Interface File で生成してください。

ラベル付き引数の挿入

ラベル付き引数を持つ関数を呼び出す際、関数呼び出しの括弧内にキャレットを置いて Alt+Enter を押し、Insert labeled arguments を選択します。すべてのラベル付き引数が名前付きパラメーターとして挿入されます。

makeUser()
makeUser(~name, ~age, ~role)

Switch ケースの統合

複数の switch ケースが同じボディを持つ場合、いずれかにキャレットを置いて Alt+Enter を押し、Merge switch cases を選択します。ケースが複数のパターンを持つ単一のアームに統合されます。

switch status {
| Active => "valid"
| Pending => "valid"
| Inactive => "invalid"
}
switch status {
| Active | Pending => "valid"
| Inactive => "invalid"
}

ケースの分割

パターンマッチの変数をすべてのコンストラクターケースに展開します。switch アームの変数パターンにキャレットを置いて Alt+Enter を押し、Case split を選択します。

switch option {
| x => handle(x)
}
switch option {
| Some(value) => handle(Some(value))
| None => handle(None)
}

ラベル付き引数への変換

位置引数をラベル付き引数に変換します。関数呼び出しにキャレットを置いて Alt+Enter を押します。

makeUser("Alice", 30, "admin")
makeUser(~name="Alice", ~age=30, ~role="admin")

不要な括弧の削除

式を囲む冗長な括弧を削除します。括弧で囲まれた式にキャレットを置いて Alt+Enter を押します。

let x = (a + b)
let x = a + b

冗長な修飾子の削除

モジュールが既に open されている場合に不要なモジュールパスの修飾子を削除します。修飾付き識別子にキャレットを置いて Alt+Enter を押します。

open Belt.Array
Belt.Array.map(arr, fn)
open Belt.Array
map(arr, fn)

filter+map を filterMap に変換

->Array.filter(f)->Array.map(g) チェーンを単一の ->Array.filterMap(...) 呼び出しに変換します。filter または map の呼び出しにキャレットを置いて Alt+Enter を押します。

items
->Array.filter(x => x > 0)
->Array.map(x => x * 2)
items->Array.filterMap(x => {
  if x > 0 {
    Some(x * 2)
  } else {
    None
  }
})

型注釈の追加

LSP hover の型情報を使用して let バインディングに明示的な型注釈を追加します。let バインディングにキャレットを置いて Alt+Enter を押します。

let name = "Alice"
let name: string = "Alice"

->ignore を追加

戻り値が使用されていない式に ->ignore を追加し、破棄された値に関するコンパイラ警告を抑制します。式にキャレットを置いて Alt+Enter を押します。

Js.log("debug message")
Array.push(items, newItem)
Js.log("debug message")->ignore
Array.push(items, newItem)->ignore

_ プレフィックスを追加

変数名にアンダースコアプレフィックスを追加して、意図的に未使用であることを示します。これによりコンパイラの未使用変数警告が抑制されます。未使用の変数にキャレットを置いて Alt+Enter を押します。

let result = someComputation()
let _result = someComputation()

冗長なブレースの削除

単一の式を囲む不要な { } を削除します。ブレースにキャレットを置いて Alt+Enter を押します。

let greet = (name) => {
  "Hello, " ++ name
}
let greet = (name) => "Hello, " ++ name

識別子ケースの修正

ReScript の規約に従って識別子のケースを修正します: 値と関数は小文字で始まり、モジュールとバリアントコンストラクターは大文字で始まる必要があります。命名が不適切な識別子にキャレットを置いて Alt+Enter を押します。

let MyValue = 42
let myValue = 42

分割代入の展開

分割代入された let バインディングを各フィールドごとの個別の let バインディングに展開します。分割代入パターンにキャレットを置いて Alt+Enter を押します。

let {name, age, email} = user
let name = user.name
let age = user.age
let email = user.email

呼び出しを uncurried 形式に変換

対象関数が旧来の uncurried 構文 let f = (. x) => ... で定義されている場合に、curried な呼び出し箇所を uncurried 形式 f(. x) に書き換えます。ReScript v10 / v11 コードベースでの LSP applyUncurried quick fix のネイティブフォールバックとして提供されます。

呼び出し箇所の識別子にキャレットを置いて Alt+Enter を押し、Convert call to uncurried form を選択します。

let add = (. x, y) => x + y
let result = add(1, 2)
let add = (. x, y) => x + y
let result = add(. 1, 2)

Intention はスタブインデックスで最初にマッチした定義のみを参照します。引数なし形式 f()f(.) に書き換えられます。

モジュールをファイルに抽出

トップレベルの module M = {{ ... }} 宣言を現在のファイルから取り出し、隣接する M.res ファイルに移動します。Language Server の WorkspaceEdit.CreateFile 操作が IDE 側で完全に処理されない場合に、LSP extractLocalModuleToFile code action のネイティブフォールバックとして提供されます。

モジュール宣言の名前部分にキャレットを置いて Alt+Enter を押し、Extract module to file を選択します。

module Inner = {
  let value = 42
  let double = x => x * 2
}

let total = Inner.double(Inner.value)

Foo.res:

let total = Inner.double(Inner.value)

Inner.res(新規作成):

let value = 42
let double = x => x * 2

Intention は抽出したモジュールへの参照を元ファイル内で書き換えません。そのような参照が検出された場合は警告バルーンが表示され、呼び出し箇所を手動で調整(例: open Inner の追加や修飾パスの更新)できます。隣接する Inner.res ファイルが既に存在する場合は Intention は表示されません。

Surround With(囲む)

Native

コードを選択して Ctrl+Alt+T を押すと、以下で囲むことができます:

  • if

  • switch

  • try / catch ブロック

  • ブロックスコープ { ... }

if 式

選択したコードを if ブロック内にラップします。カーソルは condition プレースホルダーに配置されるため、すぐに条件を入力できます。

Js.log("hello") を選択してから:

Js.log("hello")
if (condition) {
  Js.log("hello")
}

switch 式

選択したコードをデフォルトの _ アームを持つ switch 式内にラップします。カーソルは expr プレースホルダーに配置されるため、マッチする式をすぐに入力できます。

defaultHandler() を選択してから:

defaultHandler()
switch expr {
| _ => defaultHandler()
}

try / catch ブロック

選択したコードを try / catch ブロックでラップします。カーソルは catch アームの () プレースホルダーに配置されるため、エラー処理ロジックをすぐに定義できます。

parseJson(input) を選択してから:

parseJson(input)
try {
  parseJson(input)
} catch {
| exn => ()
}

ブロックスコープ { ... }

選択したコードをブロックスコープでラップします。変数のスコープを制限したり、式をグループ化する場合に便利です。

2行を選択してから:

let temp = calculate()
process(temp)
{
  let temp = calculate()
  process(temp)
}

Surround With はショートカット一つで選択コードを制御構造で囲み、囲む構文を手動で入力したり囲まれたコードを再インデントする手間を省きます。

参考

Code Completion では、同様のコード生成パターンのための Postfix テンプレート(.switch.pipe)と Live Template を提供しています。

インポートの最適化

Native

Ctrl+Alt+O を押すと、現在のファイルのインポートを最適化します。

仕組み

インポート最適化は 2 つのフェーズで実行されます:

  1. 重複検出 --- トップレベルの open 文をスキャンし、先行する open と同じモジュールパスを持つものを削除します

  2. 未使用 open 検出 --- LSP の診断警告を使用して、エクスポートがファイル内で参照されていない open 文を特定します

両フェーズは一緒に実行され、通知で結果が要約されます (例:両フェーズは同時に実行され、結果が通知で表示されます(例: "Removed 1 duplicate and 2 unused open statement(s)")。

設定

未使用 open の削除は Settings > Languages & Frameworks > ReScriptRemove unused opens チェックボックスで切り替えられます。無効にすると、重複 open のみが削除されます。

open Belt
open Belt.Array
open Belt          // duplicate
open Js.Promise    // unused
open Belt
open Belt.Array

ショートカット一つで冗長な open 文と未使用の open 文をすべてクリーンアップでき、ファイルを手動でスキャンせずにインポートを整理できます。

リネーム

LSP Required

Shift+F6 を押すと、プロジェクト全体でシンボルをリネームします。Language Server がすべての参照を検索して更新します。

リネームリファクタリングはプロジェクト全体のすべての参照を一括更新し、手動の検索と置換で残る見落としや不整合なリネームのリスクを排除します。

変数の抽出

Native

Ctrl+Alt+V(macOS では Cmd+Alt+V)を押して、選択した式を let バインディングに抽出します。

ハンドラーは let 宣言本体内の選択された式を検出し、現在のステートメントの上に新しい let バインディングを作成し、元の式を新しい変数への参照に置き換えます。

a + b を選択してから:

let calculate = (a, b) => {
  let result = a + b * 2
  result
}
let calculate = (a, b) => {
  let sum = a + b
  let result = sum * 2
  result
}

Extract Variable により中間式に名前を付けて明確にでき、周囲のコードを手動で再構成することなく複雑な式を自己文書化できます。

関数の抽出

Native

Ctrl+Alt+M(macOS では Cmd+Alt+M)を押して、選択したコードを新しい関数に抽出します。

ハンドラーは let 宣言本体内の選択された式またはステートメント範囲を検出し、現在の宣言の上に新しい let 関数として抽出し、元のコードを新しい関数の呼び出しに置き換えます。選択範囲内の自由変数は抽出された関数のパラメーターになります。

a + b を選択してから:

let calculate = (a, b) => {
  let result = a + b
  result * 2
}
let extracted = (a, b) => a + b

let calculate = (a, b) => {
  let result = extracted(a, b)
  result * 2
}

Extract Function は自由変数を自動検出してパラメータに変換するため、値を手動で引き回すことなく大きな関数を小さく再利用可能な部品に分解できます。

変数/関数のインライン化

Native

Ctrl+Alt+N(macOS では Cmd+Alt+N)を押して、キャレット位置の変数または関数をインライン化し、すべての参照を定義本体に置き換えます。

ハンドラーはキャレット位置の let 宣言を見つけ、ファイル内のすべての参照を検出し、各参照を定義本体に置き換え、元の宣言を削除します。

let prefix = "Hello"
let greet = (name) => `${prefix}, ${name}!`
let greet = (name) => `${"Hello"}, ${name}!`

インラインリファクタリングは抽出の逆で、不要な中間変数をその定義に置き換え、名前付きバインディングが明確さを追加しない場合にコードを簡素化します。

定数の導入

Native

リテラル値をモジュールレベルの定数に抽出します。文字列、数値、その他のリテラルを選択して Refactor > Introduce Constant を使用します。

ハンドラーは選択したリテラルをファイルの先頭(open 文の後)に新しい let バインディングとして抽出し、元のリテラルを新しい定数への参照に置き換えます。

"Hello, World!" の定数導入:

let greeting = "Hello, World!"
let farewell = "Goodbye, World!"
let helloWorld = "Hello, World!"
let greeting = helloWorld
let farewell = "Goodbye, World!"

Introduce Constant はマジック値をモジュールレベルの名前付きバインディングに抽出し、意図を明示的にしてファイル全体での再利用を可能にします。

シグネチャの変更

Native

Ctrl+F6 を押して関数のパラメーターを変更(並べ替え、リネーム、追加、削除)し、ファイル内の呼び出し箇所を更新します。

ハンドラーはキャレット位置の関数宣言を解析し、ラベル付き(~name: type)と位置パラメーターの両方をサポートし、宣言とすべての対応する呼び出し箇所に変更を適用します。

パラメーターの並べ替え:

let make = (~name: string, ~age: int) => { name, age }

let user = make(~name="Alice", ~age=30)
let make = (~age: int, ~name: string) => { name, age }

let user = make(~age=30, ~name="Alice")

Change Signature は関数のパラメータリストを再構成し、すべての呼び出し箇所を自動更新するため、API の進化がエラーの起きやすい手動編集ではなく安全で機械的になります。

React コンポーネントの抽出

Native

選択した JSX を新しい React コンポーネントに抽出します。JSX 式を選択し、Refactor > Extract React Component を使用します。

ハンドラーは選択した JSX を本体とする新しい @react.component モジュールを作成します。選択範囲内で使用されている props が検出され、新しいコンポーネントの make 関数にラベル付きパラメーターとして追加されます。

<div className="card">...</div> を選択してから:

@react.component
let make = (~items) => {
  <div className="container">
    <div className="card">
      {items->Array.map(item => <span key={item}> {React.string(item)} </span>)->React.array}
    </div>
  </div>
}
module Card = {
  @react.component
  let make = (~items) => {
    <div className="card">
      {items->Array.map(item => <span key={item}> {React.string(item)} </span>)->React.array}
    </div>
  }
}

@react.component
let make = (~items) => {
  <div className="container">
    <Card items />
  </div>
}

JSX から React コンポーネントを抽出するのは React 開発における一般的なリファクタリングです — この自動化は必要な props を検出し、適切に構造化されたモジュールを作成するため、手動でコードをコピーして props を引き回す手間を省きます。

JSON.t として貼り付け

Native

Edit > Paste as JSON.t を使用して、クリップボードの JSON を ReScript の JSON.t 値に変換します。

各 JSON 値を手動で ReScript コンストラクタでラップする代わりに、生の JSON をペーストして正しく型付けされた JSON.t 式を即座に取得できます。

コード生成

Native

Cmd+N(または Alt+Insert)を押して Generate メニューを開きます:

  • Generate Switch Arms — バリアント型のマッチアームを自動生成

  • Generate Module Type — モジュール実装からモジュール型のスケルトンを生成

  • Generate Make Function — レコード型からコンストラクタ関数を生成

  • Generate JSON Encoder/Decoder — 型から JSON エンコーダーとデコーダー関数を生成

  • Generate Record Value — 全フィールドにデフォルト値を設定したレコード値を生成

Switch Arms の生成

キャレットがバリアント型宣言の中にある場合、このアクションはコンストラクターごとに1つのアームを持つ switch 式を生成します。すべてのバリアントを手動で列挙することなく、網羅的なパターンマッチを記述できます。

型宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、Switch Arms を選択します。

type shape =
  | Circle(float)
  | Rectangle(float, float)
  | Triangle(float, float, float)
  | Point
type shape =
  | Circle(float)
  | Rectangle(float, float)
  | Triangle(float, float, float)
  | Point

switch value {
| Circle(_) => todo
| Rectangle(_) => todo
| Triangle(_) => todo
| Point => todo
}

ペイロードを持つコンストラクター(例: Circle(float))は生成されたアームで _ ワイルドカードを取得し、ペイロードのないコンストラクター(例: Point)は直接マッチします。各アームの todo を実際のロジックに置き換えてください。

Module Type の生成

キャレットがモジュール宣言の中にある場合、このアクションは module type シグネチャのスケルトンを生成し、モジュールの上に挿入します。生成されたシグネチャには、モジュール本体にあるすべての let, type, external、およびネストされた module 宣言が含まれます。

モジュール宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、Module Type を選択します。

module StringUtils = {
  type config = {verbose: bool}

  let capitalize = (s: string) => {
    // ...
  }

  let truncate = (s: string, maxLen: int) => {
    // ...
  }

  module Internal = {
    let helper = () => ()
  }
}
module type StringUtilsType = {
  type config
  let capitalize: 'a
  let truncate: 'a
  module Internal: {}
}

module StringUtils = {
  type config = {verbose: bool}

  let capitalize = (s: string) => {
    // ...
  }

  let truncate = (s: string, maxLen: int) => {
    // ...
  }

  module Internal = {
    let helper = () => ()
  }
}

生成された型は値の型のプレースホルダーとして 'a を使用します -- これらを実際の型シグネチャに置き換えてください。型宣言は定義本体なしで表示されるため、公開する型の形状を指定できます。ネストされたモジュールは空の {} シグネチャでリストされるため、内容を記入してください。

Make 関数の生成

キャレットがレコード型宣言の中にある場合、このアクションは各レコードフィールドに対応するラベル付き引数を持つ make コンストラクタ関数を生成します。

型宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、Make Function を選択します。

type user = {
  name: string,
  age: int,
  email: string,
}
type user = {
  name: string,
  age: int,
  email: string,
}

let make = (~name, ~age, ~email) => {
  name,
  age,
  email,
}

オプショナルフィールド(例: email?: string)はオプショナルラベル付き引数(~email=?)として生成されます。

JSON エンコーダー/デコーダーの生成

キャレットがレコード型またはバリアント型宣言の中にある場合、このアクションは @rescript/coreJSON モジュールを使用して JSON エンコーダーとデコーダー関数を生成します(外部依存は不要)。

型宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、JSON Encoder/Decoder を選択します。

レコード型の例:

type user = {name: string, age: int, email: option<string>}

各フィールドを適切な JSON.t コンストラクター(StringNumberBooleanNullObjectArray)に変換するエンコーダーと、JSON 構造をパターンマッチしてレコード型に戻すデコーダーを生成します。

バリアント型の例(単純な enum):

type color = Red | Green | Blue

各コンストラクターがその名前を JSON 文字列としてマッピングする String ベースのエンコーダー/デコーダーを生成します。

バリアント型の例(タグ付きユニオン):

type status = Success(string) | Error(int)

"tag" フィールドと位置ペイロードフィールド("_0""_1"、...)を持つ Object を使用したタグ付きユニオンのエンコーダー/デコーダーを生成します。

サポートされる型: stringintfloatbooloption<T>array<T>、および任意のネスト(例: option<array<string>>)。認識されない型には /* TODO */ プレースホルダーが生成されるので、手動で記入してください。

命名規則: 関数名は encode + 型名の先頭大文字 と decode + 型名の先頭大文字(例: encodeUser / decodeUser)です。型名が t の場合は、単に encode / decode となります。

レコード値の生成

キャレットがレコード型宣言の中にある場合、このアクションは全フィールドにデフォルト値を設定したレコード値を生成します。初期値やテストフィクスチャの素早い作成に便利です。

型宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、Record Value を選択します。

type user = {
  name: string,
  age: int,
  active: bool,
  email: option<string>,
}
type user = {
  name: string,
  age: int,
  active: bool,
  email: option<string>,
}

let value: user = {
  name: "",
  age: 0,
  active: false,
  email: None,
}

デフォルト値はフィールドの型から推論されます: string には ""int には 0float には 0.0bool には falseoption<T> には Nonearray<T> には []

モジュールタイプ実装の生成

キャレットが module type 宣言の中にある場合、このアクションは各シグネチャエントリに対するスタブ関数を持つモジュールタイプの実装モジュールを生成します。

モジュールタイプ宣言内にキャレットを置いて Cmd+N(または Alt+Insert)を押し、Module Type Implementation を選択します。

module type Printable = {
  type t
  let toString: t => string
  let print: t => unit
}
module type Printable = {
  type t
  let toString: t => string
  let print: t => unit
}

module PrintableImpl: Printable = {
  type t
  let toString = (_) => todo
  let print = (_) => todo
}

todo プレースホルダーを実際の実装に置き換えてください。生成されたモジュールはモジュールタイプに制約されているため、シグネチャの不足や不正をコンパイラが検出します。

コード生成は型定義を動作するコードに変換します — switch アーム、コンストラクタ、JSON コーデック、モジュールスケルトンが型から自動作成され、面倒でエラーの起きやすいボイラープレート記述を排除します。

末尾スペースの除去

Native

プラグインは IntelliJ が保存時に末尾スペースを削除する際、文字列リテラル内のスペースを保護します。この保護がないと、文字列行末の意図的なスペースが除去されてしまいます。

保護されるトークン型:

  • STRING_VALUE — 通常の文字列コンテンツ

  • JS_STRING_OPEN / JS_STRING_CLOSE — JavaScript テンプレート文字列の境界

末尾スペースの動作は Settings > Editor > General > On Save で設定できます。

この保護により、文字列リテラル内の意図的なスペースがエディタの末尾スペースクリーンアップで静かに削除されることがなく、文字列が多いコードでの微妙なバグを防ぎます。

エディタフローティングツールバー

Native

ReScript ファイルの編集時にフローティングツールバーが表示され、よく使うアクションに素早くアクセスできます:

  • Format — 現在のファイルをフォーマット(Cmd+Option+L

  • Open Compiled JS — コンパイル済み JavaScript 出力を開く

  • Create Interface.resi インターフェースファイルを生成

ツールバーは ReScript ファイルの編集開始時に自動表示され、使用していないときは自動的に非表示になります。

フローティングツールバーは最も一般的な ReScript 固有のアクション — フォーマット、コンパイル済み JS の表示、インターフェース作成 — をワンクリックで提供し、キーボードショートカットを覚える必要がありません。

スペルチェック

Native

プラグインは以下に対して IntelliJ の組み込みスペルチェッカーをサポートします:

  • コメント(行コメントとブロックコメント)

  • 文字列リテラル

  • 識別子(camelCase 分割)

組み込みのスペルチェックにより入力中にコメント、文字列、識別子のタイポをキャッチし、別途レビューステップなしでプロフェッショナルなコード品質を維持できます。

Backspace ハンドラー

Native

Backspace で開始 JSX タグを削除すると、対応する終了タグも自動的に削除されます。

ペアタグ削除により孤立した閉じタグを防ぎます — 開き JSX タグをバックスペースで削除すると、閉じタグも自動的に消え、マークアップのバランスが保たれます。

要素の左右移動

Native

Alt+Shift+Cmd+Left / Alt+Shift+Cmd+Right でカンマ区切りの要素を入れ替えます。関数の引数、配列の要素、レコードフィールド、タプルの要素に対応しています。

手動のカット&ペーストの代わりにキーボードショートカットで引数、配列項目、レコードフィールドを並べ替え、カンマとフォーマットが自動的に正しく保たれます。

コードブロックの選択

Native

Ctrl+Shift+[Ctrl+Shift+] を使用して、囲んでいるコードブロック(ブレース区切り)の先頭と末尾に移動します。

大きな関数本体や深くネストされた構造で作業する際に、スクロールや対応するブレースの検索なしでブロック境界に素早くジャンプできます。

リストの分割/結合

Native

カンマ区切りのリストを単一行と複数行の形式で切り替えます。Edit > Split/Join List から利用できます。

コンパクト形式と展開形式のリスト切り替えは単一のアクションで、改行やカンマを手動で追加・削除することなく可読性のためのコード密度を調整できます。

コピー/ペースト時のエスケープ

Native

文字列リテラルにテキストを貼り付けると、特殊文字(バックスラッシュ、引用符、改行、タブ)が自動的にエスケープされます。

自動エスケープにより、文字列リテラルに生テキストをペーストしても特殊文字が正しく処理されることが保証され、エスケープされていない引用符やバックスラッシュによる発見しにくい構文エラーを回避できます。

Unwrap/Remove(ラップ解除/削除)

Native

Ctrl+Shift+Delete(macOS では Cmd+Shift+Delete)を押して、囲んでいるラッパーを除去し、内側の式を抽出します。

カーソル位置で適用可能なすべてのラップ解除オプションがポップアップに表示されます。いずれかを選択してラップを解除します。

サポートされるラッパー

ラッパー

変更前

変更後

Some(...)

Some(myValue)

myValue

Ok(...)

Ok(result)

result

Error(...)

Error(msg)

msg

if (...) { ... }

if (cond) { body }

body

switch ... { ... }

switch x { | _ => body }

body

try { ... } catch { ... }

try { body } catch { | e => () }

body

{ ... }(ブロック)

{ expr }

expr

例:

let greeting = Some("Hello, world!")
let greeting = "Hello, world!"

Unwrap/Remove は Surround With の逆で、Some()iftry などのラッパーをワンアクションで剥がし、デリミタを手動で削除して再インデントすることなく式を簡素化します。

JSX 自動閉じタグ

Native

JSX 開始タグを閉じるために > を入力すると、対応する終了タグが自動的に挿入され、カーソルはタグ間に配置されます。

<div> を入力:

<div>
<div></div>

以下に対応しています:

  • HTML 要素: <div>, <span>, <input>

  • React コンポーネント: <MyComponent>

  • モジュール修飾コンポーネント: <Module.Component>

自己閉じタグ(例: <br />)、コメント内、文字列リテラル内では自動閉じは動作しません。

自動閉じタグによりキーストロークを節約し、JSX タグの不一致を防ぎます — 開きタグを入力すると閉じタグが自動的に表示され、記述中のマークアップのバランスが保たれます。

Enter ハンドラー(コメント継続)

Native

コメント内で Enter を押すと、次の行に適切なコメント継続文字が自動的に挿入されます。

ドキュメントコメント

/** ... */ ブロック内で Enter を押すと、新しい行の先頭に * が挿入されます:

/** Some documentation|

Enter を押した後:

/** Some documentation
 * |

行コメント

// コメント内で Enter を押すと、新しい行の先頭に // が挿入されます:

// This is a comment|

Enter を押した後:

// This is a comment
// |

ドキュメントコメント(///)も継続されます:

/// A doc comment|

Enter を押した後:

/// A doc comment
/// |

コメント継続により、各行にプレフィックスを手動で入力することなく複数行コメントを適切にフォーマットし、クリーンなコメントスタイルを楽に維持できます。

スマート行結合

Native

Ctrl+Shift+J(macOS では Cmd+Shift+J)を押して、ReScript に適した方法で現在の行を次の行と結合します。

パイプチェーンの結合

行が -> で終わるか、次の行が -> で始まる場合、スペースを追加せずに行が結合されます:

value->
  Array.map(x => x + 1)
value->Array.map(x => x + 1)

Let バインディングの結合

行が = で終わる場合、= の後にスペース1つを入れて行が結合されます:

let result =
  computeValue()
let result = computeValue()

アロー関数の結合

行が => で終わる場合、スペース1つを入れて行が結合されます:

let fn = (x) =>
  x + 1
let fn = (x) => x + 1

上記のパターンに該当しない場合は、IDE の標準の行結合動作が使用されます。

スマート結合は ReScript 構文を理解します — パイプチェーンはスペースなしで結合し、let バインディングは = を保持し、アロー関数は可読性を維持するため、汎用的な行結合よりクリーンな結果を生成します。

ワード選択(拡大/縮小)

Native

Ctrl+W(macOS では Alt+Up)で選択を拡大、Ctrl+Shift+W(macOS では Alt+Down)で選択を縮小します。ReScript に適した境界を認識します。

選択境界

ワードセレクターは選択の拡大/縮小に対して以下の ReScript 固有の境界を認識します:

コンテキスト

選択の拡大先

文字列リテラル内

文字列の内容(引用符なし) → 文字列全体(引用符を含む)

括弧 (...)

括弧内の内容 → 括弧を含む全体

ブロックコメント /* ... */

コメント内容 → デリミタを含むコメント全体

行コメント // ...

コメントテキスト → コメント行全体

ReScript のコード構造を扱う際に、デフォルトのワードセレクターよりも自然な選択動作を提供します。

ReScript 対応の選択境界により、標準の拡大/縮小ショートカットを使って、引用符なしの文字列内容やデリミタなしのブロックコメントテキストなど、必要なコンテンツを正確に選択できます。

JSX として貼り付け

Native

HTML コンテンツを ReScript ファイルに貼り付けると、自動的に JSX 構文に変換されます:

  • HTML 属性(classforonclick)が JSX の同等属性(classNamehtmlForonClick)にリネームされます

  • Void 要素(<br><img><input>)が自己閉じタグ(<br />)に変換されます

  • インライン style 文字列が ReScript のスタイルオブジェクトに変換されます

  • Boolean 属性(例: disabledchecked)が JSX の boolean props として保持されます

  • data-* および aria-* 属性はそのまま保持されます

Paste as JSX は HTML を ReScript JSX に自動変換します — classclassName に手動でリネームしたり void 要素を自己終了させたりする代わりに、ペースト時に変換が行われます。

ReScript として貼り付け

Native

この変換は、標準のペーストショートカット(Cmd+V / Ctrl+V)で JavaScript または TypeScript コードを .res ファイルに貼り付けると自動的にトリガーされます。別途メニューアクションは不要です — プラグインがクリップボード内の JavaScript/TypeScript パターンを検出し、その場で変換します。

JavaScript または TypeScript コードを ReScript ファイルに貼り付けると、自動的に ReScript 構文に変換されます:

JavaScript の変換

  • const/let/var 宣言が let バインディングに変換されます

  • アロー関数 (x) => { return x }(x) => x に簡素化されます

  • === / !==== / != に変換されます

  • console.log(x)Js.log(x) に変換されます

  • null / undefinedNone に変換されます

  • テンプレートリテラルはそのまま維持されます(ReScript は同じ構文を使用)

TypeScript 型の除去

  • 変数の型注釈(const x: string = ...)が除去されます

  • 関数パラメータの型注釈((a: number, b: string))が除去されます

  • 戻り値の型注釈(): boolean {)が除去されます

  • 型アサーション(value as string)が除去されます

  • interface および enum 宣言がコメントアウトされます

  • export type / export interface / export enum がコメントアウトされます

JSX/TSX パターンの変換

  • 条件付きレンダリング {condition && <expr>}{condition ? <expr> : React.null} に変換されます

  • 配列メソッド(.map().filter().forEach())がパイプファーストスタイル(->Array.map())に変換されます

  • JSX スプレッド {...props} に警告コメントが追加されます(ReScript JSX ではサポートされていません)

const greeting = (name: string): string => {
  console.log("Hello, " + name);
  return name.toUpperCase();
}
let greeting = (name) => {
  Js.log("Hello, " ++ name)
  name->String.toUpperCase
}

Paste as ReScript は JavaScript/TypeScript と ReScript のギャップを埋めます — ドキュメント、Stack Overflow、既存の JS/TS ファイルからコードをコピーし、自動構文変換付きで .res ファイルに直接ペーストできます。

React JSX/TSX コード(className={expression} ブレース、onClick= などの camelCase イベントハンドラを含む)は、HTML→JSX コンバータではなく JS/TS→ReScript コンバータによって処理され、JSX パターンが正しく扱われます。