Skip to content

Commit c9fbf70

Browse files
committed
.
1 parent 7e8e5a7 commit c9fbf70

File tree

2 files changed

+16
-21
lines changed

2 files changed

+16
-21
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,28 +1359,21 @@ object Parsers {
13591359

13601360
// Find the last line (should be just whitespace before closing delimiter)
13611361
val lastNewlineIdx = str.lastIndexOf('\n')
1362-
if (lastNewlineIdx < 0) {
1363-
// No newlines, return as-is (shouldn't happen for valid dedented strings)
1364-
return str
1365-
}
1362+
assert(
1363+
lastNewlineIdx >= 0,
1364+
"Dedented string literal must contain at least two newlines"
1365+
)
13661366

1367-
// Extract the indentation from the last line
13681367
val closingIndent = str.substring(lastNewlineIdx + 1)
13691368

13701369
// Split into lines
1371-
val lines = str.split("\n", -1) // -1 to keep trailing empty strings
1370+
val lines = str.linesIterator.toSeq
13721371

13731372
// Process all lines except the last (which is just the closing indentation)
13741373
val dedented = lines.dropRight(1).map { line =>
1375-
if (line.startsWith(closingIndent)) {
1376-
line.substring(closingIndent.length)
1377-
} else if (line.trim.isEmpty) {
1378-
// Empty or whitespace-only lines
1379-
""
1380-
} else {
1381-
// Line doesn't start with the closing indentation, keep as-is
1382-
line
1383-
}
1374+
if (line.startsWith(closingIndent)) line.substring(closingIndent.length)
1375+
else if (line.trim.isEmpty) "" // Empty or whitespace-only lines
1376+
else ??? // should never happen
13841377
}
13851378

13861379
// Drop the first line if it's empty (the newline after opening delimiter)
@@ -1397,7 +1390,10 @@ object Parsers {
13971390
* @param negOffset The offset of a preceding `-' sign, if any.
13981391
* If the literal is not negated, negOffset == in.offset.
13991392
*/
1400-
def literal(negOffset: Int = in.offset, inPattern: Boolean = false, inTypeOrSingleton: Boolean = false, inStringInterpolation: Boolean = false): Tree = {
1393+
def literal(negOffset: Int = in.offset,
1394+
inPattern: Boolean = false,
1395+
inTypeOrSingleton: Boolean = false,
1396+
inStringInterpolation: Boolean = false): Tree = {
14011397
def literalOf(token: Token): Tree = {
14021398
val isNegated = negOffset < in.offset
14031399
def digits0 = in.removeNumberSeparators(in.strVal)
@@ -1423,9 +1419,7 @@ object Parsers {
14231419
val str = in.strVal
14241420
if (token == STRINGLIT && !inStringInterpolation && isDedentedStringLiteral(negOffset)) {
14251421
dedentString(str)
1426-
} else {
1427-
str
1428-
}
1422+
} else str
14291423
case TRUE => true
14301424
case FALSE => false
14311425
case NULL => null

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,8 @@ object Scanners {
13491349
foundQuotes += 1
13501350
nextRawChar()
13511351
}
1352+
// The while-loop above steps forward to the first non-`'` character,
1353+
// so we need to backtrack 1 char to avoid consuming it
13521354
charOffset -= 1
13531355

13541356
if (foundQuotes == quoteCount && ch != '\'') {
@@ -1407,8 +1409,7 @@ object Scanners {
14071409
}
14081410
else {
14091411
val isUnclosedLiteral = !isUnicodeEscape && ch == SU
1410-
if (isUnclosedLiteral)
1411-
incompleteInputError(em"unclosed dedented string literal")
1412+
if (isUnclosedLiteral) incompleteInputError(em"unclosed dedented string literal")
14121413
else {
14131414
putChar(ch)
14141415
nextRawChar()

0 commit comments

Comments
 (0)