Skip to content

Commit a8edefc

Browse files
committed
SI-7271 fixes positions of string interpolation parts
Positions of static parts are now set explicitly during parsing rather than filled in wholesale during subsequent atPos after parsing. I also had to change the offsets that scanner uses for initial static parts of string interpolations so that they no longer point to the opening double quote, but rather to the actual beginning of the part.
1 parent 403ba89 commit a8edefc

File tree

6 files changed

+54
-6
lines changed

6 files changed

+54
-6
lines changed

src/compiler/scala/tools/nsc/ast/parser/Parsers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ self =>
11521152
val exprBuf = new ListBuffer[Tree]
11531153
in.nextToken()
11541154
while (in.token == STRINGPART) {
1155-
partsBuf += literal()
1155+
partsBuf += atPos(in.offset)(literal())
11561156
exprBuf += {
11571157
if (inPattern) dropAnyBraces(pattern())
11581158
else {
@@ -1166,7 +1166,7 @@ self =>
11661166
}
11671167
}
11681168
}
1169-
if (in.token == STRINGLIT) partsBuf += literal()
1169+
if (in.token == STRINGLIT) partsBuf += atPos(in.offset)(literal())
11701170

11711171
val t1 = atPos(o2p(start)) { Ident(nme.StringContext) }
11721172
val t2 = atPos(start) { Apply(t1, partsBuf.toList) }

src/compiler/scala/tools/nsc/ast/parser/Scanners.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ trait Scanners extends ScannersCommon {
425425
if (ch == '\"') {
426426
nextRawChar()
427427
if (ch == '\"') {
428+
offset += 3
428429
nextRawChar()
429430
getStringPart(multiLine = true)
430431
sepRegions = STRINGPART :: sepRegions // indicate string part
@@ -434,6 +435,7 @@ trait Scanners extends ScannersCommon {
434435
strVal = ""
435436
}
436437
} else {
438+
offset += 1
437439
getStringPart(multiLine = false)
438440
sepRegions = STRINGLIT :: sepRegions // indicate single line string part
439441
}

test/files/neg/t5510.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
t5510.scala:2: error: unclosed string literal
22
val s1 = s"xxx
3-
^
3+
^
44
t5510.scala:3: error: unclosed string literal
55
val s2 = s"xxx $x
66
^
77
t5510.scala:4: error: unclosed string literal
88
val s3 = s"xxx $$
9-
^
9+
^
1010
t5510.scala:5: error: unclosed string literal
1111
val s4 = ""s"
12-
^
12+
^
1313
t5510.scala:6: error: unclosed multi-line string literal
1414
val s5 = ""s""" $s1 $s2 s"
1515
^

test/files/neg/t5856.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
t5856.scala:10: error: invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected
22
val s9 = s"$"
3-
^
3+
^
44
t5856.scala:10: error: unclosed string literal
55
val s9 = s"$"
66
^

test/files/run/t7271.check

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[[syntax trees at end of parser]] // newSource1
2+
[0:91]package [0:0]<empty> {
3+
[0:91]class C extends [8:91][91]scala.AnyRef {
4+
[8]def <init>() = [8]{
5+
[8][8][8]super.<init>();
6+
[8]()
7+
};
8+
[16:44]def quote = [28:44]<28:44><28:44>[28]StringContext([30:34]"foo", [40:44]"baz").s([35:39]this);
9+
[51:85]def tripleQuote = [69:85]<69:85><69:85>[69]StringContext([71:75]"foo", [81:85]"baz").s([76:80]this)
10+
}
11+
}
12+

test/files/run/t7271.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import scala.tools.partest._
2+
import java.io._
3+
import scala.tools.nsc._
4+
import scala.tools.nsc.util.CommandLineParser
5+
import scala.tools.nsc.{Global, Settings, CompilerCommand}
6+
import scala.tools.nsc.reporters.ConsoleReporter
7+
8+
object Test extends DirectTest {
9+
10+
override def extraSettings: String = "-usejavacp -Xprint:parser -Ystop-after:parser -d " + testOutput.path
11+
12+
override def code = """
13+
class C {
14+
def quote = s"foo${this}baz"
15+
def tripleQuote = s"foo${this}baz"
16+
}
17+
""".trim
18+
19+
override def show(): Unit = {
20+
// redirect err to out, for logging
21+
val prevErr = System.err
22+
System.setErr(System.out)
23+
compile()
24+
System.setErr(prevErr)
25+
}
26+
27+
override def newCompiler(args: String*): Global = {
28+
29+
val settings = new Settings()
30+
settings.Xprintpos.value = true
31+
val command = new CompilerCommand((CommandLineParser tokenize extraSettings) ++ args.toList, settings)
32+
new Global(command.settings, new ConsoleReporter(settings)) with interactive.RangePositions
33+
}
34+
}

0 commit comments

Comments
 (0)