たにしきんぐダム

プログラミングやったりゲームしてます

Scala の開発環境構築 2021

f:id:tanishiking24:20201203004828p:plain
特に意味はないけどおしゃれかなと思って貼ったスクショ

Scala Advent Calendar 2020 - Qiita 3日目です

ここ2,3年の間にScalaの開発ツールチェーンは進化を続けていて、Scalaの開発体験はめちゃくちゃ良くなってきています。例えば、数年前だと

  • IDEは基本的にIntelliJ一択、vimとかemacsで開発環境作れなくもないけどかなり大変
  • IntelliJの型チェックがうまく行かなくて、ちょっと複雑なコード書くとコンパイルは通るのに画面が真っ赤になる
  • コンパイルが遅い(インクリメンタルビルドしても遅い)

という感じだったのですが、現状はかなり改善されていて

  • IntelliJ 以外にも metals という Language Server がかなり使いやすくなっていてあらゆるエディタで簡単にScalaを書けるようになった
  • IntelliJ ã‚‚ metals コンパイラ(正確にはビルドサーバー)から直接コンパイルエラーを受け取るのでコンパイル通るのに真っ赤とかはない
  • Scalaコンパイラ自体は少しずつ早くなってる。
    • sbtのincremental compilerの改善が劇的で、sbtを立ち上げっぱなしにしている場合はかなり開発効率が良い
    • フルビルドはやっぱり時間かかる

基本的に OSX / VSCode での環境構築方法を書いていきます。InttelliJ の構築もそのうち書きたい

まだ2020年だけどもうすぐ2021年だし2021年ってタイトルにしちゃった。


Java のインストール

とりあえずJava11を入れておけば良いと思います。Javaディストリビューションはいろいろあるけどローカルなら何でも良いんじゃないんですかね? oracle とか adoptopenjdk とかで

brew

$ brew cask install java11
# ~/.zshrc なんかに
export JAVA_HOME=`/usr/libexec/java_home -v 11`
$ java -version

してなんか出てればOK

HomebrewでインストールできるJDKまとめ(2019年11月時点) - Qiita

java のバージョン切り替え

  • アプリケーション開発する分にはjavaのバージョン切り替えたいことはあまりないはず
  • 僕は稀にローカル開発環境で異なるjavaを使って動作確認をしたいことがあるので、javaのバージョンをシュシュっと切り替えるために shyiko/jabba: (cross-platform) Java Version Manager を使っています。使い方はREADME読めば分かるはず
  • 他には jenv/jenv: Manage your Java environment とか

sbt のインストール

scala の主流なビルドツールである sbt - The interactive build tool をダウンロードします

$ brew install sbt
  • ここでダウンロードするsbtのバージョンはそんなに気にしなくて良いです
  • ここでダウンロードするsbtはlauncher、プロジェクト毎の設定で実際に利用するsbtのバージョンを指定できる

新しくsbtのプロジェクトを作る

$ sbt new scala/hello-world.g8
[info] welcome to sbt 1.4.4 (AdoptOpenJDK Java 11.0.9)
[info] set current project to tanishiking (in build file:/Users/tanishiking/src/github.com/tanishiking/)
[info] set current project to tanishiking (in build file:/Users/tanishiking/src/github.com/tanishiking/)

A template to demonstrate a minimal Scala application

name [Hello World template]: hello

Template applied in /Users/tanishiking/src/github.com/tanishiking/./hello

hello ディレクトリ以下に以下のようなプロジェクトが出来ます。

$ tree
.
|-- build.sbt
|-- project
|   `-- build.properties
`-- src
    `-- main
        `-- scala
            `-- Main.scala
  • build.sbt
  • project/build.properties
    • sbt.version=1.4.3 みたいなのが書かれてるはず。ここで利用するsbtのバージョンを指定するよ
    • ルートディレクトリで sbt を起動するとここに書かれてるバージョンのsbtがダウンロードされる

sbt を立ち上げてみる

$ sbt
[info] [launcher] getting org.scala-sbt sbt 1.4.3  (this may take some time)...
...
...
[info] welcome to sbt 1.4.3 (AdoptOpenJDK Java 11.0.9)
[info] loading project definition from /Users/tanishiking/src/github.com/tanishiking/hello/project
[info] loading settings for project hello from build.sbt ...
[info] set current project to hello-world (in build file:/Users/tanishiking/src/github.com/tanishiking/hello/)
[info] sbt server started at local:///Users/tanishiking/.sbt/1.0/server/baf7ac7b489b491bdcaa/sock
[info] started sbt server
sbt:hello-world>
sbt:hello-world> compile
[info] compiling 1 Scala source to /Users/tanishiking/src/github.com/tanishiking/hello/target/scala-2.13/classes ... update 0s
[success] Total time: 3 s, completed Dec 2, 2020, 9:42:12 PM
sbt:hello-world> run
[info] running Main
Hello, World!
[success] Total time: 0 s, completed Dec 2, 2020, 9:42:18 PM
  • sbt は $ sbt compile のように shell から実行することも出来ますが、開発中は sbt は立ち上げっぱなしにしておくことが推奨されています
  • なぜなら
    • sbt を起動するたびにJVMが起動することになるので時間かかる
    • sbt は起動している限り同じ同じScalaコンパイラが利用されるので、compileを繰り返すことでScalaコンパイラのJITが温まっていって高速にコンパイルが動くようになっていく

REPL を立ち上げてみる

sbt を起動して、そこから console と打ってみましょう

sbt:hello-world> console
[info] Starting scala interpreter...
Welcome to Scala 2.13.3 (OpenJDK 64-Bit Server VM, Java 11.0.9).
Type in expressions for evaluation. Or try :help.

scala>

sbt console からなら sbt でダウンロードした依存ライブラリも import 出来たりするので便利


vscode のセットアップ

最近のScalaのIDEは

という感じになっています。metals は scalameta という Scala の解析ツールセットをベースにしたLanguage Server Protocol 実装で IntelliJ Scala に次ぐシェアを誇る (https://scalacenter.github.io/scala-developer-survey-2019/) 開発ツールです。

scalameta.org

先程のディレクトリでVSCode を立ち上げ

$ code .

f:id:tanishiking24:20201202222158p:plain
vscode の extension から metals を検索してダウンロード

ダウンロードが完了したら build.sbt や *.scala ファイルを開いてみましょう。以下のようなポップアップが出てくるので Import build を押して暫くお待ち下さい。

f:id:tanishiking24:20201202222538p:plain
Import build を押してください

これでセットアップ完了です

間違えて Import build しそこねた人は VSCode のコマンドパレットを開いて > metals: Import build を実行してね。

pro tip

なんかIDEがcomopletionとか返してくれなくなったときは一度 .metals と .bloop というディレクトリを削除してVSCodeを再起動しましょう。(IDEのサーバー安定させたいと思っている)


コードフォーマット

scalameta.org を使いましょう

  • CLI / sbt plugin / IDE から使えるようになってるけど基本的には sbt plugin か IDE から使うのが個人的におすすめ
  • プロジェクトルートに .scalafmt.conf を作って version=2.7.4 とか書いてください

VSCode からやる場合

  • VSCode のコマンドパレットを開いて > Format Document を実行してみましょう。開いているファイルに対してフォーマットが実行されます。
  • .scalafmt.conf が存在しない場合は以下のようなポップアップが出てくるので Create '.scalafmt.conf' を押して勝手にファイルを作ってもらったりしましょう。
  • VSCode の Format On Save を有効にすると save 時に勝手にフォーマットしてくれるようになる

f:id:tanishiking24:20201202222939p:plain
コードフォーマット

sbt から使う場合

  • scalameta/sbt-scalafmt: sbt plugin for Scalafmt を使いましょう
  • project/plugins.sbt に以下のように書いて sbt を起動します
    • 紛らわしいのですが、sbt-scalafmt のバージョンと、上に書いた scalafmt のバージョンは完全に独立しています。sbt-scalafmt は scalafmt 本体をダウンロードしてきて、それを使ってフォーマットを実行するやつ
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")

sbt を立ち上げ以下のコマンドを打つことで全てのファイルをフォーマットする

sbt:hello-world> scalafmtAll

詳しくは

https://scalameta.org/scalafmt/docs/installation.html#task-keys


Linter

Scala ってデファクトな感じの Linter がないんですよね

一応カスタマイズしやすくて将来的に Scala3 との互換性も保たれそうな Linter(Refactoring tool) としては scalafix が有望、他には WartRemover とかかなぁだけど、そんなに使われてる印象ない

scalacenter.github.io

www.wartremover.org


Worksheet 機能を使ってみよう

  • worksheet 機能は高級REPLみたいな機能? Scala の標準ライブラリの挙動を確認したりするのに便利
    • goto definition などの IDE の機能のついた REPL みたいに考えると良さそう
  • 詳しくは https://scalameta.org/metals/docs/editors/vscode.html#worksheets

コマンドパレットから New Scala File を選び、Worksheets を選ぶ。

f:id:tanishiking24:20201203003822p:plain

xxx.worksheet.sc というファイルができるので、そこに適当な scala スクリプトを書いてみよう。以下のような感じでコメントに評価結果が表示される。

f:id:tanishiking24:20201203004057p:plain