Skip to content

Commit 809656c

Browse files
committed
Revert "cleanup"
This reverts commit 3aefb59.
1 parent 3aefb59 commit 809656c

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

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

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,26 +1368,43 @@ object Parsers {
13681368
// APIs behaves predictably in the presence of empty leading/trailing lines
13691369
if (closingIndent == "") str
13701370
else {
1371-
if (closingIndent.contains('\t') && closingIndent.contains(' ')) {
1371+
// Check for mixed tabs and spaces in closing indent
1372+
1373+
val hasTabs = closingIndent.contains('\t')
1374+
val hasSpaces = closingIndent.contains(' ')
1375+
if (hasTabs && hasSpaces) {
13721376
syntaxError(
13731377
em"dedented string literal cannot mix tabs and spaces in indentation",
13741378
offset
13751379
)
13761380
return str
13771381
}
13781382

1383+
// Split into lines
13791384
val linesAndWithSeps = (str.linesIterator.zip(str.linesWithSeparators)).toSeq
1385+
13801386
var lineOffset = offset
13811387

13821388
def dedentLine(line: String, lineWithSep: String) = {
13831389
val result =
13841390
if (line.startsWith(closingIndent)) line.substring(closingIndent.length)
13851391
else if (line.trim.isEmpty) "" // Empty or whitespace-only lines
13861392
else {
1387-
syntaxError(
1388-
em"line in dedented string literal must be indented at least as much as the closing delimiter with an identical prefix",
1389-
lineOffset
1390-
)
1393+
// Check if this line has mixed tabs/spaces that don't match closing indent
1394+
val lineIndent = line.takeWhile(_.isWhitespace)
1395+
val lineHasTabs = lineIndent.contains('\t')
1396+
val lineHasSpaces = lineIndent.contains(' ')
1397+
if ((hasTabs && lineHasSpaces && !lineHasTabs) || (hasSpaces && lineHasTabs && !lineHasSpaces)) {
1398+
syntaxError(
1399+
em"dedented string literal cannot mix tabs and spaces in indentation",
1400+
offset
1401+
)
1402+
} else {
1403+
syntaxError(
1404+
em"line in dedented string literal must be indented at least as much as the closing delimiter",
1405+
lineOffset
1406+
)
1407+
}
13911408
line
13921409
}
13931410
lineOffset += lineWithSep.length // Make sure to include any \n, \r, \r\n, or \n\r
@@ -1534,15 +1551,14 @@ object Parsers {
15341551
in.charOffset + 1 < in.buf.length &&
15351552
in.buf(in.charOffset) == '"' &&
15361553
in.buf(in.charOffset + 1) == '"'
1537-
15381554
val isDedented =
15391555
in.charOffset + 2 < in.buf.length &&
15401556
in.buf(in.charOffset - 1) == '\'' &&
15411557
in.buf(in.charOffset) == '\'' &&
15421558
in.buf(in.charOffset + 1) == '\''
1543-
15441559
in.nextToken()
15451560

1561+
// Collect all string parts and their offsets
15461562
val stringParts = new ListBuffer[(String, Offset)]
15471563
val interpolatedExprs = new ListBuffer[Tree]
15481564

@@ -1553,6 +1569,7 @@ object Parsers {
15531569
offsetCorrection = 0
15541570
in.nextToken()
15551571

1572+
// Collect the interpolated expression
15561573
interpolatedExprs += atSpan(in.offset) {
15571574
if (in.token == IDENTIFIER)
15581575
termIdent()
@@ -1574,6 +1591,7 @@ object Parsers {
15741591
}
15751592
}
15761593

1594+
// Get the final STRINGLIT
15771595
val finalLiteral = if (in.token == STRINGLIT) {
15781596
val s = in.strVal
15791597
val off = in.offset + offsetCorrection
@@ -1593,6 +1611,7 @@ object Parsers {
15931611
}
15941612
}
15951613

1614+
// Build the segments with dedented strings
15961615
for ((str, expr) <- dedentedParts.zip(interpolatedExprs)) {
15971616
val (dedentedStr, offset) = str
15981617
segmentBuf += Thicket(
@@ -1601,7 +1620,8 @@ object Parsers {
16011620
)
16021621
}
16031622

1604-
if (finalLiteral) { // Add the final literal if present
1623+
// Add the final literal if present
1624+
if (finalLiteral) {
16051625
val (dedentedStr, offset) = dedentedParts.last
16061626
segmentBuf += atSpan(offset, offset, offset + dedentedStr.length) { Literal(Constant(dedentedStr)) }
16071627
}

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -990,17 +990,26 @@ object Scanners {
990990
case '\'' =>
991991
def fetchSingleQuote(): Unit = {
992992
nextChar()
993-
if (ch == '\'') { // Check for triple single quote (dedented string literal)
993+
// Check for triple single quote (dedented string literal)
994+
if (ch == '\'') {
994995
nextChar()
995996
if (ch == '\'') {
996-
// We have at least ''' check if this is an interpolated dedented string
997+
// We have at least '''
998+
// Check if this is an interpolated dedented string
997999
if (token == INTERPOLATIONID) {
1000+
// For interpolation, handle as string part
9981001
nextRawChar()
9991002
val quoteCount = getDedentedString(isInterpolated = true)
10001003
currentRegion = InDedentedString(quoteCount, currentRegion)
1001-
} else getDedentedString(isInterpolated = false)
1004+
} else {
1005+
getDedentedString(isInterpolated = false)
1006+
// No need to store quoteCount for non-interpolated strings
1007+
}
1008+
}
1009+
else {
1010+
// We have '' followed by something else
1011+
error(em"empty character literal")
10021012
}
1003-
else error(em"empty character literal") // We have '' followed by something else
10041013
}
10051014
else if isIdentifierStart(ch) then
10061015
charLitOr { getIdentRest(); QUOTEID }

0 commit comments

Comments
 (0)