Skip to content

Commit

Permalink
Merge pull request scala#5726 from scala/revert-5629-issue/10120-quot…
Browse files Browse the repository at this point in the history
…e-err

Revert "SI-10133 Require escaped single quote char lit"
  • Loading branch information
adriaanm committed Feb 22, 2017
2 parents a8c4a54 + d60f6e3 commit effde0c
Show file tree
Hide file tree
Showing 16 changed files with 76 additions and 84 deletions.
24 changes: 6 additions & 18 deletions src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
Expand Up @@ -543,36 +543,24 @@ trait Scanners extends ScannersCommon {
}
fetchDoubleQuote()
case '\'' =>
def unclosedCharLit() = {
val msg = "unclosed character literal"
// previous token was Symbol contiguous with the orphan single quote at offset
if (token == SYMBOLLIT && offset == lastOffset) {
syntaxError(s"""$msg (or use " for string literal "$strVal")""")
} else {
syntaxError(msg)
}
}
def fetchSingleQuote() = {
nextChar()
if (isIdentifierStart(ch))
charLitOr(getIdentRest)
else if (isOperatorPart(ch) && (ch != '\\'))
charLitOr(getOperatorRest)
else if (ch == '\'') {
nextChar()
val advice = if (ch == '\'') { do nextChar() while (ch == '\''); " (use '\\'' for single quote)" } else ""
syntaxError(s"empty character literal${advice}")
}
else if (!isAtEnd && (ch != SU && ch != CR && ch != LF || isUnicodeEscape)) {
getLitChar()
if (ch != '\'') unclosedCharLit()
else {
if (ch == '\'') {
nextChar()
token = CHARLIT
setStrVal()
} else {
syntaxError("unclosed character literal")
}
}
else unclosedCharLit()
else
syntaxError("unclosed character literal")
}
fetchSingleQuote()
case '.' =>
Expand Down Expand Up @@ -804,7 +792,7 @@ trait Scanners extends ScannersCommon {
next.token = kwArray(idx)
}
} else {
syntaxError(s"invalid string interpolation $$$ch, expected: $$$$, $$identifier or $${expression}")
syntaxError("invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected")
}
} else {
val isUnclosedLiteral = !isUnicodeEscape && (ch == SU || (!multiLine && (ch == CR || ch == LF)))
Expand Down
35 changes: 35 additions & 0 deletions src/repl/scala/tools/nsc/interpreter/Formatting.scala
@@ -0,0 +1,35 @@
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* @author Paul Phillips
*/

package scala.tools.nsc
package interpreter

import util.stringFromWriter

class Formatting(indent: Int) {

private val indentation = " " * indent

private def indenting(code: String): Boolean = {
/** Heuristic to avoid indenting and thereby corrupting """-strings and XML literals. */
val tokens = List("\"\"\"", "</", "/>")
val noIndent = (code contains "\n") && (tokens exists code.contains)

!noIndent
}
/** Indent some code by the width of the scala> prompt.
* This way, compiler error messages read better.
*/
def indentCode(code: String) = stringFromWriter(str =>
for (line <- code.lines) {
if (indenting(code)) str print indentation
str println line
str.flush()
}
)
}
object Formatting {
def forPrompt(prompt: String) = new Formatting(prompt.lines.toList.last.length)
}
7 changes: 5 additions & 2 deletions src/repl/scala/tools/nsc/interpreter/IMain.scala
Expand Up @@ -111,8 +111,11 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
try body finally label = saved
}

// the expanded prompt but without color escapes and without leading newline, for purposes of indenting
lazy val formatting = Formatting.forPrompt(replProps.promptText)
lazy val reporter: ReplReporter = new ReplReporter(this)

import formatting.indentCode
import reporter.{ printMessage, printUntruncatedMessage }

// This exists mostly because using the reporter too early leads to deadlock.
Expand Down Expand Up @@ -864,8 +867,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
|${preambleHeader format lineRep.readName}
|${envLines mkString (" ", ";\n ", ";\n")}
|$importsPreamble
|${toCompute}""".stripMargin
def preambleLength = preamble.length - toCompute.length
|${indentCode(toCompute)}""".stripMargin
def preambleLength = preamble.length - toCompute.length - 1

val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this

Expand Down
33 changes: 13 additions & 20 deletions src/repl/scala/tools/nsc/interpreter/ReplReporter.scala
Expand Up @@ -9,7 +9,7 @@ package interpreter
import reporters._
import IMain._

import scala.reflect.internal.util.{OffsetPosition, Position}
import scala.reflect.internal.util.Position

/** Like ReplGlobal, a layer for ensuring extra functionality.
*/
Expand Down Expand Up @@ -40,25 +40,14 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i
case INFO => RESET
}

private val promptLength = replProps.promptText.lines.toList.last.length
private val indentation = " " * promptLength

// colorized console labels
override protected def clabel(severity: Severity): String = {
val label0 = super.clabel(severity)
if (replProps.colorOk) s"${severityColor(severity)}${label0}${RESET}" else label0
}

// shift indentation for source text entered at prompt
override def print(pos: Position, msg: String, severity: Severity) {
val adjusted =
if (pos.source.file.name == "<console>")
new OffsetPosition(pos.source, pos.offset.getOrElse(0)) {
override def lineContent = s"${indentation}${super.lineContent}"
override def lineCaret = s"${indentation}${super.lineCaret}"
}
else pos
super.print(adjusted, msg, severity)
val prefix = (
if (replProps.colorOk)
severityColor(severity) + clabel(severity) + RESET
else
clabel(severity)
)
printMessage(pos, prefix + msg)
}

override def printMessage(msg: String) {
Expand All @@ -74,8 +63,12 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i
else Console.println("[init] " + msg)
}

override def displayPrompt() = if (!intp.totalSilence) super.displayPrompt()
override def displayPrompt() {
if (intp.totalSilence) ()
else super.displayPrompt()
}

override def rerunWithDetails(setting: reflect.internal.settings.MutableSettings#Setting, name: String) =
s"; for details, enable `:setting $name' or `:replay $name'"

}
8 changes: 4 additions & 4 deletions test/files/jvm/interpreter.check
Expand Up @@ -278,13 +278,13 @@ scala> // both of the following should abort immediately:

scala> def x => y => z
<console>:1: error: '=' expected but '=>' found.
def x => y => z
^
def x => y => z
^

scala> [1,2,3]
<console>:1: error: illegal start of definition
[1,2,3]
^
[1,2,3]
^

scala>

Expand Down
8 changes: 1 addition & 7 deletions test/files/neg/badtok-1.check
Expand Up @@ -4,10 +4,4 @@ badtok-1.scala:2: error: unclosed character literal
badtok-1.scala:2: error: unclosed character literal
'42'
^
badtok-1.scala:6: error: empty character literal (use '\'' for single quote)
'''
^
badtok-1.scala:9: error: unclosed character literal (or use " for string literal "abc")
'abc'
^
four errors found
two errors found
7 changes: 0 additions & 7 deletions test/files/neg/badtok-1.scala
@@ -1,9 +1,2 @@
// bug 989
'42'


// SI-10133
'''

// SI-10120
'abc'
2 changes: 1 addition & 1 deletion test/files/neg/t5856.check
@@ -1,4 +1,4 @@
t5856.scala:10: error: invalid string interpolation $", expected: $$, $identifier or ${expression}
t5856.scala:10: error: invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected
val s9 = s"$"
^
t5856.scala:10: error: unclosed string literal
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_22.check
Expand Up @@ -15,7 +15,7 @@ scala> {
}
println(code.eval)
}
<console>:19: free term: Ident(TermName("x")) defined by res0 in <console>:18:7
<console>:19: free term: Ident(TermName("x")) defined by res0 in <console>:18:14
val code = reify {
^
2
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_23.check
Expand Up @@ -14,7 +14,7 @@ scala> def foo[T]{
}
println(code.eval)
}
<console>:17: free type: Ident(TypeName("T")) defined by foo in <console>:16:9
<console>:17: free type: Ident(TypeName("T")) defined by foo in <console>:16:16
val code = reify {
^
foo: [T]=> Unit
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_25.check
Expand Up @@ -5,7 +5,7 @@ scala> {
val tt = implicitly[TypeTag[x.type]]
println(tt)
}
<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:7
<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:14
val tt = implicitly[TypeTag[x.type]]
^
TypeTag[x.type]
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_26.check
Expand Up @@ -4,7 +4,7 @@ scala> def foo[T]{
val tt = implicitly[WeakTypeTag[List[T]]]
println(tt)
}
<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:11:9
<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:11:16
val tt = implicitly[WeakTypeTag[List[T]]]
^
foo: [T]=> Unit
Expand Down
8 changes: 4 additions & 4 deletions test/files/run/repl-colon-type.check
@@ -1,8 +1,8 @@

scala> :type List[1, 2, 3]
<console>:1: error: identifier expected but integer literal found.
List[1, 2, 3]
^
List[1, 2, 3]
^

scala> :type List(1, 2, 3)
List[Int]
Expand Down Expand Up @@ -38,8 +38,8 @@ scala> :type protected lazy val f = 5
Access to protected lazy value f not permitted because
enclosing object $eval in package $line13 is not a subclass of
object $iw where target is defined
lazy val $result = f
^
lazy val $result = f
^

scala> :type def f = 5
=> Int
Expand Down
14 changes: 0 additions & 14 deletions test/files/run/t8918-unary-ids.check
Expand Up @@ -5,17 +5,3 @@ Expected 41 lines, got 39
-Type in expressions to have them evaluated.
-Type :help for more information.

@@ -14,4 +12,4 @@
<console>:1: error: illegal start of simple expression
-- if (true) 1 else 2
- ^
+ - if (true) 1 else 2
+ ^

@@ -19,4 +17,4 @@
<console>:1: error: ';' expected but integer literal found.
-- - 1
- ^
+ - - 1
+ ^

4 changes: 2 additions & 2 deletions test/files/run/t9170.scala
Expand Up @@ -48,8 +48,8 @@ object Y {
def f[A](a: => A): Int at line 12 and
def f[A](a: => Either[Exception,A]): Int at line 13
have same type after erasure: (a: Function0)Int
def f[A](a: => Either[Exception, A]) = 2
^
def f[A](a: => Either[Exception, A]) = 2
^
scala> :quit"""
}
Expand Down
2 changes: 1 addition & 1 deletion test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala
Expand Up @@ -96,7 +96,7 @@ class ScriptedTest {
}
@Test def `on compile error`(): Unit = {
val engine = scripted
val err = "not found: value foo in def f = foo at line number 11 at column number 9"
val err = "not found: value foo in def f = foo at line number 11 at column number 16"
assertThrows[ScriptException](engine.compile("def f = foo"), _ == err)
}
}

0 comments on commit effde0c

Please sign in to comment.