I have some nested case classes, and for a specific serialization mechanism I need to provide a productPrefix
that contains $
characters. Like so
object Foo {
case class Bar() {
override def productPrefix = "Foo$Bar"
}
}
Now I get a compiler warning from this:
Warning:(53, 42) possible missing interpolator: detected interpolated identifier `$Bar` override def productPrefix: String = "Foo$Bar"
Is there a way to disable the warning, if possible only for this instance? Scala version is 2.11.8.
Edit: I just thought I was clever: "Foo\u0024Bar"
. But the compiler even warns about this. Another solution is classOf[Bar].getName
, given the constraint that there are no further outer objects.
If there's a way to compose the string from its parts you could do something like this.
override def productPrefix = "Foo$" + "Bar"
You could also quiet the "missing interpolator" warning by actually invoking the interpolator, but escaping the $
.
override def productPrefix = f"Foo$$Bar"
The warning only happens when there is an identifier with that name in the lexical scope. In case the linter complains about it when the identifier is a val/var, you could just rename the val/var
The warning is induced by -Xlint
. The specific linter about the supposedly missing interpolator can be disabled by giving the scalac
command line option as
-Xlint:_,-missing-interpolator
The underscore (_
) is for "everything" and the -missing-interpolator
is for "except the missing interpolator warning".
-Xlint
warns if it sees a var in scope:
$ scala -Xlint
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> { val x = "hi" ; s"$x" }
res0: String = hi
scala> { val x = "hi" ; "$x" }
<console>:12: warning: possible missing interpolator: detected interpolated identifier `$x`
{ val x = "hi" ; "$x" }
^
res1: String = $x
scala> { val y = "hi" ; "$x" } // no warning if x is not a symbol
res2: String = $x
scala> object Foo { case class Bar() { override def productPrefix = "Foo$Bar" } }
<console>:11: warning: possible missing interpolator: detected interpolated identifier `$Bar`
object Foo { case class Bar() { override def productPrefix = "Foo$Bar" } }
^
defined object Foo
Usually, use double dollar for literal dollar when interpolating. (Edit: to be clear, $$
is like \$
.)
scala> object Foo { case class Bar() { override def productPrefix = s"Foo$$Bar" } }
defined object Foo
scala> Foo.Bar().productPrefix
res8: String = Foo$Bar
Use f-interpolator to get a constant string.
scala> def productPrefix = f"Foo$$Bar"
productPrefix: String
scala> :javap -pv -
[snip]
public java.lang.String productPrefix();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: ldc #16 // String Foo$Bar
2: areturn
You can also put your funky constants in a quarantined scope:
scala> :pa -raw
// Entering paste mode (ctrl-D to finish)
package k {
trait K { final val p = "Foo$Bar" }
}
package q {
case class Bar() { override def productPrefix = (null: k.K).p }
}
// Exiting paste mode, now interpreting.
scala> q.Bar().productPrefix
res1: String = Foo$Bar
The constant is inlined. The trick of the null reference avoids any allocations, including any singleton object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With