+
Executes all of the specified tasks concurrently.
```
---
class: middle
- アルプにおけるsbtのsub projectは60以上ある
- 先ほどのsbtのallに渡す引数生成がだるい
- 次どこをコンパイル通せばいいのか?が分かりにくい
---
class: middle
やりたいことや方針
- どこがScala 3対応済、未対応なのか?を可視化したい
- できるだけ細かくやっていきたい
- sbtのallに渡す引数を半自動で生成したい
- 次にどのsub projctの対応をやればいいのか?がわかるようにしたい
---
class: middle
- とあるsbt pluginを使いつつ拡張した仕組み定義
- https://github.com/dwijnand/sbt-project-graph
- https://gist.github.com/xuwei-k/4469101194f6a192eb3a1c71444741ea
---
class: middle
---
class: middle
## Scala 3対応の現状
- Spark除いてtestコード含めてcompileは通りそうな状態
- これからtest通していく予定
- 実際に動かすには、結局ライブラリ待ちも多少ある
- 出したpull req 60個以上
---
class: middle
## Scala 3関連で具体的にやったことをひたすら話していくよ
- +と-は変更行数です
- `#` のものはpull req番号だが、資料作る都合で付けただけ
---
class: middle
依存ライブラリ系
- 全く使っていない依存ライブラリや設定削除 #8541 +0 -8
- circeの依存整理 #8544 +1 -12
- kind-projectorの依存をCrossVersion.fullにして最新に #8545 +7 -8
- semanticdbの依存の書き方を変更 #8560 +9 -1
- 明示的な scala-java8-compat の依存の記述削除 #8599 +3 -4
- 意味がないcatsの明示的依存削除 #8597 +0 -1
- scala-parallel-collectionsを最新に更新 #8613 +1 -1
- 某libraryが色々厳しいので改変しつつ必要な部分だけ組み込み #8614 +290 -10
- scala-parallel-collectionsの依存の書き方修正(Scala 3準備) #8885 +2 -2
- circe-generic-extrasの依存定義を必要なところのみに移動 #9018 +9 -5
- Scala 3準備のために org.jetbrains annotations の依存追加 #8916 +10 -0
---
class: middle
ビルド設定
- wartremover追加 #8641 +12 -0
- wartremover自体はむしろScala 3未対応だが、Scala 3で非推奨な機能の警告出すのに使う
- buildファイル内でScala 3の準備のための設定追加 #8790 +14 -1
- implicitに型が書いてなかったら警告するscalafix rule追加 #8948 +1 -0
---
class: middle
コード修正
- 非推奨なscala.Appをやめて明示的なmain定義 #8665 +401, −234
- procedure syntax修正 #8668 +6 −5
- wartremoverで非推奨なscala.Appを使用禁止に #8670 +4 -1
- Scala 3で動かないのでcirceのJsonCodec全て削除 #8700 +1041 −395
- 呼び出し側と定義側で括弧の有無揃える #8768 +26 −27
- Scala 3で消えるdo-whileを書き換え #8779 +3 -2
---
class: middle
コード修正
- Scala 3に備えてkind-projectorでのinfixやめる #8783 +6 -6
- コンパイルエラーになる型パラメーターと同じtype member削除 #8784 +0 -2
- Scala 3の準備のためにshepeless使った3で動かない部分を分割 #8791 +135 −109
- shapeless 2に依存した未使用のclass削除 #8792 +0 -62
- Scala 2.13での警告修正(呼び出しと定義の括弧の付与揃える) #8796 +5 -5
- overrideしてsub typeを返している場合に型を明示(Scala 3準備) #8857 +5 -5
- exportがScala 3の予約語なのでバッククオートで囲う #8866 +6 -6
- 重複している必要ないimplicit削除 #8871 +7 -7
- scalatestのMatcherのimplicit defが名前指定でimportされてるのを修正 #8874 +2 -2
- shapelessのHListの書き方修正(Scala 3準備) #8880 +75 −72
- パターンマッチ部分に型を書くと逆にエラーになる場合があったので型を消す #8886 +4 -5
---
class: middle
コード修正
- Function1の引数に必ず括弧を付与 #8887 +49 −48
- https://github.com/xuwei-k/scalafix-rules/commit/384782c38bc688eaa1acec57d30b2c2db3881391
- Scala 3で自動で導出されないのでUnitに対するテスト用のインスタンス明示的に追加 #8890 +4 -0
- cats.implicitsをcats.syntax.allに置き換え #8908 +185 −213
- https://github.com/typelevel/cats/issues/4138
- Scala 3 bug回避のためcompanion objectのcaseを消す #8910
- https://github.com/lampepfl/dotty/issues/12919
- case classではないclassのEncoderでmacro使うのやめる(Scala 3準備) #8911 +13 −3
- case classでないものに対するdervingができないので導出された型クラスインスタンスの使用やめる #8914 +4 -4
- 重複しているimplicit削除 #8918 +1 -1
- shapeless 2依存でそのままでは動かないものを削除、書き換え #8953 +7 -51
- 使ってないのにcirce-generic-extrasのConfigを生成している箇所を削除 #8961 +1 -5
---
class: middle
scalikejdbcアップデート
scalikejdbcのbatchByNameでscala.Symbol使っている箇所修正 #8723 +29 -29
scalikejdbcをupdateする準備として括弧削除 #8907 +113 −109
scalikejdbcのapplyに括弧を付与(scalafixで) #8952 +247 −226
scalikejdbcを3.5.0から4にアップデート #8999 +25 −13
---
class: middle
## mockito-scalaやめる
#9006 +4 -13
#9007 +399 −395
#9004 +255 -32
---
class: middle
ひたすらimplicitに型を付与
implicitに型書きつつvalue classに #8760 +12 −8
#8777 +167 −107
#8653 +37 -35
#8865 +20 -21
#8876 +43 -29
#8895 +44 -32
#8923 +41 -20
#8931 +49 -46
---
class: middle
すぐに必須では無い?が警告修正系
- objectに対するfinal削除 #8780 +2 -2
- Unreachable Warning修正 #8888 +0 -3
- テスト内部の重複している type R 削除
- null以外でmatchする可能性がないパターンマッチのcaseを消す #8955 +13 −67
---
class: middle
sub typeが返らない件
```scala
Welcome to Scala 3.1.1 (1.8.0_322, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> trait A
|
| class B extends A
|
| trait X {
| def foo: A
| }
|
| class Y extends X {
| override def foo = new B // ここの型を省略するかどうか?
| }
|
| val y = new Y
|
| y.foo // Scala 3ではBではなくA型でかえる。Scala 2ではB
```
---
class: middle
implicitを2回書くの禁止
```scala
Welcome to Scala 3.1.1 (1.8.0_322, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> class A(a: Int)(
| implicit b: String,
| implicit val c: Boolean)
-- [E015] Syntax Error: --------------------------------------------------------
3 | implicit val c: Boolean)
| ^^^
| Repeated modifier implicit
```
---
class: middle
HListの件でpull reqに書いた説明
HListのapplyは
「implicit parameterでScala 2 macroで生成されたもの(Generic)」
を受け取っているので、このままではScala 3でコンパイルが通らないため。
https://github.com/milessabin/shapeless/blob/v2.3.8/core/src/main/scala/shapeless/hlists.scala#L69
https://github.com/milessabin/shapeless/blob/v2.3.8/core/src/main/scala/shapeless/generic.scala#L167
このapplyというのは、任意のcase classやTupleを受け取って、HListに変換するためのメソッドである。
可変長引数のように見えるが、これはTupleを渡している。
implicit parameterでScala 2 macroで生成されたものに関しては、無理やり頑張ってScala 3のmacroで生成するのは不可能ではないが、Scala 2のimplicitが勝手にスコープに入るため、もしapply使い続けるならば、「Scala 2と3でソースコード分けつつ、implicitを明示的に渡す」といった変なことをやらないといけないので、HListをそのまま書く方式に変えた。
これは結局HListのapplyで返ってくる結果そのものなので、compile時の処理的にも実行時の処理的にも、この方が処理することが減るはずである。
ある程度は以下のscalafixで自動修正したが、formatが崩れたりコメントが消えてしまったところやimportを手動で修正した。
---
class: middle
### shapeless 2のHListをScala 3で使う
Before (Scala 2のmacro依存)
```scala
HList(a, b, c)
```
After (とりあえずScala 3で動く)
```scala
a :: b :: c :: HNil
```
---
class: middle
```scala
import scalafix.Patch
import scalafix.v1.SyntacticDocument
import scalafix.v1.SyntacticRule
import scala.meta.Term
class ShapelessHListApply extends SyntacticRule("ShapelessHListApply") {
override def fix(implicit doc: SyntacticDocument): Patch = {
doc.tree.collect {
case t @ Term.Apply(Term.Name("HList"), args) =>
Patch.replaceTree(
t,
args.mkString("(", " :: ", " :: HNil)")
)
}.asPatch
}
}
```
---
class: middle
---
class: middle
## えっ、mockito-scala
辛すぎ・・・!?
---
class: middle
## mockito-scala
- coreがscalatestに依存してしまってるので、デフォルトではfor3Use2_13で誤魔化してコンパイル通すだけでも厳しい!
- 待っていても対応される可能性は低い
- I've been pretty busy at work and had 0 time. Maybe someone in the community wants to step up?
---
class: middle
## デフォルト引数mock問題
```scala
class X {
def a(b: Boolean = true): Int = ???
}
val x = new X
x.a()
```
---
class: middle
生成されるコード
```scala
class X {
def a(b: Boolean): Int = ???
def a$default$1: Boolean = true
}
val x = new X
x.a(x.a$default$1)
```
---
class: middle
mockito使ったテストコード例
```scala
val x = mock[X]
when(x.a()).thenReturn(3)
// 途中省略
verify(x, times(1)).a()
```
---
class: middle
生成されるコード
```scala
val x = mock[X]
when(x.a(x.a$default$1)).thenReturn(3)
// 途中省略
verify(x, times(1)).a(x.a$default$1)
// x の `a$default$1` を2回呼んでるよ m9(^Д^) って怒られる
```
---
class: middle
内部実装依存な力技。
これらのデフォルト引数扱うだけなら、macroもreflectionも必要なかった
```scala
if (
realMethod.isInvokable &&
(
methodName.contains("$default$") ||
ExecuteIfSpecialised(methodName)
)
) i.callRealMethod()
```
https://github.com/mockito/mockito-scala/blob/3f7dbfaac58/common/src/main/scala/org/mockito/internal/handler/ScalaMockHandler.scala#L26-L27
---
class: middle
shapelessはcase classでなくても勝手にいい感じにやるがScala 3だと普通には無理
https://github.com/milessabin/shapeless/blob/v2.3.8/core/src/main/scala/shapeless/generic.scala#L672
```scala
def isCaseClassLike(sym: ClassSymbol): Boolean
def isCaseAccessorLike(sym: TermSymbol): Boolean
```
---
class: middle
scalikejdbcのapply括弧の自動付与scalafix
```scala
import scalafix.Patch
import scalafix.v1.SyntacticDocument
import scalafix.v1.SyntacticRule
import scala.meta.Term
class ScalikejdbcApplyParentheses extends SyntacticRule("ScalikejdbcApplyParentheses") {
override def fix(implicit doc: SyntacticDocument): Patch = {
doc.tree.collect {
case a @ Term.Select(
Term.Select(_, Term.Name("list" | "single" | "update")),
apply @ Term.Name("apply")
) if a.parent.forall(!_.is[Term.Apply]) =>
Patch.addRight(apply, "()")
}.asPatch
}
}
```
---
class: middle
type paramとtype member同じだと怒られる
```scala
Welcome to Scala 3.1.1 (1.8.0_302, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> trait A[B] { type B }
-- [E161] Naming Error: --------------------------------------------------------
1 |trait A[B] { type B }
| ^^^^^^
| B is already defined as type B
1 error found
```
---
class: middle
自作Scala 3関連scalafix
- AddExplicitImplicitTypes
- AddLambdaParamParentheses
- CirceCodec
- ExplicitImplicitTypes
- KindProjector
- LambdaParamParentheses
- ObjectSelfType
- ReplaceSymbolLiterals
- Scala3ImportRewrite
- Scala3ImportWarn
- Scala3Placeholder
- ScalaApp
---
class: middle
OSSでの対応含め、細かいこと話そうとすればいくらでもある気がするけど、ひとまず終わり。
質問タイム?