Skip to content

Commit 5c8c892

Browse files
committed
.
1 parent 300f300 commit 5c8c892

File tree

6 files changed

+27
-34
lines changed

6 files changed

+27
-34
lines changed

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,7 @@ object Parsers {
13631363

13641364
// Find the last line (should be just whitespace before closing delimiter)
13651365
val lastNewlineIdx = str.lastIndexOf('\n')
1366+
13661367
if (lastNewlineIdx < 0) {
13671368
syntaxError(
13681369
em"dedented string literal must start with newline after opening quotes",
@@ -1392,11 +1393,12 @@ object Parsers {
13921393
}
13931394

13941395
// Split into lines
1395-
val lines = str.linesIterator.toSeq
1396+
val linesAndWithSeps = (str.linesIterator.zip(str.linesWithSeparators)).toSeq
13961397

1397-
// Process all lines except the last (which is just the closing indentation)
1398+
// Process all lines except the first (which is empty before the first newline)
1399+
// and the last (which is just the closing indentation)
13981400
var lineOffset = offset
1399-
val dedented = lines.dropRight(1).map { line =>
1401+
val dedented = linesAndWithSeps.drop(1).dropRight(1).map { case (line, lineWithSep) =>
14001402
val result =
14011403
if (line.startsWith(closingIndent)) line.substring(closingIndent.length)
14021404
else if (line.trim.isEmpty) "" // Empty or whitespace-only lines
@@ -1418,14 +1420,11 @@ object Parsers {
14181420
}
14191421
line
14201422
}
1421-
lineOffset += line.length + 1 // +1 for the newline
1423+
lineOffset += lineWithSep.length // Make sure to include any \n, \r, \r\n, or \n\r
14221424
result
14231425
}
14241426

1425-
// Drop the first line if it's empty (the newline after opening delimiter)
1426-
val result = if (dedented.headOption.contains("")) dedented.drop(1) else dedented
1427-
1428-
result.mkString("\n")
1427+
dedented.mkString("\n")
14291428
}
14301429

14311430
/** Literal ::= SimpleLiteral

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,10 +1319,6 @@ object Scanners {
13191319
return 0
13201320
}
13211321

1322-
// Skip the initial newline (CR LF or just LF)
1323-
if (ch == CR) nextRawChar()
1324-
if (ch == LF) nextRawChar()
1325-
13261322
// Collect all content using the string part parser
13271323
getDedentedStringPartWithDelimiter(quoteCount, isInterpolated)
13281324

@@ -1349,11 +1345,11 @@ object Scanners {
13491345
foundQuotes += 1
13501346
nextRawChar()
13511347
}
1352-
// The while-loop above steps forward to the first non-`'` character,
1353-
// so we need to backtrack 1 char to avoid consuming it
1354-
charOffset -= 1
13551348

13561349
if (foundQuotes == quoteCount && ch != '\'') {
1350+
// The while-loop above steps forward to the first non-`'` character,
1351+
// so we need to backtrack 1 char to avoid consuming it
1352+
charOffset -= 1
13571353
// Found closing delimiter - exact match and not followed by another quote
13581354
setStrVal()
13591355
nextChar() // Switch from raw mode to normal mode

tests/neg/dedented-string-literals.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
19 | val nonWhitespaceBeforeClosing = '''
1515
| ^
1616
|last line of dedented string literal must contain only whitespace before closing delimiter
17+
-- [E040] Syntax Error: tests/neg/dedented-string-literals.scala:41:17
18+
41 | val unclosed = '''
19+
| ^
20+
|unclosed dedented string literal
1721
-- Error: tests/neg/dedented-string-literals.scala:35:4
1822
35 | onlyAtCompileTime // error
1923
| ^^^^^^^^^^^^^^^^^
2024
|This method should only be used at compile time
2125
|Do not call at runtime
22-
-- [E040] Syntax Error: tests/neg/dedented-string-literals.scala:41:17
23-
41 | val unclosed = '''
24-
| ^
25-
|unclosed dedented string literal

tests/neg/dedented-string-literals.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ object CompileTimeOnlyTest {
3838

3939
// Error: Unclosed literal - must be last since it breaks parsing
4040
object UnclosedTest {
41-
val unclosed = ''' // error: unclosed dedented string literal
42-
some content
41+
val unclosed = '''
42+
some content // error: unclosed dedented string literal

tests/run/dedented-string-literals.check

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ Empty lines anywhere:
5555
content
5656

5757
more content
58-
5958
]
6059

6160
With quotes:
@@ -94,20 +93,20 @@ Interpolated pattern (two lines):
9493
Two line interpolated result: matched two line greeting
9594

9695
In function:
97-
function content
98-
more content
96+
function content
97+
more content
9998

10099
In class:
101-
class member
102-
content
100+
class member
101+
content
103102

104103
In list:
105-
Item: [first]
106-
Item: [second]
107-
Item: [third]
104+
Item: [ first]
105+
Item: [ second]
106+
Item: [ third]
108107

109108
Nested in expressions:
110-
prefixmiddlesuffix
109+
prefix middlesuffix
111110

112111
Type ascription:
113112
Value: [ first line

tests/run/dedented-string-literals.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ object Test {
112112
113113
// Test tabs for indentation
114114
val withTabs = '''
115-
tab indented
116-
content here
115+
tab indented
116+
content here
117117
'''
118118
println("With tabs:")
119119
println(withTabs)
@@ -289,8 +289,7 @@ object Test {
289289
println()
290290
291291
// Test as type parameter to valueOf
292-
import scala.compiletime.valueOf
293-
val valueOfResult = valueOf['''
292+
val valueOfResult = scala.compiletime.constValue['''
294293
alpha
295294
beta
296295
gamma

0 commit comments

Comments
 (0)