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

RegexCompat: fix leading-asterisk pattern for \r #4776

Merged
merged 1 commit into from
Jan 31, 2025
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 @@ -20,7 +20,7 @@ private[scalafmt] object RegexCompat {

val mlcParagraphBeg = Pattern.compile("^(?:[-*@=]|\\d++[.:])")

private val leadingAsteriskSpace = Pattern.compile("(?<=\n)\\h*+(?=[*][^*])")
val leadingAsteriskSpace = Pattern.compile("\\h*\\r*\\n(\\h*+)(?:[*][^*])?")

val docstringLine = Pattern
.compile("^(?:\\h*+\\*)?(\\h*+)(.*?)\\h*+$", Pattern.MULTILINE)
Expand Down Expand Up @@ -53,10 +53,6 @@ private[scalafmt] object RegexCompat {
def getStripMarginPattern(pipe: Char) =
if (pipe == '|') leadingPipeSpace else compileStripMarginPattern(pipe)

@inline
def replaceAllLeadingAsterisk(trimmed: String, spaces: String): String =
leadingAsteriskSpace.matcher(trimmed).replaceAll(spaces)

// Replaces baseText.split("(?={beforeText})")
@inline
def splitByBeforeTextMatching(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object RegexCompat {

val mlcParagraphBeg = pat("^(?:[-*@=]|\\d+[.:])")

val leadingAsteriskSpace = pat("\n\\h*[*][^*]", Pattern.MULTILINE)
val leadingAsteriskSpace = pat("\\h*\\r*\\n(\\h*)(?:[*][^*])?")

val docstringLine = pat("^(?:\\h*\\*)?(\\h*)(.*?)\\h*$", Pattern.MULTILINE)

Expand All @@ -93,60 +93,12 @@ object RegexCompat {
val stripMarginPatternWithLineContent =
compileStripMarginPatternWithLineContent('|')

// startAfterPattern and endBeforePattern should be unique in basePattern
// basePattern = startAfterPattern + matched pattern + endBeforePattern
private def replaceAll(
basePattern: Pattern,
startAfterPattern: Pattern,
endBeforePattern: Pattern,
baseText: String,
replacingText: String,
): String = {
val sb = new java.lang.StringBuilder()
val matcher = basePattern.matcher(baseText)
var currPosition = 0
while (matcher.find()) {
val start = matcher.start()
val end = matcher.end()

sb.append(baseText, currPosition, start)

val subtext = baseText.substring(start, end)
val startAfterMatcher = startAfterPattern.matcher(subtext)
val endBeforeMatcher = endBeforePattern.matcher(subtext)

startAfterMatcher.find()
endBeforeMatcher.find()

sb.append(startAfterMatcher.group())
sb.append(replacingText)
sb.append(endBeforeMatcher.group())

currPosition = end
}

sb.append(baseText, currPosition, baseText.length())
sb.toString()
}

private val leadingPipeSpace = compileStripMarginPattern('|')

@inline
def getStripMarginPattern(pipe: Char) =
if (pipe == '|') leadingPipeSpace else compileStripMarginPattern(pipe)

private val startAfterForReplaceAllLeadingAsterisk = pat("\n")
private val endBeforeForReplaceAllLeadingAsterisk = pat("([*][^*])")
@inline
def replaceAllLeadingAsterisk(trimmed: String, spaces: String): String =
replaceAll(
leadingAsteriskSpace,
startAfterForReplaceAllLeadingAsterisk,
endBeforeForReplaceAllLeadingAsterisk,
trimmed,
spaces,
)

// replaces baseText.split("(?={beforeText})")
def splitByBeforeTextMatching(
baseText: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,18 @@ class FormatWriter(formatOps: FormatOps) {
val lines = iterSections(sectionIter)
terminateMlc(curlen, lines)
} else {
val trimmed = removeTrailingWhiteSpace(text)
sb.append(RegexCompat.replaceAllLeadingAsterisk(trimmed, spaces))
val matcher = RegexCompat.leadingAsteriskSpace.matcher(text)
var pos = 0
while (matcher.find()) {
sb.append(CharBuffer.wrap(text, pos, matcher.start())).append(eol)
val end = matcher.end()
val endMargin = matcher.end(1)
if (endMargin == end) // no asterisk
pos = if (end < text.length) matcher.start(1) else text.length
else { sb.append(spaces); pos = endMargin }
}
val lastLength = State.getLineLength(text, pos, text.length)
sb.append(CharBuffer.wrap(text, pos, pos + lastLength))
}

private def appendLineBreak(): Unit = startNewLine(spaces).append('*')
Expand Down