diff options
author | Som Snytt <som.snytt@gmail.com> | 2016-03-23 11:23:41 -0700 |
---|---|---|
committer | Som Snytt <som.snytt@gmail.com> | 2016-03-23 11:23:41 -0700 |
commit | 75cfd808aec7cd94ab3e2c13ffd4821887de6ddd (patch) | |
tree | 787bc3b522632261f7a8ee43dbc50b0b648ab7b8 | |
parent | 275305a3d291cca49163903b5b6fe1d496b507a6 (diff) | |
download | scala-75cfd808aec7cd94ab3e2c13ffd4821887de6ddd.tar.gz scala-75cfd808aec7cd94ab3e2c13ffd4821887de6ddd.tar.bz2 scala-75cfd808aec7cd94ab3e2c13ffd4821887de6ddd.zip |
SI-9314 No warn on ${nonid}
Use the sym test on an expr that happens to be a subset of
idents and is not in scope. Other `${ operator_* }` warn.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 18 | ||||
-rw-r--r-- | test/files/neg/t7848-interp-warn.check | 18 | ||||
-rw-r--r-- | test/files/neg/t7848-interp-warn.scala | 13 |
3 files changed, 36 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1b55618691..facb695447 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 { @@ -5211,14 +5211,18 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper 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 - val suspiciousExpr = InterpolatorCodeRegex findFirstMatchIn s + val suspiciousExprs = InterpolatorCodeRegex findAllMatchIn s def suspiciousIdents = InterpolatorIdentRegex findAllIn s map (s => suspiciousSym(TermName(s drop 1))) - - if (suspiciousExpr.nonEmpty) - suspiciousExpr filter (!_.group(1).trim.isEmpty) foreach (_ => + 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 + } 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 ad66ae1577..cc94cc81de 100644 --- a/test/files/neg/t7848-interp-warn.check +++ b/test/files/neg/t7848-interp-warn.check @@ -1,8 +1,8 @@ t7848-interp-warn.scala:18: warning: possible missing interpolator: detected interpolated identifier `$foo` - "An important $foo message!" + "An important $foo message!" // warn on ident in scope ^ t7848-interp-warn.scala:22: warning: possible missing interpolator: detected an interpolated expression - "A doubly important ${foo * 2} message!" + "A doubly important ${foo * 2} message!" // warn on some expr, see below ^ 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 @@ -10,6 +10,18 @@ t7848-interp-warn.scala:25: warning: possible missing interpolator: detected int 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 635dd48c27..ceaf6c7d67 100644 --- a/test/files/neg/t7848-interp-warn.scala +++ b/test/files/neg/t7848-interp-warn.scala @@ -15,16 +15,23 @@ object Test { 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 j = s"Try using '${ "something like $bar" }' instead." // warn 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! + 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 } |