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

Docstrings: use keep/fold/unfold in BlankFirstLine #3947

Merged
merged 1 commit into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4127,19 +4127,22 @@ the default `maxColumn`.
### `docstrings.blankFirstLine`

Controls whether to force the first line to be blank in a multiline docstring.
Keep in mind that some combinations of parameters are prohibited (e.g.,
`blankFirstLine=keep` contradicts with `style=Asterisk`).
Some values of [`docstrings.style`](#docstringsstyle) might take precedence.
Takes the following values:

- `keep`: preserves the first line as-is
- `fold`: will ensure there's no blank first line
(default; replaced `no` in v3.8.2)
- `unfold`: will enforce a blank first line
(replaced `yes` in v3.8.2)

> Since v2.7.5. Ignored for `docstrings.style = keep` or
> `docstrings.style = Asterisk` or
> `docstrings.wrap = no`.

```scala mdoc:defaults
docstrings.blankFirstLine
```

```scala mdoc:scalafmt
# do not force a blank first line
docstrings.blankFirstLine = no
docstrings.blankFirstLine = fold
docstrings.style = SpaceAsterisk
maxColumn = 30
---
Expand All @@ -4154,7 +4157,7 @@ val a = 1

```scala mdoc:scalafmt
# force a blank first line
docstrings.blankFirstLine = yes
docstrings.blankFirstLine = unfold
docstrings.style = SpaceAsterisk
maxColumn = 30
---
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package org.scalafmt.config

import org.scalafmt.util.ValidationOps

import scala.collection.mutable

import metaconfig._

/** @param oneline
Expand All @@ -26,27 +22,20 @@ case class Docstrings(
wrap: Docstrings.Wrap = Docstrings.Wrap.yes,
private[config] val wrapMaxColumn: Option[Int] = None,
forceBlankLineBefore: Option[Boolean] = None,
blankFirstLine: Docstrings.BlankFirstLine = Docstrings.BlankFirstLine.no,
blankFirstLine: Option[Docstrings.BlankFirstLine] = None,
style: Docstrings.Style = Docstrings.SpaceAsterisk,
) {
import Docstrings._

def withoutRewrites: Docstrings =
copy(removeEmpty = false, wrap = Wrap.no, style = Preserve)

def skipFirstLineIf(wasBlank: Boolean): Boolean = blankFirstLine match {
case BlankFirstLine.yes => true
case BlankFirstLine.no => style.skipFirstLine
case BlankFirstLine.keep => wasBlank || style.skipFirstLine
}

def validate(implicit errors: mutable.Buffer[String]): Unit = {
import ValidationOps._
addIf(
blankFirstLine.eq(BlankFirstLine.keep) && style.eq(Docstrings.Asterisk),
s"docstrings",
)
}
def skipFirstLineIf(wasBlank: Boolean): Boolean = style.skipFirstLine
.orElse(blankFirstLine).exists {
case BlankFirstLine.unfold => true
case BlankFirstLine.fold => false
case BlankFirstLine.keep => wasBlank
}

}

Expand All @@ -58,21 +47,21 @@ object Docstrings {
.deriveCodecEx(Docstrings()).noTypos

sealed abstract class Style {
def skipFirstLine: Boolean
def skipFirstLine: Option[BlankFirstLine]
}
case object Preserve extends Style {
override def skipFirstLine: Boolean = throw new NotImplementedError(
"skipFirstLine called for docstrings.style=preserve, it's a bug in scalafmt",
)
override def skipFirstLine: Option[BlankFirstLine] =
Some(BlankFirstLine.keep)
}
case object Asterisk extends Style {
override def skipFirstLine: Boolean = true
override def skipFirstLine: Option[BlankFirstLine] =
Some(BlankFirstLine.unfold)
}
case object SpaceAsterisk extends Style {
override def skipFirstLine: Boolean = false
override def skipFirstLine: Option[BlankFirstLine] = None
}
case object AsteriskSpace extends Style {
override def skipFirstLine: Boolean = false
override def skipFirstLine: Option[BlankFirstLine] = None
}

implicit val reader: ConfCodecEx[Style] = ReaderUtil
Expand Down Expand Up @@ -102,13 +91,15 @@ object Docstrings {

sealed abstract class BlankFirstLine
object BlankFirstLine {
case object yes extends BlankFirstLine
case object no extends BlankFirstLine
case object unfold extends BlankFirstLine
case object fold extends BlankFirstLine
case object keep extends BlankFirstLine
implicit val codec: ConfCodecEx[BlankFirstLine] = ReaderUtil
.oneOfCustom[BlankFirstLine](yes, no, keep) {
case Conf.Bool(true) => Configured.Ok(yes)
case Conf.Bool(false) => Configured.Ok(no)
.oneOfCustom[BlankFirstLine](unfold, fold, keep) {
case Conf.Str("no") => Configured.Ok(fold)
case Conf.Bool(false) => Configured.Ok(fold)
case Conf.Str("yes") => Configured.Ok(unfold)
case Conf.Bool(true) => Configured.Ok(unfold)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,6 @@ object ScalafmtConfig {
addIf(optIn.breaksInsideChains)
addIf(!includeCurlyBraceInSelectChains)
}
docstrings.validate
if (errors.nonEmpty) {
allErrors += s"newlines.source=${newlines.source} and ["
errors.foreach(x => allErrors += "\t" + x)
Expand Down
Loading