コンテンツにスキップ
{/* SVGアイコンは変更不要 */} {/* SVGアイコンは変更不要 */} {/* SVGアイコンは変更不要 */}

Crystalツール

Brian J. Cardiff

Crystalコンパイラは、プログラマがより表現力豊かに、生産性を高く、そして…怠惰になれるように、多くの作業を行います。

0.7.7以降、コンパイラには、プログラマがコードからコンパイラが何を理解しているのかを知り、より興味深い方法でナビゲートするのに役立つ初期ツールがいくつか付属しています。

実装に移動するツール

メソッド呼び出しをコンパイルするとき、コンパイラはどのメソッド定義が呼び出されるかを正確に知っています。しかし、プログラマがソースコードを見ているとき、(文字列検索以外に)メソッド定義に到達する方法はありませんでした。

プロジェクトが大きくなればなるほど、定義を見つけるのが難しくなります。

そのため、次のコードを含む*program.cr*がある場合

def add(a, b)
  a + b
end

add(1, 2)
$ crystal tool implementations --cursor program.cr:5:1 program.cr
1 implementation found
/path/to/program.cr:1:1

コンピュータフレンドリーな出力を生成し、お気に入りのテキストエディタに統合するための何かを構築するために、--format json を渡すことができます。これは、crystal-tools atomパッケージで使用されており、素晴らしいです。すべての場所はクリック可能です。

Atomを使用する場合は、ダウンロードして、カーソルが5行目のaddの上にある間に⌘⌥i / ctrl-alt-iを押してください。

複数の実装

このツールは、def foodef self.fooの文字列マッチング地獄を回避できるだけでなく、メソッド呼び出しの実際の候補がどれであるかを指摘します。

class A
  def foo
  end
end

class B
  def foo
  end
end

def use_foo(o)
  o.foo           # put the cursor in this #foo call
end

use_foo(A.new)
use_foo(B.new)    # if removed, line 7 won't be an implementation of line 12

マクロの深淵へ

スニペットは千の言葉に値します。

class Person
  property name
end

p = Person.new
p.name = "John"   # put the cursor in over #name= call
$ crystal tool implementations --cursor program.cr:6:6 program.cr
1 implementation found
/path/to/program.cr:2:3
 ~> macro property: /path/to/crystal-src/object.cr:365:5
 ~> macro setter: /path/to/crystal-src/object.cr:324:9

そして、*object.cr*がどのように見えるか知っていますか?

class Object
  # ...
  macro setter(*names){% for name in names %}
      {%- if name.is_a?(DeclareVar) %}
        def {{name.var.id}}=(@{{name.var.id}} : {{name.type}}) # line 324
        end
      {%- else %}
        def {{name.id}}=(@{{name.id}})
        end
      {%- end %}
    {%- end %}
  end
  # ...
  macro property(*names)
    getter {{*names}}
    setter {{*names}}   # line 365
  end
  # ...
end

これが大好きです!

コンテキストを明らかにするツール

pp varまたはpp typeof(var)で実行するのを回避するのに役立つもう1つの便利なツールは、コンテキストツールです。カーソルをどこか⌘⌥c / ctrl-alt-cに置いて、すべての変数の型情報が表示されます。

前のツールと同様に、プログラム自体は決して実行されません。表示されるすべての情報は、バイナリを生成するのと同じビルドプロセスから取得されます。

このツールはコマンドライン形式で利用できます。

a = "a string"
b = 1

$ crystal tool context --cursor program.cr:3:1 program.cr
1 possible context found

| Expr | Type   |
-----------------
| a    | String |
| b    | Int32  |

defが保持するすべてのオーバーロードを見るのは興味深いことです。

最後に

作業中

これは進行中の作業です:-) 。もっと多くのツールが必要で、誰にとっても十分に堅牢なものにしたいと考えています。私たちは、あなたがそれらを楽しむのに十分な準備ができていると考えており、私たちがそれらをより良くするのを助けてくれることを願っています。

次のステップ

crystal-tools atomパッケージは、おそらくcrystal specのサポートを受けるため、エディタから単一ファイル/単一スペックを実行するのが簡単になります。

もう1つの望ましいツールは、特定のメソッドのすべての呼び出し元を取得することです。実装のデュアルツールのようなもので、「このコードは誰が使用しているのか?」という質問に答えます。

緑色のコンパイルステータスは必須です

これらのツールは、Crystalコンパイラの上に、そのすべての型推論とコンパイラフェーズとともに構築されているため、コードがコンパイルされない場合、ツールを実行することはできません。

メインプログラム

ここで示したすべてのサンプルは単一ファイルのプログラムでしたが、ツールはより大きなプロジェクトでも機能します。これが発生するためには、ツールはコンパイルするメインファイルを知る必要があります。これはコマンドの最後の引数でした。--cursor引数は、テキストカーソルがエディタのどこにあるかを指定します。

単一ファイルプログラムの場合、メインプログラムはそれだけです。より大きなプログラムの場合はそれほど簡単ではありません。開発者として、どのファイルをコンパイルするかを知っている必要があります。

crystal-tools atomパッケージは、すべての仕様をメインプログラムとして使用します。これが必要なものでない場合は、設定ページから、コンパイルするファイルなどを変更できます。

…さらに優れたCrystalプログラミング体験に向けて。❤