diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala index 1f0cfac8b8..835090140f 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/util/StyleMap.scala @@ -10,9 +10,6 @@ import org.scalameta.FileLine import org.scalameta.logger import scala.meta._ import scala.meta.tokens.Token -import scala.meta.tokens.Token.Comment -import scala.meta.tokens.Token.LeftParen -import scala.meta.tokens.Token.RightParen import scala.annotation.tailrec import scala.collection.mutable @@ -30,20 +27,20 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { styleBuilder += init val disableBinPack = mutable.Map.empty[Token, BinPack.Site] def warn(err: String)(implicit fileLine: FileLine): Unit = logger.elem(err) - tokens.arr.foreach { tok => + tokens.arr.foreach { ft => def changeStyle(style: ScalafmtConfig): Option[ScalafmtConfig] = { val changing = curr != style if (!changing) None else { - startBuilder += tok.left.start + startBuilder += ft.left.start styleBuilder += style val prev = curr curr = style Some(prev) } } - tok.left match { - case Comment(c) if prefix.matcher(c).find() => + ft.left match { + case Token.Comment(c) if prefix.matcher(c).find() => val configured = ScalafmtConfig .fromHoconString(c, init, Some("scalafmt")) // TODO(olafur) report error via callback @@ -54,28 +51,24 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { } changeStyle(style) } - case open @ LeftParen() + case tok: Token.LeftParen if curr.binPack.literalArgumentLists && - opensLiteralArgumentList(tok)(curr) => - forcedBinPack += tok.meta.leftOwner + opensLiteralArgumentList(ft)(curr) => + forcedBinPack += ft.meta.leftOwner changeStyle(setBinPack(curr, callSite = BinPack.Site.Always)) .foreach { x => - tokens.matchingOpt(open) + tokens.matchingOpt(tok) .foreach(disableBinPack.update(_, x.binPack.callSite)) } - case close @ RightParen() => disableBinPack.remove(close).foreach { x => - changeStyle(setBinPack(curr, callSite = x)) - } + case tok: Token.RightParen => disableBinPack.remove(tok) + .foreach(x => changeStyle(setBinPack(curr, callSite = x))) case _ => } } (startBuilder.result(), styleBuilder.result()) } - @tailrec - private def isBasicLiteral( - tree: Tree, - )(implicit style: ScalafmtConfig): Boolean = tree match { + private def isBasicLiteral(tree: Tree): Boolean = tree match { case lit: Lit => val strName = tree match { case t: Lit.Int @@ -86,40 +79,43 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { } literalR.matches(strName) case x: Name => literalR.matches(x.productPrefix) - case _ if !style.binPack.literalsIncludeSimpleExpr => false - case t: Term.Select => isBasicLiteral(t.qual) - case t: Term.Assign => isBasicLiteral(t.rhs) - case _ => tree.children match { + case _ => false + } + + @tailrec + private def isSimpleLiteral(tree: Tree): Boolean = tree match { + case t: Term.Select => isSimpleLiteral(t.qual) + case t: Term.Assign => isSimpleLiteral(t.rhs) + case _ => isBasicLiteral(tree) || + (tree.children match { case Nil => true - case one :: Nil => isBasicLiteral(one) + case one :: Nil => isSimpleLiteral(one) case _ => false - } + }) } @tailrec - private def isLiteral(tree: Tree)(implicit style: ScalafmtConfig): Boolean = - isBasicLiteral(tree) || - style.binPack.literalsIncludeSimpleExpr && - (tree match { - case t: Term.Assign => isLiteral(t.rhs) - case t: Term.Apply => isBasicLiteral(t.fun) && - (t.argClause match { - case Term.ArgClause(Nil, None) => true - case Term.ArgClause(arg :: Nil, None) => isLiteral(arg) - case _ => false - }) - case Term.New(t) => isBasicLiteral(t.name) && - (t.argClauses match { - case Nil | Term.ArgClause(Nil, None) :: Nil => true - case Term.ArgClause(arg :: Nil, None) :: Nil => isLiteral(arg) - case _ => false - }) - case _ => tree.children match { - case Nil => true - case one :: Nil => isLiteral(one) - case _ => false - } + private def isComplexLiteral(tree: Tree): Boolean = tree match { + case t: Term.Assign => isComplexLiteral(t.rhs) + case t: Term.Apply => isSimpleLiteral(t.fun) && + (t.argClause match { + case Term.ArgClause(Nil, None) => true + case Term.ArgClause(arg :: Nil, None) => isComplexLiteral(arg) + case _ => false + }) + case Term.New(t) => isSimpleLiteral(t.name) && + (t.argClauses match { + case Nil | Term.ArgClause(Nil, None) :: Nil => true + case Term.ArgClause(arg :: Nil, None) :: Nil => isComplexLiteral(arg) + case _ => false + }) + case _ => isSimpleLiteral(tree) || + (tree.children match { + case Nil => true + case one :: Nil => isComplexLiteral(one) + case _ => false }) + } def opensLiteralArgumentList( ft: FormatToken, @@ -128,8 +124,17 @@ class StyleMap(tokens: FormatTokens, val init: ScalafmtConfig) { case Member.SyntaxValuesClause(v) => Some(v) case _ => None }).exists { args => - args.lengthCompare(style.binPack.literalsMinArgCount) >= 0 && - args.forall(isLiteral) + implicit val pred: Tree => Boolean = + if (style.binPack.literalsIncludeSimpleExpr) isComplexLiteral + else isBasicLiteral + @tailrec + def iter(rest: List[Tree], cnt: Int)(implicit + pred: Tree => Boolean, + ): Boolean = rest match { + case head :: tail => pred(head) && iter(tail, cnt + 1) + case Nil => cnt >= style.binPack.literalsMinArgCount + } + iter(args, 0) } @inline