scalariformかけるとDSL形式のインデントが崩れる

scala開発関連

scalikejdbcやWSClientなんかでDSLっぽく書いたプログラムがscalariformかけるとインデント崩れする問題を解決するために調べたメモとなります。

scalariformとは

コンパイルと同時にコード整形してくれる便利なツールです。コードの書き方が統一されるので大規模であればあるほど保守性が高くなるはず。

コード整形の細かい調整はこちら

自分が使っている設定抜粋

参考までに自分が使っているbuild.sbtの設定の抜粋です。

Seq(
  scalariformPreferences := scalariformPreferences.value
    .setPreference(AlignParameters, true)
    .setPreference(AlignArguments, true)
    .setPreference(AlignSingleLineCaseStatements, true)
    .setPreference(DoubleIndentConstructorArguments, true)
    .setPreference(DoubleIndentMethodDeclaration, true)
    .setPreference(IndentWithTabs, false)
    .setPreference(IndentSpaces, 2)
    .setPreference(PlaceScaladocAsterisksBeneathSecondAsterisk, true)
    .setPreference(DanglingCloseParenthesis,  scalariform.formatter.preferences.Force)
)

そのままコード整形すると

クラス定義は省略しますがDSLっぽく書くと各ステップごとにインデントが深くなってしまいます。(インデント2スペースなので少しわかりづらいかもしれませんが・・・)

  def test(): Unit = {
    Await.result(
      ws.url(
        ""
      ).withHttpHeaders(
          ("Content-Type", "application/json")
        ).post(
            Json.obj(
              "submittedAt" -> System.currentTimeMillis(),
              "fields" -> Json.arr(
                Json.obj(
                  "name" -> "email",
                  "value" -> "test@shimer-system.com"
                )
              )
            ).toString()
          ).map { res =>
              println("======================")
              println(res.status + ":" + res.statusText)
              println(res.body)
              println("======================")
            },
      Duration.Inf
    )
  }

formatのON/OFFを切り替える方法

scalariformの丁度いい設定が見つからなかったので少し強引ですが、コメントで
// format: OFF
または
// format: ON
をいれることでフォーマット対象のコードを細かく指定できます。

  def test(): Unit = {
    // format: OFF
    Await.result(
      ws.url(
        ""
      ).withHttpHeaders(
        ("Content-Type", "application/json")
      ).post(
        Json.obj(
          "submittedAt" -> System.currentTimeMillis(),
          "fields" -> Json.arr(
            Json.obj(
              "name" -> "email",
              "value" -> "test@shimer-system.com"
            )
          )
        ).toString()
      ).map { res =>
        println("======================")
        println(res.status + ":" + res.statusText)
        println(res.body)
        println("======================")
      },
      Duration.Inf
    )
    // format: ON
  }
©2018 LLC Shimer-System.
image/svg+xml