この記事について
- scalafixに依存しているプロジェクトでscalaのバージョンを上げるとタイトルのエラーが出る場合があるので原因などを整理したもの
- ちょっと前のメモ書きをブログ化してるので各種バージョンは古いです
各エラーについて
エラー1: Error downloading org.scalameta:semanticdb-scalac_2.13.7:4.4.28 と言われたら
原因
scalafixが依存しているsemantic DBのライブラリが存在していないことが原因
semanticdbのバージョンは Installation · Scalafix に従っていれば以下のようになっているはず。
semanticdbEnabled := true,
semanticdbVersion := scalafixSemanticdb.revision
semanticdbVersion
は実際には下記の様に指定されている。
val scalafixSemanticdb: ModuleID = scalafixSemanticdb(BuildInfo.scalametaVersion) def scalafixSemanticdb(scalametaVersion: String): ModuleID = "org.scalameta" % "semanticdb-scalac" % scalametaVersion cross CrossVersion.full
この例では実際には org.scalameta:semanticdb-scalac_2.13.7:4.4.28
と解決される(細かいバージョンはscalaとsbt-scalafixのバージョンで変化する)
今回の細かい値は以下のようになっていた。
- scalaVersion=2.13.7
- sbt-scalafix version=0.9.31
このライブラリがmaven上にpublishされていないことが依存が解決できないのが表題のエラーの原因。
publishされているかの確認は https://repo1.maven.org/maven2/org/scalameta/semanticdb-scalac_2.13.7/ に存在しているかで行える。
解決方法
単純にsemanticdbが存在しないことが原因なので、すでにpublish済みのsemanticdbバージョンを使えば良い。
sbt-scalafixでは scalafixSemanticdb(scalametaVersion: String)
で指定できるので、以下のように好きなように指定すれば良い。
import scalafix.sbt.ScalafixPlugin.autoImport.scalafixSemanticdb ... semanticdbVersion := scalafixSemanticdb("4.4.30").revision,
指定するバージョンは Central Repository: org/scalameta から semanticdb-scalac_${使いたいscalaバージョン}
配下にある最新のversionのものにすればよい。
例: Central Repository: org/scalameta/semanticdb-scalac_2.13.7/4.4.30 なら 4.4.30
を指定する。
余談
余談1: ワンポイントsbt
scalafixのコードのなかで CrossVersion.full
という指定が出てきていたので意味を整理しておく。
ライブラリのバージョン指定時に CrossVersion.full
が指定されていると "org.scalameta" % "semanticdb-scalac" % バージョン番号
が "org.scalameta" % "semanticdb-scalac_<scalaバージョン>:バージョン番号
として解決され、最終的に org.scalameta:semanticdb-scalac_2.13.7:4.4.28
という指定になる。
普段依存ライブラリを指定する場合は "org.scalameta" % "semanticdb-scalac" %% バージョン番号
のように %%
を使った指定を行うことが多いが、この場合は "semanticdb-scalac_<scalaバイナリバージョン>:バージョン番号
のように解決され、最終的に org.scalameta:semanticdb-scalac_2.13:4.4.28
のようにバイナリ互換性のあるバージョンまで(2.13.7ではなく2.13まで)を指定するようになっている。これは CrossVersion.binary
を指定するのと等しい挙動になる。
CrossVersionには他にCrossVersion.disableも存在するが、これは単にscalaバージョン番号を埋め込んでいないもの(javaのライブラリなど)の指定に用いる。
※ 通常はjava製ライブラリは%、scala製ライブラリは%%を使うと覚えておくと良い。
参考
- %と%%の違いとCrossVersionについて sbt Reference Manual — Cross-building
- 日本語記事 Scalaのcompiler pluginをCrossVersion.fullにするかCrossVersion.binaryにするか - xuwei-k's blog
余談2: scalametaのバージョンはどう指定されているか?
sbt-scalafix version=0.9.31 の場合、scalametaのバージョンは4.4.28と解決される。
これは
- sbt-scalafix
をみると scalafix-interfaces.properties
というリソースの scalametaVersion
に記されていることが分かる。
このファイルの場所はsbt-scalafixに依存している適当なプロジェクトで以下のようにすれば特定できる。
$ sbt > reload plugins ... > console scala> getClass.getClassLoader.getResource("scalafix-interfaces.properties") res0: java.net.URL = jar:file:/略/https/repo1.maven.org/maven2/ch/epfl/scala/scalafix-interfaces/0.9.31/scalafix-interfaces-0.9.31.jar!/scalafix-interfaces.properties
が、 GitHub - scalacenter/scalafix: Refactoring and linting tool for Scala のリポジトリを見てみるとそういったファイルは存在しない。
こういった場合は自動生成されている可能性があるので build.sbt
を探すと以下のように自動生成を行うタスクの記述がある
scalafix/build.sbt at v0.9.31 · scalacenter/scalafix · GitHub
これを見ると scalametaV
という変数を参照していることが分かるので
scalafix/Dependencies.scala at v0.9.31 · scalacenter/scalafix · GitHub
にある
val scalametaV = "4.4.28"
が該当する。
エラー2: not found scalafix-test-kit_2.12.13/0.9.29と言われたら
現象
- scalafix(scalafix-testkit)はscalaのメジャーバージョン(scala 2.12 or 2.13)だけでなくマイナーバージョン (2.12.13 or 2.12.14)のレベルまで依存している。
- scalafixとscalaのバージョンの組み合わせが悪いのでnot foundになっている
解決方法
以下のような要領で使えるバージョンを探しましょう