sbt 1.1.0-RC1 の sbt server と統一スラッシュ構文

in

Lightbend の技術系ブログ Tech Hub blog に sbt 1.1.0-RC1 with sbt server and slash syntax という記事を書いたので、訳しました。

@eed3si9n

皆さんこんにちは。Lightbend Tooling team にかわって sbt 1.1.0-RC1 をアナウンスします。これは、sbt 1 初のフィーチャーリリースで、バイナリ互換性は維持しつつ新機能にフォーカスを当てたリリースとなっている。
sbt 1 は Semantic Versioning にもとづいてリリースされるので、プラグインは sbt 1.x シリーズ中機能することが期待されている。2017年12月14日までに大きな問題が見つからなければ、1.1.0-RC1 は 1.0.0 final 版となる予定だ。

sbt 1.1 の主な新機能は統一スラッシュ構文 (unified slash syntax) と sbt server だ。これらは両方とも僕が個人的にしばらく関わってきた機能だが、sbt 1.0 には入れずに延期させたものだ。そのため、やっとこれらを世に出せるのがひとしお嬉しい。

セッティングキーの統一スラッシュ構文

sbt の 1ユーザとして、sbt シェルと build.sbt でセッティングとタスクキーに 2つの表記方法があるのが、sbt の学習を難しくしている理由だと長いこと思ってきた。コミュニティーの皆さんと議論を重ね、いくつかのプロトタイプを作った後、sbt 1.1.0-RC1 より統一スラッシュ構文がサポートされることになった。 (sbt 0.13 表記も引き続き動作するのでご心配無く)

build.sbt と sbt shell の両方において、セッティングはスコープ軸をスラッシュで分けて以下のように書くことができる:

ref / Config / intask / key

上の ref は典型的にはサブプロジェクト名もしくは ThisBuild が入り、ConfigCompileTest などコンフィギュレーションの Scala 識別子が入る。それぞれの軸は省略するか、特殊な Zero という値で置き換えることが可能なので、実際は以下のようになっている:

((ref | "Zero") "/") ((Config | "Zero") "/") ((intask | "Zero") "/") key

具体例で説明すると、sbt 0.13 では:

  • Test コンフィギュレーションのみをコンパイルするには build.sbt 内では (compile in Test).value と書き、sbt shell では test:compile と書いた。
  • Global レベルの cancelable セッティングは build.sbt 内では (cancelable in Global).value と書き、sbt shell では */*:cancelable と書いた。

一方 sbt 1.1.0-RC1 では:

  • Test にスコープ付けされた compile タスクは、build.sbt 内では (Test / compile).value と書き、sbt shell でも Test / compile と書く。
  • Global にスコープ付けされた cancelable セッティングは build.sbt 内では (Global / cancelable).value と書き、sbt shell でも Global / cancelable と書く。

以下はデモだ:

slash

詳細は Migrating to slash syntaxスコープのドキュメンテーションを参照。

注意: プラグイン作者の皆さんに注意してほしいのは、この新構文をプラグインで使うと動作可能な最小 sbt バージョンが sbt 1.1.0-RC1 に引き上がってしまうことだ。

#1812/#3434/#3617/#3620 by @eed3si9n and @dwijnand

sbt server

「sbt server」という名前を聞くと、リモートのサーバで走って、何かすごいことをやってくれるんじゃないかと想像するかもしれない。しかし、今のところ sbt server はそれではない。sbt server は単に sbt shell にネットワークからのアクセスを追加するだけだ。sbt 1.1 はこの機能を刷新して Language Server Protocol 3.0 (LSP) をワイヤープロトコルとして採用した。これは、Microsoft 社が Visual Studio Code のために開発したプロトコルだ。

実行中のサーバを発見するには、sbt 1.1.0 はビルドから見て ./project/target/active.json にポートファイルを作成するので、それを見つける:

{"uri":"local:///Users/foo/.sbt/1.0/server/0845deda85cb41abcdef/sock"}

ここで local: は Unix ドメインソケットを表している。nc を用いてサーバに hello と言うには以下を実行する (^M を発信するには Ctrl-V を打ってから Return を打つ):

$ nc -U /Users/foo/.sbt/1.0/server/0845deda85cb41abcdef/sock
Content-Length: 99^M
^M
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { } } }^M

compile は以下のように行う:

Content-Length: 93^M
^M
{ "jsonrpc": "2.0", "id": 2, "method": "sbt/exec", "params": { "commandLine": "compile" } }^M

これで、現在実行中の sbt セッションは compile をキューに加え、もしコンパイラ警告やエラーがあれば、メッセージを返すはずだ:

Content-Length: 296
Content-Type: application/vscode-jsonrpc; charset=utf-8
 
{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:/Users/foo/work/hellotest/Hello.scala","diagnostics":[{"range":{"start":{"line":2,"character":26},"end":{"line":2,"character":27}},"severity":1,"source":"sbt","message":"object X is not a member of package foo"}]}}

これによって、複数のクライアントが単一の sbt セッションに接続することが可能となる。クライアントの主な用途はエディタや IDE といったツーリングの統合を想定している。詳細に関しては sbt server を参照。

#3524/#3556 by @eed3si9n

VS Code エクステンション

エディタ統合の概念実証として、Scala (sbt) という Visual Studio Code エクステンションを作ってみた。これを試すには、Visual Studio Code をインストールして、「Scala (sbt)」 を Extensions タブから検索して、sbt 1.1.0-RC1 を何らかのプロジェクトから実行して、VS Code を使ってそのプロジェクトを開く。

今のところこのエクステンションが可能なのは:

  • *.scala ファイルが保存されたら、ルートプロジェクトから compile を実行する。 #3524 by Eugene Yokota (@eed3si9n)
  • コンパイラエラーを表示する。
  • ログメッセージを表示する。 #3740 by Alexey Alekhin (@laughedelic)
  • クラス定義にジャンプする。 #3660 by Wiesław Popielarski at VirtusLab (@wpopielarski)

以下はデモだ:

vscode-scala-sbt

その他のバグ修正や改善点

  • Semantic Versioning に準拠して version セッティングのデフォルトを 0.1.0-SNAPSHOT に変更した。 #3577 by @laughedelic
  • Java 9 でのオーバーコンパイルを修正した。 zinc#450 by @retronym
  • 深く入れ子になった Java クラスの処理を修正した。 zinc#423 by @romanowski
  • JavaDoc が全てのエラーを表示しない問題を修正した。 zinc#415 by @raboof
  • ScalaInstance.otherJars の JAR の順序を保つようにした。 zinc#411 by @dwijnand
  • 名前に改行が含まれる場合の used name 処理を修正した。 zinc#449 by @jilen
  • ThisProject の処理を修正した。 #3609 by @dwijnand
  • sbt ファイルにおける import 文をエスケープして、もしバッククォートが必要な定義があった場合にタスクが失敗しないようにした。 #3635 by @panaeon
  • 警告文からバージョン 0.14.0 への言及を削除した。 #3693 by @saniyatech
  • screpl が "Not a valid key: console-quick" を投げる問題を修正した。 #3762 by @xuwei-k
  • scripted test を project/build.properties を用いてフィルターできるようにした。 #3564/#3566 by @jonas
  • サブプロジェクトの id を変更するために Project#withId を追加した。 #3601 by @dwijnand
  • 現在のアーティファクトを boot ディレクトリから削除する reboot dev というコマンドを追加した。これは sbt の開発版を使っているときに便利な機能だ。 #3659 by @eed3si9n
  • reload 時に sbt version が変わっていないかチェックするようにした。 #1055/#3673 by @RomanIakovlev
  • 現在 CI環境で実行されているかを知るための insideCI という新セッティングを追加した。 #3672 by @RomanIakovlev
  • Command trait に nameOption を追加した。 #3671 by @miklos-martin
  • IO に IO.chmod(...) など POSIX アクセス権処理を追加した。 io#76 by @eed3si9n
  • sbt 1 モジュールを eviction warning において Semantic Versioning 扱いするようにした。 lm#188 by @eed3si9n
  • コード内で kind-projector を使うようにした。 #3650 by @dwijnand
  • Completions 内の displayOnly メソッドなどを正格にした。 #3763 by @xuwei-k

参加

sbt や Zinc 1 を実際に使ったり、バグ報告、ドキュメンテーションの改善、ビルドの移植、プラグインの移植、pull request をレビューしたり送ってくれた皆さん、ありがとうございます。

sbt, zinc, librarymanagement, util, io, website などのモジュールで実行した git shortlog -sn --no-merges v1.0.4..v1.1.0-RC によると、sbt 1.1.0-RC1 は 32名のコントリビュータのお陰でできました (敬称略): Eugene Yokota, Dale Wijnand, Kenji Yoshida (xuwei-k), Alexey Alekhin, Simon Schäfer, Jorge Vicente Cantero (jvican), Miklos Martin, Jeffrey Olchovy, Jonas Fonseca, Andrey Artemov, Arnout Engelen, Dominik Winter, Krzysztof Romanowski, Roman Iakovlev, Wiesław Popielarski, Age Mooij, Allan Timothy Leong, Antonio Cunei, Jason Zaugg, Jilen Zhang, Long Jinwei, Martin Duhem, Michael Stringer, Michael Wizner, Nud Teeraworamongkol, OlegYch, PanAeon, Philippus Baalman, Pierre Dal-Pra, Saniya Tech, Tom Walford, その他大勢の人のアイディアも得ている。 Thank you!

sbt を手伝ってみたいと興味があれば、好みによって色々な方法があります。

  • プラグインやライブラリを sbt 1 へと移行させる。
  • バグを見つけたら報告する。
  • バグの修正を送る。
  • ドキュメンテーションの更新。

他にもアイディアがあれば、sbt-contrib で声をかけてください。