Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank Newlines between defs aren't enough to break alignment (3.0.0) #2750

Closed
mwachs5 opened this issue Sep 19, 2021 · 0 comments · Fixed by #2753
Closed

Blank Newlines between defs aren't enough to break alignment (3.0.0) #2750

mwachs5 opened this issue Sep 19, 2021 · 0 comments · Fixed by #2753

Comments

@mwachs5
Copy link

mwachs5 commented Sep 19, 2021

This template is a guideline, not a strict requirement.

  • Version: 3.0.0
  • Integration: command line
  • Configuration:
version = 3.0.0

maxColumn = 160
align.preset = most
continuationIndent.defnSite = 2

align.tokens."+" = [
  {
    code = "=",
    owners=[{regex="Term.Param|Defn|Term.Assign"}]
  },
  {
    code = ":",
    owners = [{regex="Term.Param|Decl.Def"}]
  },
]

Steps

Given code like this:

object Thing {

  def apply(foo: FooBaz.booberry, someInt: Int, booControl: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl)

  def apply(foo: FooBaz.booberry, someInt: Int)(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl = None)

  def apply(fooBaz: Int, someBooberry: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy = FooBaz.booberry, Some(someInt), booControl)

  def apply(fooBaz: Int)(implicit p: Parameters): TLNode =
    apply(policy = FooBaz.booberry, Some(someInt), booControl = None)
}

When I run scalafmt like this, where SmallTest.scala contains the code above

scalafmt --config <config file shown above> SmallTest.scala

Problem

Scalafmt formats code like this: (note added whitespace in the def lines)

object Thing {

  def apply(foo: FooBaz.booberry, someInt: Int, booControl: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl)

  def apply(foo:    FooBaz.booberry, someInt: Int)(implicit p:                            Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl = None)

  def apply(fooBaz: Int, someBooberry:        Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy = FooBaz.booberry, Some(someInt), booControl)

  def apply(fooBaz: Int)(implicit p:          Parameters): TLNode =
    apply(policy = FooBaz.booberry, Some(someInt), booControl = None)
}

Expectation

I would like the formatted output to look like this:
** I expect that blank lines between defs, regardless of multiline options, would be enough to "stop" the alignment.**

object Thing {

  def apply(foo: FooBaz.booberry, someInt: Int, booControl: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl)

  def apply(foo: FooBaz.booberry, someInt: Int)(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl = None)

  def apply(fooBaz: Int, someBooberry: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy = FooBaz.booberry, Some(someInt), booControl)

  def apply(fooBaz: Int)(implicit p: Parameters): TLNode =
    apply(policy = FooBaz.booberry, Some(someInt), booControl = None)
}

Workaround

I've found that by putting the def body in {...} it does do the alignment properly:

object Thing {

  def apply(foo: FooBaz.booberry, someInt: Int, booControl: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz = {
    apply(policy, Some(beatBytes), booControl)
  }

  def apply(foo: FooBaz.booberry, someInt: Int)(implicit p: Parameters): FooBaz = {
    apply(policy, Some(beatBytes), booControl = None)
  }

  def apply(fooBaz: Int, someBooberry: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz = {
    apply(policy = FooBaz.booberry, Some(someInt), booControl)
  }

  def apply(fooBaz: Int)(implicit p: Parameters): TLNode = {
    apply(policy = FooBaz.booberry, Some(someInt), booControl = None)
  }
}

And by adding the align.mutliline = false alignment it also does it "properly" as expected above, but I actually do want multiline alignment if there is no blank newline.

Also, If I put the input defs and bodies on one line and get scalafmt to pick where the line will be too long and needs to be broken down to the next line, things are "as I expect" though not optimal from an overall code appearance:

object Thing {

  def apply(foo: FooBaz.booberry, someInt: Int, booControl: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy, Some(beatBytes), booControl)

  def apply(foo: FooBaz.booberry, someInt: Int)(implicit p: Parameters): FooBaz = apply(policy, Some(beatBytes), booControl = None)

  def apply(fooBaz: Int, someBooberry: Option[OptionalBooberryParams])(implicit p: Parameters): FooBaz =
    apply(policy = FooBaz.booberry, Some(someInt), booControl)

  def apply(fooBaz: Int)(implicit p:   Parameters): TLNode = apply(policy = FooBaz.booberry, Some(someInt), booControl = None)

}

Notes

This seems somewhat related to the issue I reported in #2703 which was dismissed as user error, but I am still surprised that blank newlines "cancel" alignment in some scenarios but not all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant