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

FormatTokens: add more methods around comments #3968

Merged
merged 1 commit into from
May 10, 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
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class FormatOps(
case c: T.Comment
if start.noBreak &&
(!start.left.is[T.LeftParen] ||
tokens.isBreakAfterRight(start)) => Some(c)
tokens.hasBreakAfterRightBeforeNonComment(start)) => Some(c)
case _ => Some(start.left)
}
}.fold(_.right, identity)
Expand All @@ -164,8 +164,9 @@ class FormatOps(
case _: T.Comma | _: T.LeftParen | _: T.Semicolon | _: T.RightArrow |
_: T.Equals => None
case _: T.RightParen if start.left.is[T.LeftParen] => None
case c: T.Comment if start.noBreak && tokens.isBreakAfterRight(start) =>
Some(c)
case c: T.Comment
if start.noBreak &&
tokens.hasBreakAfterRightBeforeNonComment(start) => Some(c)
case _ if !style.newlines.formatInfix && start.noBreak && isInfix => None
case _ => Some(start.left)
}
Expand Down Expand Up @@ -1241,7 +1242,7 @@ class FormatOps(
def isDone(x: FormatToken) = x.hasBlankLine || x.right.end >= end
@tailrec
def iter(x: FormatToken): FormatToken = {
val nft = tokens.nextNonCommentSameLine(next(x))
val nft = tokens.nextNonCommentSameLineAfter(x)
if (isDone(nft)) nft
else if (!nft.right.is[T.Comment]) ft // original
else iter(nft)
Expand All @@ -1267,7 +1268,7 @@ class FormatOps(
case _: T.Comment =>
val isDetachedSlc = ft.hasBreak && tokens.isBreakAfterRight(ft)
if (isDetachedSlc || ft.rightHasNewline) null else Space
case _ => Space(style.spaces.inParentheses && spaceOk)
case _ => Space(spaceOk && style.spaces.inParentheses)
}

// look for arrow before body, if any, else after params
Expand Down Expand Up @@ -1637,7 +1638,7 @@ class FormatOps(
if (!ft.right.is[T.Comment]) splitsFunc(ft)
else if (ft.hasBreak) Seq(nlSplitFunc(0).forThisLine)
else {
val nextFt = nextNonCommentSameLine(next(ft))
val nextFt = tokens.nextNonCommentSameLineAfter(ft)
val splits =
if (nextFt.noBreak) splitsFunc(nextFt)
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken]
final def nextNonCommentSameLine(curr: FormatToken): FormatToken =
findToken(curr, next)(ft => ft.hasBreak || !ft.right.is[Token.Comment])

final def nextNonCommentSameLineAfter(curr: FormatToken): FormatToken =
nextNonCommentSameLine(next(curr))

final def nextNonComment(curr: FormatToken): FormatToken =
findToken(curr, next)(!_.right.is[Token.Comment])

Expand Down Expand Up @@ -288,13 +291,21 @@ class FormatTokens(leftTok2tok: Map[TokenHash, Int])(val arr: Array[FormatToken]
@inline
def isBreakAfterRight(ft: FormatToken): Boolean = next(ft).hasBreakOrEOF

@inline
def hasBreakAfterRightBeforeNonComment(ft: FormatToken): Boolean =
nextNonCommentSameLineAfter(ft).hasBreakOrEOF

@inline
def hasBreakBeforeNonComment(ft: FormatToken): Boolean = ft.hasBreak ||
hasBreakAfterRightBeforeNonComment(ft)

@inline
def isRightCommentThenBreak(ft: FormatToken): Boolean = ft.right
.is[Token.Comment] && isBreakAfterRight(ft)
.is[Token.Comment] && hasBreakAfterRightBeforeNonComment(ft)

@inline
def isRightLikeSingleLineComment(ft: FormatToken): Boolean =
isRightCommentThenBreak(ft) && !ft.rightHasNewline
def isRightCommentWithBreak(ft: FormatToken): Boolean = ft.right
.is[Token.Comment] && hasBreakBeforeNonComment(ft)

@inline
def isAttachedCommentThenBreak(ft: FormatToken): Boolean = ft.noBreak &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1869,7 +1869,8 @@ object FormatWriter {
case x => x
}

val slc = tokens.isRightLikeSingleLineComment(ft)
val slc = ft.right.is[T.Comment] && tokens.isBreakAfterRight(ft) &&
!ft.rightHasNewline
val code = if (slc) "//" else ft.meta.right.text
floc.style.alignMap.get(code).flatMap { matchers =>
// Corner case when line ends with comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1143,8 +1143,7 @@ class Router(formatOps: FormatOps) {
val rightIsComment = right.is[T.Comment]
val mustUseNL = onlyConfigStyle ||
style.newlines.keepBreak(newlines) ||
rightIsComment &&
(newlines != 0 || nextNonCommentSameLine(next(ft)).hasBreak)
tokens.isRightCommentWithBreak(ft)
val noSplitModification =
if (rightIsComment && !mustUseNL) getMod(ft) else baseNoSplitMod
val nlMod = if (rightIsComment && mustUseNL) getMod(ft) else Newline
Expand Down Expand Up @@ -1186,8 +1185,7 @@ class Router(formatOps: FormatOps) {
val nlOnly = flags.dangleForTrailingCommas ||
flags.configStyle != ConfigStyle.None ||
style.newlines.keepBreak(newlines) || scalaJsStyleNL ||
rightIsComment &&
(newlines != 0 || nextNonCommentSameLine(next(ft)).hasBreak)
tokens.isRightCommentWithBreak(ft)

def findComma(ft: FormatToken) = findFirstOnRight[T.Comma](ft, close)

Expand Down Expand Up @@ -1949,7 +1947,7 @@ class Router(formatOps: FormatOps) {
if (style.newlines.getBeforeMultiline eq Newlines.unfold) CtrlBodySplits
.checkComment(ft, nlSplitFunc) { ft =>
if (ft.right.is[T.LeftBrace]) {
val nextFt = nextNonCommentSameLine(next(ft))
val nextFt = tokens.nextNonCommentSameLineAfter(ft)
val policy = decideNewlinesOnlyAfterToken(nextFt.left)
Seq(Split(Space, 0, policy = policy))
} else Seq(nlSplitFunc(0))
Expand Down Expand Up @@ -1981,7 +1979,7 @@ class Router(formatOps: FormatOps) {
case FormatToken(_, _: T.KwThen | _: T.KwDo, _) =>
if (style.newlines.sourceIgnored || newlines == 0) Seq(
Split(Space, 0)
.withOptimalToken(nextNonCommentSameLine(next(ft)).left),
.withOptimalToken(tokens.nextNonCommentSameLineAfter(ft).left),
Split(Newline, 1),
)
else Seq(Split(Newline, 0))
Expand Down Expand Up @@ -2114,7 +2112,7 @@ class Router(formatOps: FormatOps) {
val policy =
if (bodyBlock || tokens.isAttachedCommentThenBreak(arrowFt)) NoPolicy
else if (isCaseBodyEnclosedAsBlock(postArrowFt, owner)) {
val postParenFt = nextNonCommentSameLine(next(postArrowFt))
val postParenFt = tokens.nextNonCommentSameLineAfter(postArrowFt)
val lparen = postParenFt.left
val rparen = matching(lparen)
if (postParenFt.right.start >= rparen.start) defaultPolicy
Expand Down Expand Up @@ -2156,7 +2154,7 @@ class Router(formatOps: FormatOps) {
if (style.newlines.keepBreak(newlines)) Seq(Split(Newline, 0))
else {
val arrow = getCaseArrow(rightOwner.asInstanceOf[Case]).left
val afterIf = nextNonCommentSameLine(next(ft))
val afterIf = tokens.nextNonCommentSameLineAfter(ft)
val noSplit =
if (style.newlines.keepBreak(afterIf)) {
val indent = Indent(style.indent.main, arrow, ExpiresOn.Before)
Expand Down Expand Up @@ -2416,13 +2414,14 @@ class Router(formatOps: FormatOps) {
}
ft match {
case FormatToken(_: T.BOF, _, _) => splits
case FormatToken(_, _: T.Comment, _) if tokens.isBreakAfterRight(ft) =>
case FormatToken(_, _: T.Comment, _) if rhsIsCommentedOutIfComment(ft) =>
splitsAsNewlines(splits.map(_.withNoIndent))
case FormatToken(_: T.Comment, _, _) =>
if (ft.noBreak) splits else splitsAsNewlines(splits)
case FormatToken(_, _: T.Comment, _)
if tokens.hasBreakAfterRightBeforeNonComment(ft) =>
if (ft.noBreak) splits.map(_.withMod(Space))
else if (!rhsIsCommentedOut(ft)) splitsAsNewlines(splits)
else splitsAsNewlines(splits.map(_.withNoIndent))
// Only newlines after inline comments.
case FormatToken(_: T.Comment, _, _) if ft.hasBreak =>
splitsAsNewlines(splits)
else splitsAsNewlines(splits)
case ft if ft.meta.formatOff && ft.hasBreak => splitsAsNewlines(splits)
case FormatToken(_: T.Equals, r: T.KwMacro, _)
if dialect.allowSignificantIndentation =>
Expand All @@ -2445,10 +2444,8 @@ class Router(formatOps: FormatOps) {
def expire = getLastToken(body)
if (ft.right.is[T.LeftBrace]) // The block will take care of indenting by 2
Seq(Split(Space, 0).withIndents(spaceIndents))
else if (
ft.right.is[T.Comment] &&
(ft.hasBreak || nextNonCommentSameLine(next(ft)).hasBreak)
) Seq(CtrlBodySplits.withIndent(Split(Space.orNL(ft.noBreak), 0), ft, body))
else if (tokens.isRightCommentWithBreak(ft))
Seq(CtrlBodySplits.withIndent(Split(Space.orNL(ft.noBreak), 0), ft, body))
else if (isJsNative(body)) Seq(Split(Space, 0).withSingleLine(expire))
else if (style.newlines.forceBeforeAssign(ft.meta.leftOwner))
Seq(CtrlBodySplits.withIndent(Split(Newline, 0), ft, body))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,8 @@ private class PreferCurlyFors(implicit val ftoks: FormatTokens)
else null

case _: Token.Semicolon
if !style.rewrite.preferCurlyFors.removeTrailingSemicolonsOnly || {
val next = ftoks.next(ft)
next.hasBreak || ftoks.isRightCommentThenBreak(next)
} =>
if !style.rewrite.preferCurlyFors.removeTrailingSemicolonsOnly ||
ftoks.hasBreakAfterRightBeforeNonComment(ft) =>
ft.meta.rightOwner match {
case _: Term.For | _: Term.ForYield => removeToken
case _ => null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,13 @@ object TokenOps {
def withNoIndent(ft: FormatToken): Boolean = ft.between.lastOption
.exists(_.is[LF])

@inline
def rhsIsCommentedOut(ft: FormatToken): Boolean = ft.right.is[Comment] &&
withNoIndent(ft) && isSingleLineIfComment(ft.right)
rhsIsCommentedOutIfComment(ft)

@inline
def rhsIsCommentedOutIfComment(ft: FormatToken): Boolean = withNoIndent(ft) &&
isSingleLineIfComment(ft.right)

@inline
def isLeftCommentThenBreak(ft: FormatToken): Boolean = ft.left
Expand Down
8 changes: 4 additions & 4 deletions scalafmt-tests/src/test/resources/scala3/Extension.stat
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ maxColumn = 40
extension [A](cat: Cat) /* new feature */ // or this
def a = 1
>>>
extension [A](cat: Cat)
/* new feature */ // or this
extension [A](
cat: Cat
) /* new feature */ // or this
def a = 1
<<< extension comments with embedded NL
maxColumn = 40
Expand All @@ -136,8 +137,7 @@ extension [A](cat: Cat) /*
* new feature */ // or this
def a = 1
>>>
extension [A](cat: Cat)
/*
extension [A](cat: Cat) /*
* new feature */ // or this
def a = 1
<<< extension comments brace
Expand Down
Loading