Error downloading org.scalameta:semanticdb-scalac_2.13.7:4.4.28 や scalafix-test-kit_2.12.13:0.9.29 と言われたら

この記事について

  • 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 は実際には下記の様に指定されている。

https://github.com/scalacenter/sbt-scalafix/blob/b7b890d00598a574b9d4ea88e4f42168cc83765c/src/main/scala/scalafix/sbt/ScalafixPlugin.scala#L91-L94

    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製ライブラリは%%を使うと覚えておくと良い。

参考

余談2: scalametaのバージョンはどう指定されているか?

sbt-scalafix version=0.9.31 の場合、scalametaのバージョンは4.4.28と解決される。

これは

をみると 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になっている

解決方法

以下のような要領で使えるバージョンを探しましょう