scalafmt icon indicating copy to clipboard operation
scalafmt copied to clipboard

Can't align def and val on the same token

Open Driox opened this issue 2 years ago • 1 comments

I can't align def and val on the same token This used to work on previous version, like 3.5.9

NB: this issue follow the discussion here

Configuration (required)

version = "3.7.1"
project.git = true
runner.dialect = scala213
maxColumn = 120
align.preset = most
align.allowOverflow = true
align.multiline = true
continuationIndent {
  defnSite = 2
  extendSite = 2
  withSiteRelativeToExtends = 2
}
assumeStandardLibraryStripMargin = true
docstrings.style = keep
newlines.source = keep
lineEndings = preserve
includeCurlyBraceInSelectChains = true
danglingParentheses {
  defnSite = true
  callSite = true
  ctrlSite = true
}

spaces {
  inImportCurlyBraces     = true
  afterKeywordBeforeParen = false
}
optIn.annotationNewlines = true

rewrite.rules = [SortImports, PreferCurlyFors]
rewrite.redundantBraces.generalExpressions = false
rewrite.redundantBraces.methodBodies = false
rewrite.redundantBraces.includeUnitMethods = false
rewrite.redundantBraces.stringInterpolation = false

align.tokens.add = [
  { code = ":", owner = "Param" }
  { code = "=" }
  { code = "?|" }
  { code = "?|>" }
  { code = "|>" }
  { code = "withClue" }
]

Command-line parameters (required)

When I run scalafmt via CLI like this:

~/Dev/scala/sorus develop +2 !11 ?6 ❯ scalafmt                                                                                                                                                                                              11.0.12+0
'align.tokens.add' is deprecated; use align.tokens."+" instead.
Reformatting...
  100,0% [##########] 10 source files formatted

Steps

Given code like this:

package helpers.sorus

import scala.concurrent.duration._

class AuthenticationService() {

  private[this] def retry_count_cache_key(xxx: String) = s"some_very_very_very_very_very_very_very_very_very_very_very_long_string_$xxx"
  private[this] def retry_cache_key(xxx: String) = s"some_short_string$xxx"
  private[this] val retry_timing_in_seconds = 30 seconds
  val x                                     = "some_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_veryvery_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_long_string"
  val xx                       = "àç098098"
  val xxx                               = "àç098098"
  val xxxxx                                 = "àç098098"

  def coucou(): Int = {
    println(s"""
      ${retry_count_cache_key("123")}
      ${retry_cache_key("123")}
      $retry_timing_in_seconds
    """)

    12
  }
}

Problem

Scalafmt formats code like this:

package helpers.sorus

import scala.concurrent.duration._

class AuthenticationService() {

  private[this] def retry_count_cache_key(xxx: String) =
    s"some_very_very_very_very_very_very_very_very_very_very_very_long_string_$xxx"
  private[this] def retry_cache_key(xxx: String) = s"some_short_string$xxx"
  private[this] val retry_timing_in_seconds = 30 seconds
  val x                                     =
    "some_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_veryvery_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_long_string"
  val xx                                    = "àç098098"
  val xxx                                   = "àç098098"
  val xxxxx                                 = "àç098098"

  def coucou(): Int = {
    println(s"""
      ${retry_count_cache_key("123")}
      ${retry_cache_key("123")}
      $retry_timing_in_seconds
    """)

    12
  }
}

Expectation

I would like the formatted output to look like this:

package helpers.sorus

import scala.concurrent.duration._

class AuthenticationService() {

  private[this] def retry_count_cache_key(xxx: String) = s"some_very_very_very_very_very_very_very_very_very_very_very_long_string_$xxx"
  private[this] def retry_cache_key(xxx: String)       = s"some_short_string$xxx"
  private[this] val retry_timing_in_seconds            = 30 seconds
  val x                                                = "some_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_veryvery_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_long_string"
  val xx                                               = "àç098098"
  val xxx                                              = "àç098098"
  val xxxxx                                            = "àç098098"

  def coucou(): Int = {
    println(s"""
      ${retry_count_cache_key("123")}
      ${retry_cache_key("123")}
      $retry_timing_in_seconds
    """)

    12
  }
}

Note

this is the output when I switch version to 3.5.9

  • def and val are aligned according to =
package helpers.sorus

import scala.concurrent.duration._

class AuthenticationService() {

  private[this] def retry_count_cache_key(xxx: String) =
    s"some_very_very_very_very_very_very_very_very_very_very_very_long_string_$xxx"
  private[this] def retry_cache_key(xxx: String)       = s"some_short_string$xxx"
  private[this] val retry_timing_in_seconds            = 30 seconds
  val x                                                =
    "some_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_veryvery_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_long_string"
  val xx                                               = "àç098098"
  val xxx                                              = "àç098098"
  val xxxxx                                            = "àç098098"

  def coucou(): Int = {
    println(s"""
      ${retry_count_cache_key("123")}
      ${retry_cache_key("123")}
      $retry_timing_in_seconds
    """)

    12
  }
}

Driox avatar Feb 13 '23 18:02 Driox

@Driox unfortunately, for now, i don't know how to fix this problem.

it was probably introduced in #3335, to be able to align parameters on adjacent lines, as requested by another user. alas, your use case was not protected by regression tests at that time.

since you have both : and = in your list of tokens, for the def line in your example, : is in alignment position 1 and = is in position 2. however, for the val line, = is in position 1; it doesn't align with the previous = because positions don't match. if you remove : from your configuration, it should work.

to make this work, we'd have to rewrite the entire alignment logic, to be able to assign priority to alignment stops, remove assumptions about alignment stops being contiguous etc., and i don't have the time to do that.

kitbellew avatar Feb 18 '23 15:02 kitbellew