From 46d733fcc7ab24e97f50c81430eb2f6e23c27125 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Tue, 23 Jun 2020 08:36:05 -0700 Subject: [PATCH 1/3] Add failing test for scaladoc amid expression --- .../src/test/resources/test/JavaDoc.stat | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scalafmt-tests/src/test/resources/test/JavaDoc.stat b/scalafmt-tests/src/test/resources/test/JavaDoc.stat index 1bd3260036..5f17e4052f 100644 --- a/scalafmt-tests/src/test/resources/test/JavaDoc.stat +++ b/scalafmt-tests/src/test/resources/test/JavaDoc.stat @@ -1259,3 +1259,20 @@ object a { /** alias for [[literal]] */ /** alias for [[literal]] */ } +<<< #2043 +object Day extends Enumeration { + type Day = Value + + val + /** Monday */ + MON = Value +} +>>> +object Day extends Enumeration { + type Day = Value + + val + + /** Monday */ + MON = Value +} From cce0e2ca8d76f74c2a315f31b41b32685b7350a6 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Tue, 23 Jun 2020 09:20:36 -0700 Subject: [PATCH 2/3] TreeOps: extend the findTree methods --- .../org/scalafmt/internal/FormatOps.scala | 3 ++- .../scala/org/scalafmt/internal/State.scala | 14 +++++----- .../scala/org/scalafmt/util/TreeOps.scala | 27 +++++++++++++++++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala index d523067bc7..4fcb426418 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala @@ -650,7 +650,8 @@ class FormatOps(val tree: Tree, baseStyle: ScalafmtConfig) { ft: FormatToken, newStmtModOrBody: Either[Modification, Tree] )(implicit style: ScalafmtConfig): Seq[Split] = { - val fullInfixTreeOpt = findTreeWithParentSimple(lhsApp.all)(!isInfixApp(_)) + val fullInfixTreeOpt = + findTreeWithParentSimple(lhsApp.all, false)(isInfixApp) val fullInfix = fullInfixTreeOpt.flatMap(asInfixApp).getOrElse(lhsApp) val app = findLeftInfix(fullInfix) newStmtModOrBody.fold( diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala index 1ca0142e99..ef696cff98 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala @@ -217,9 +217,10 @@ final case class State( if (startsWithLeft(lo)) Some(lo) else None } owner.map { x => - val y = - if (!x.parent.exists(startsWithLeft)) None - else TreeOps.findTreeWithParentSimple(x)(!startsWithLeft(_)) + val y = x.parent.flatMap { p => + if (!startsWithLeft(p)) None + else TreeOps.findTreeWithParentSimple(p, false)(startsWithLeft) + } (ft, y.getOrElse(x)) } } @@ -235,13 +236,13 @@ final case class State( getLineStartOwner(isComment).flatMap { case (lineFt, lineOwner) => val ft = fops.tokens(depth) - val ok = (ft.meta.leftOwner eq lineOwner) || { + val ok = { // comment could be preceded by a comma isComment && ft.left.is[Token.Comma] && (fops.prev(ft).meta.leftOwner eq lineOwner) } || TreeOps - .findTreeWithParentSimple(ft.meta.leftOwner)(_ eq lineOwner) + .findTreeOrParentSimple(ft.meta.leftOwner)(_ eq lineOwner) .isDefined if (ok) Some(lineFt) else None } @@ -389,7 +390,6 @@ object State { @inline private def isWithinInterpolation(tree: meta.Tree): Boolean = - isInterpolation(tree) || - TreeOps.findTreeWithParentSimple(tree)(isInterpolation).isDefined + TreeOps.findTreeOrParentSimple(tree)(isInterpolation).isDefined } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala index 9fff244bee..b8abad822b 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TreeOps.scala @@ -229,6 +229,28 @@ object TreeOps { case _ => cnt } + /** + * Returns first ancestor which matches the given predicate. + */ + @tailrec + def findTreeOrParent( + tree: Tree + )(pred: Tree => Option[Boolean]): Option[Tree] = + pred(tree) match { + case Some(true) => Some(tree) + case Some(false) => None + case None => + tree.parent match { + case None => None + case Some(p) => findTreeOrParent(p)(pred) + } + } + def findTreeOrParentSimple( + tree: Tree, + flag: Boolean = true + )(pred: Tree => Boolean): Option[Tree] = + findTreeOrParent(tree)(x => if (pred(x) == flag) Some(true) else None) + /** * Returns first ancestor whose parent matches the given predicate. */ @@ -246,9 +268,10 @@ object TreeOps { } } def findTreeWithParentSimple( - tree: Tree + tree: Tree, + flag: Boolean = true )(pred: Tree => Boolean): Option[Tree] = - findTreeWithParent(tree)(x => if (pred(x)) Some(true) else None) + findTreeWithParent(tree)(x => if (pred(x) == flag) Some(true) else None) /** * Returns first ancestor with a parent of a given type. From 5ca963cae547429e84b8e05e8cc41d7a700aee68 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Tue, 23 Jun 2020 09:23:42 -0700 Subject: [PATCH 3/3] TokenOps: no blank line for scaladoc in expression --- .../src/main/scala/org/scalafmt/util/TokenOps.scala | 11 ++++++++--- scalafmt-tests/src/test/resources/test/JavaDoc.stat | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala index a4a7380e6c..a261a68614 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/TokenOps.scala @@ -1,7 +1,7 @@ package org.scalafmt.util import scala.meta.classifiers.Classifier -import scala.meta.{Defn, Pkg, Template, Tree} +import scala.meta.{Defn, Pkg, Source, Template, Term, Tree} import scala.meta.tokens.Token import scala.meta.tokens.Token._ import scala.meta.tokens.Tokens @@ -54,8 +54,13 @@ object TokenOps { style.optIn.forceNewlineBeforeDocstringSummary && ft.right.is[Token.Comment] && !ft.left.is[Token.Comment] && ft.meta.right.text.startsWith("/**") && - !ft.meta.leftOwner.is[meta.Mod] && - !TreeOps.existsParentOfType[meta.Mod](ft.meta.leftOwner) + TreeOps + .findTreeOrParent(ft.meta.leftOwner) { + case _: Pkg | _: Source | _: Template | _: Term.Block => Some(false) + case t if t.pos.end > ft.right.start => Some(true) + case _ => None + } + .isEmpty // 2.13 implements SeqOps.findLast def findLast[A](seq: Seq[A])(cond: A => Boolean): Option[A] = diff --git a/scalafmt-tests/src/test/resources/test/JavaDoc.stat b/scalafmt-tests/src/test/resources/test/JavaDoc.stat index 5f17e4052f..e4e1543656 100644 --- a/scalafmt-tests/src/test/resources/test/JavaDoc.stat +++ b/scalafmt-tests/src/test/resources/test/JavaDoc.stat @@ -1272,7 +1272,6 @@ object Day extends Enumeration { type Day = Value val - /** Monday */ MON = Value }