Help us understand the problem. What is going on with this article?

scalac にもっと警告してもらう

More than 5 years have passed since last update.

これはScala Advent Calendar 2014 6日目の記事です。

Scala はコンパイルが遅いことで有名ですが、コンパイルの嬉しいところは、実行前に沢山のプログラムミスやミスっぽいものをキャッチできることです。
C を書くときは -Wall -Wextra -Wpedantic あたりをつけるとたくさん警告だしてくれてありがたいですね。Scala の場合もたくさん警告出して欲しい。scalac 2.11.4 にある警告関連のオプションを見てみましょう。

オプションの区分

とその前に、scalac オプションの区分についておさらいです。オプションは

  • -X や -Y 以外から始まる普通のオプション
  • -X から始まる advanced オプション
  • -Y から始まる private オプション

に分類されています。それぞれ scalac -help, scalac -X, scalac -Y でヘルプを見ることが出来ます。
advanced や private の意味するところは正直良くわかっていませんが、普通のオプションより-Xのほうが、-Xより-Yのほうが変化が激しいようです。

普通の警告オプション

普通のオプションで警告関連のものは次の3つです。

  • -deprecation: @deprecated なAPIが使われている箇所を警告します
  • -feature: langauge feature の import が必要な箇所を警告します
  • -unchecked: ヘルプによると Enable additional warnings where generated code depends on assumptions. とのことです(が、何のことだかよくわかってません…)

とりあえず、この3つは付けましょう。

advanced 警告オプション

advanced な警告関連のオプションは -Xlint-Xfatal-warnings です。

-Xlint は様々な警告を有効にします。有効になる警告は scalac -Xlint:help で一覧できます(scala 2.11.2 以降)。2.11.4 で実行してみるとこうなりました。

Enable or disable specific warnings
  adapted-args               Warn if an argument list is modified to match the receiver.
  nullary-unit               Warn when nullary methods return Unit.
  inaccessible               Warn about inaccessible types in method signatures.
  nullary-override           Warn when non-nullary `def f()' overrides nullary `def f'.
  infer-any                  Warn when a type argument is inferred to be `Any`.
  missing-interpolator       A string literal appears to be missing an interpolator id.
  doc-detached               A ScalaDoc comment appears to be detached from its element.
  private-shadow             A private field (or class parameter) shadows a superclass field.
  type-parameter-shadow      A local type parameter shadows a type already in scope.
  poly-implicit-overload     Parameterized overloaded implicit methods are not visible as view bounds.
  option-implicit            Option.apply used implicit view.
  delayedinit-select         Selecting member of DelayedInit
  by-name-right-associative  By-name parameter of right associative operator.
  package-object-classes     Class or object defined in package object.
  unsound-match              Pattern match may not be typesafe.

-Xlint とだけ指定すれば、これら全てが有効になります。とにかく一杯警告出して欲しいので -Xlint も指定しましょう。

-Xfatal-warnings は警告をエラーとして扱うオプションです。
個人的には付けるほうが好みですが、どうしても消せない警告があるときにコンパイルできずに困るかもしれません。とりあえず付けた状態で始めて、どうしようもなくなったら外すという運用が良いと思います。

private 警告オプション

scalac -Y 2>&1 | grep warn するとこのようになります。

  -Yinline-warnings                       Emit inlining warnings. (Normally surpressed due to high volume)
  -Ywarn-adapted-args                     Warn if an argument list is modified to match the receiver.
  -Ywarn-dead-code                        Warn when dead code is identified.
  -Ywarn-inaccessible                     Warn about inaccessible types in method signatures.
  -Ywarn-infer-any                        Warn when a type argument is inferred to be `Any`.
  -Ywarn-nullary-override                 Warn when non-nullary `def f()' overrides nullary `def f'.
  -Ywarn-nullary-unit                     Warn when nullary methods return Unit.
  -Ywarn-numeric-widen                    Warn when numerics are widened.
  -Ywarn-unused                           Warn when local and private vals, vars, defs, and types are are unused.
  -Ywarn-unused-import                    Warn when imports are unused.
  -Ywarn-value-discard                    Warn when non-Unit expression results are unused.

いくつかは -Xlint とかぶっているようですね。
かぶっていないものは

  • -Ywarn-dead-code
  • -Ywarn-numeric-widen
  • -Ywarn-unused
  • -Ywarn-unused-import
  • -Ywarn-value-discard

の5つです。

Scala のバージョンによってあったりなかったりすると思うので、利用できる場合には利用すると良いかと思います。

ちなみに -Ywarn-unused-import を指定すると、 sbt consoleimport するたびに警告されます。 -Xfatal-warnings と同時に指定している場合はエラーになってしまいます。
:paste で import 文と使用箇所をまとめて貼り付けるか、console を使う時だけ -Ywarn-unused-import-Xfatal-warnings のどちらかを外すかで回避します。
console で不便なことを差し引いても警告が出たほうがうれしいですね!

sbt での指定方法

scalac コマンドを直接使う時はコマンドライン引数として指定しますが、sbt を使っている方が多いと思います。
sbt での指定方法は build.sbtscalacOptions ++= Seq(/* ここに警告オプション */) です。

まとめ

Scala 2.11.4 で沢山警告をだすには、次のように build.sbt に書きます。

build.sbt
scalacOptions ++= Seq(
  "-deprecation",
  "-feature",
  "-unchecked",
  "-Xlint",
  "-Ywarn-dead-code",
  "-Ywarn-numeric-widen",
  "-Ywarn-unused",
  "-Ywarn-unused-import",
  "-Ywarn-value-discard"
  // 警告をエラーにする(お好みに応じて)
  , "-Xfatal-warnings"
)

諸般の事情で 2.11.4 を使っていない人も居ると思います。Scala のバージョンによって存在する警告オプション(特に -Ywarn-なんとか )は異なるので、 scalac -help, scalac -X, scalac -Y を参照して存在する警告オプションを片っ端から有効にしましょう。

私たちが間違った方向に行くのをいつも諌めてくれる scalac 先生に感謝しましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away