summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2016-03-23 21:18:26 +0100
committerLukas Rytz <lukas.rytz@typesafe.com>2016-03-23 21:18:26 +0100
commit1802aa4eb22939d79f1cab67def5013025f24939 (patch)
tree8b95cb0ba759039c81a71a5de11e5e45478687ec
parent952da60a5be15ef972b521bdaf5e650f7e0a5245 (diff)
parent75cfd808aec7cd94ab3e2c13ffd4821887de6ddd (diff)
downloadscala-1802aa4eb22939d79f1cab67def5013025f24939.tar.gz
scala-1802aa4eb22939d79f1cab67def5013025f24939.tar.bz2
scala-1802aa4eb22939d79f1cab67def5013025f24939.zip
Merge pull request #5053 from som-snytt/issue/9314
SI-9314 Marginal edge case to warn-missing-interp
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala20
-rw-r--r--test/files/neg/t7848-interp-warn.check28
-rw-r--r--test/files/neg/t7848-interp-warn.scala29
3 files changed, 57 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9446a45c06..16d3f5134b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -105,7 +105,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// that are turned private by typedBlock
private final val SYNTHETIC_PRIVATE = TRANS_FLAG
- private final val InterpolatorCodeRegex = """\$\{.*?\}""".r
+ private final val InterpolatorCodeRegex = """\$\{\s*(.*?)\s*\}""".r
private final val InterpolatorIdentRegex = """\$[$\w]+""".r // note that \w doesn't include $
abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with PatternTyper with TyperContextErrors {
@@ -5206,17 +5206,23 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case MethodType(p :: _, _) => p.isImplicit // implicit method requires no args
case _ => true // catches all others including NullaryMethodType
}
- def isPlausible(m: Symbol) = m.alternatives exists (m => requiresNoArgs(m.info))
+ def isPlausible(m: Symbol) = !m.isPackage && m.alternatives.exists(x => requiresNoArgs(x.info))
def maybeWarn(s: String): Unit = {
def warn(message: String) = context.warning(lit.pos, s"possible missing interpolator: $message")
def suspiciousSym(name: TermName) = context.lookupSymbol(name, _ => true).symbol
- def suspiciousExpr = InterpolatorCodeRegex findFirstIn s
+ val suspiciousExprs = InterpolatorCodeRegex findAllMatchIn s
def suspiciousIdents = InterpolatorIdentRegex findAllIn s map (s => suspiciousSym(TermName(s drop 1)))
-
- if (suspiciousExpr.nonEmpty)
- warn("detected an interpolated expression") // "${...}"
- else
+ def isCheapIdent(expr: String) = (Character.isJavaIdentifierStart(expr.charAt(0)) &&
+ expr.tail.forall(Character.isJavaIdentifierPart))
+ def warnableExpr(expr: String) = !expr.isEmpty && (!isCheapIdent(expr) || isPlausible(suspiciousSym(TermName(expr))))
+
+ if (suspiciousExprs.nonEmpty) {
+ val exprs = (suspiciousExprs map (_ group 1)).toList
+ // short-circuit on leading ${}
+ if (!exprs.head.isEmpty && exprs.exists(warnableExpr))
+ warn("detected an interpolated expression") // "${...}"
+ } else
suspiciousIdents find isPlausible foreach (sym => warn(s"detected interpolated identifier `$$${sym.name}`")) // "$id"
}
lit match {
diff --git a/test/files/neg/t7848-interp-warn.check b/test/files/neg/t7848-interp-warn.check
index 637fc8941a..cc94cc81de 100644
--- a/test/files/neg/t7848-interp-warn.check
+++ b/test/files/neg/t7848-interp-warn.check
@@ -1,15 +1,27 @@
-t7848-interp-warn.scala:8: warning: possible missing interpolator: detected interpolated identifier `$foo`
- "An important $foo message!"
+t7848-interp-warn.scala:18: warning: possible missing interpolator: detected interpolated identifier `$foo`
+ "An important $foo message!" // warn on ident in scope
^
-t7848-interp-warn.scala:12: warning: possible missing interpolator: detected an interpolated expression
- "A doubly important ${foo * 2} message!"
+t7848-interp-warn.scala:22: warning: possible missing interpolator: detected an interpolated expression
+ "A doubly important ${foo * 2} message!" // warn on some expr, see below
^
-t7848-interp-warn.scala:15: warning: possible missing interpolator: detected interpolated identifier `$bar`
- def i = s"Try using '${ "$bar" }' instead." // was: no warn on space test
+t7848-interp-warn.scala:25: warning: possible missing interpolator: detected interpolated identifier `$bar`
+ def i = s"Try using '${ "$bar" }' instead." // was: no warn on space test
^
-t7848-interp-warn.scala:16: warning: possible missing interpolator: detected interpolated identifier `$bar`
+t7848-interp-warn.scala:26: warning: possible missing interpolator: detected interpolated identifier `$bar`
def j = s"Try using '${ "something like $bar" }' instead." // warn
^
+t7848-interp-warn.scala:32: warning: possible missing interpolator: detected an interpolated expression
+ def v = "${baz}${bar}" // warn on second expr
+ ^
+t7848-interp-warn.scala:33: warning: possible missing interpolator: detected an interpolated expression
+ def w = "${ op_* }" // warn, only cheap ident parsing
+ ^
+t7848-interp-warn.scala:34: warning: possible missing interpolator: detected an interpolated expression
+ def x = "${ bar }" // warn, a cheap ident in scope
+ ^
+t7848-interp-warn.scala:36: warning: possible missing interpolator: detected an interpolated expression
+ def z = "${ baz * 3}" // warn, no expr parsing
+ ^
error: No warnings can be incurred under -Xfatal-warnings.
-four warnings found
+8 warnings found
one error found
diff --git a/test/files/neg/t7848-interp-warn.scala b/test/files/neg/t7848-interp-warn.scala
index a76141041d..ceaf6c7d67 100644
--- a/test/files/neg/t7848-interp-warn.scala
+++ b/test/files/neg/t7848-interp-warn.scala
@@ -1,18 +1,37 @@
package test
+package pancake { }
+
object Test {
+ type NonVal = Int
+
+ def ok = "Don't warn on $nosymbol interpolated."
+
+ def pass = "Don't warn on $pancake package names."
+
+ def types = "Or $NonVal type symbols either."
+
def bar = "bar"
def f = {
val foo = "bar"
- "An important $foo message!"
+ "An important $foo message!" // warn on ident in scope
}
def g = {
val foo = "bar"
- "A doubly important ${foo * 2} message!"
+ "A doubly important ${foo * 2} message!" // warn on some expr, see below
}
- def h = s"Try using '$$bar' instead." // no warn
- def i = s"Try using '${ "$bar" }' instead." // was: no warn on space test
+ def h = s"Try using '$$bar' instead." // no warn
+ def i = s"Try using '${ "$bar" }' instead." // was: no warn on space test
def j = s"Try using '${ "something like $bar" }' instead." // warn
- def k = f"Try using '$bar' instead." // no warn on other std interps
+ def k = f"Try using '$bar' instead." // no warn on other std interps
+ def p = "Template ${} {}" // no warn on unlikely or empty expressions
+ def q = "${}$bar" // disables subsequent checks! (a feature)
+ def r = "${}${bar}" // disables subsequent checks! (a feature)
+
+ def v = "${baz}${bar}" // warn on second expr
+ def w = "${ op_* }" // warn, only cheap ident parsing
+ def x = "${ bar }" // warn, a cheap ident in scope
+ def y = "${ baz }" // no warn, cheap ident not in scope
+ def z = "${ baz * 3}" // warn, no expr parsing
}