scalameta / scalafmt

Code formatter for Scala
http://scalameta.org/scalafmt
Apache License 2.0
1.44k stars 277 forks source link

`danglingParentheses.callSite = false` should never result in non-compiling code for multiline lambdas #4569

Open djneades opened 4 days ago

djneades commented 4 days ago

Configuration (required)

version = "3.8.4-RC2"
runner.dialect = scala3
danglingParentheses.callSite = false

Command-line parameters (required)

When I run scalafmt via CLI like this: scalafmt test.sc

Steps

Given code like this:

def fn1(arg: String, arg2: String)(f: String ?=> Unit): Unit =
  f(using arg)

def fn2(arg: String, arg2: String)(f: String => Unit): Unit =
  f(arg)

fn1(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"): env ?=>
    val x = env
    println(x)

fn2(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"): env =>
    val x = env
    println(x)

Problem

Scalafmt formats code like this:

def fn1(arg: String, arg2: String)(f: String ?=> Unit): Unit =
  f(using arg)

def fn2(arg: String, arg2: String)(f: String => Unit): Unit =
  f(arg)

fn1(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"): env ?=>
  val x = env
  println(x)

fn2(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"): env =>
  val x = env
  println(x)

Expectation

I should like the formatted output to compile. However, the reformatted code does not because the lambda bodies are insufficiently indented:

> scala-cli test.sc
Compiling project (Scala 3.5.2, JVM (23))
[error] ./test.sc:9:63
[error] end of statement expected but '?=>' found
[error]   arg2 = "the quick brown fox jumped over the lazy dog"): env ?=>
[error]                                                               ^^^
[error] ./test.sc:13:1
[error] '}' expected, but unindent found
[error] fn2(
[error] ^^^
[error] ./.scala-build/q_1deee6db16-831d1d41ff/src_generated/main/test.scala:4:12
[error] Not found: test_sc
[error] def args = test_sc.args$
[error]            ^^^^^^^
[error] ./test.sc:9:59
[error] Not found: type env
[error]   arg2 = "the quick brown fox jumped over the lazy dog"): env ?=>
[error]                                                           ^^^
[error] ./test.sc:11:11
[error] Not found: x
[error]   println(x)
[error]           ^
Error compiling project (Scala 3.5.2, JVM (23))
Compilation failed

Workaround

Set danglingParentheses.callSite = true or set newlines.beforeCurlyLambdaParams = always.

kitbellew commented 4 days ago

what about

fn3(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"):
    val x = env
    println(x)

does it also require indent relative to arg2 and not fn3?

kitbellew commented 4 days ago

@odersky is this expected behaviour? does arg2 start a significant-indentation region?

doesn't look like it:

djneades commented 4 days ago

@kitbellew Hmm, no, the extra indentation is not required there. Curious. This compiles without problem:

def fn3(arg: String, arg2: String)(f: => Unit): Unit =
  f

fn3(
  arg = "blue sleeps faster than tuesday",
  arg2 = "the quick brown fox jumped over the lazy dog"):
  val x = "Hello"
  println(x)
kitbellew commented 4 days ago

@djneades in reading section 2.2.2, i interpret it as stipulating indentation should be relative to enclosing region (which should be fn).

hence, this behaviour might be a compiler bug.

djneades commented 4 days ago

@kitbellew Understood, thank you!