というパターンがScala標準で不可能な気がするので、build.sbtで頑張るサンプルを作ってみたのですが、Scala標準で不可能ですよね???
どういうパターンか?をもう少し詳細に説明すると
- 直せる警告は出来るだけはやく気がついて、はやく直した方がいい
- とはいえ、簡単に直せない警告もある
- あるいは、重要ではない警告(unused importとか?)は、最悪merge後に別に直す、とかにしたほうが、開発の効率はいい場合もある?
- Scala標準では警告関連だと、以下のような色々な機能がある
- しかしそれらを組み合わせても微妙にやりたいことが足りない気がしてきた
- CIで
-Werror
にしてしまうのは、原理的に警告が増えたままmergeされなくなって、簡単に設定可能で便利だが、割と重大だと思うデメリットがある@nowarn
や-Wconf
で抑制するパターンが多くなり過ぎてしまうと厳しい。@nowarn
の追加自体を別途検知する、みたいなことは原理上不可能ではないが、イタチごっこというか、何のためにやってるのかよくわからなくなるというか、buildやコードが変に複雑になり過ぎる@nowarn
で抑制するより「簡単には直せないけど頑張れば直せるもの」に関して、「警告は警告のままにして出したまま」の方が「これ直さないといけないなぁ〜」というのが常に意識されやすいはず?- 理由を書きつつ
@nowarn
なら、まだマシな可能性があって、警告を避けるためだけに謎に変な書き方されたら最悪である
- そういうデメリットがあって、警告のdiffを出すsbt plugin作ったりした https://xuwei-k.hatenablog.com/entry/2022/10/27/103253
-Wconf
で柔軟に警告にするものとエラーにするものを選べるが、自分が知る限り表題の「基本的には警告をエラーにしたいが、特定の警告を警告のままにしたい」は不可能ですよね???
書いてみたサンプルの build.sbt
が以下です。
import sbt.internal.inc.Analysis scalaVersion := "2.13.16" scalacOptions += "-deprecation" Seq(Compile, Test).map { x => (x / compile) := { val res = (x / compile).value val warnings = res.asInstanceOf[Analysis].infos.allInfos.values.flatMap(i => i.getReportedProblems ++ i.getUnreportedProblems ).collect { case p if p.severity() == xsbti.Severity.Warn => p }.filterNot{ p => // 特定の警告だけ除外 // 失敗させるかどうか?の判断から除外するだけで、 // あくまで警告としてはそのまま全て表示される // https://github.com/sbt/sbt/blob/f284e809d41f27ceefa/internal/util-interface/src/main/java/xsbti/Problem.java#L17-L24 p.message().contains("type Stream in package scala is deprecated") }.toList assert(warnings.isEmpty, s"警告があったので `${x.id}/compile` のtaskを失敗させます") res } }
これは scala.Stream
の警告だけを警告のままにして、その他の警告があったらcompileを失敗させます。
あくまで結果のエラーメッセージであって、compilerが持ってる情報よりは少ないというか加工済みなので、 -Wconf
ほどには柔軟ではないですが、実用的にはそこまで困らないはず・・・?
( -Wconf
はsite、origin、since、categoryなどの色々な概念で指定が可能)
messageでやってますが、positionなども取れるので、それを使ったfilterも可能です。
あくまでサンプルで、現状では特に実運用してないので、細かい部分が雑ですが。
場合によってはこれsbt pluginにするか・・・? 🤔