Skip to content

Instantly share code, notes, and snippets.

@szeiger
Created March 25, 2013 17:41
Show Gist options
  • Save szeiger/5239006 to your computer and use it in GitHub Desktop.
Save szeiger/5239006 to your computer and use it in GitHub Desktop.
Compile-time unit tests that check for type-checking failures
package scala.slick.test.lifted
import com.typesafe.slick.testkit.util.ShouldNotTypecheck
class NegativeCompilationTests {
def noColumnBaseToOptionConversion = ShouldNotTypecheck("""
class FooBarBlub extends String
""", "illegal inheritance from final class String")
}
package com.typesafe.slick.testkit.util
import scala.language.experimental.macros
import scala.reflect.macros.{Context, TypecheckException}
import scala.util.control.NonFatal
/**
* A macro that ensures that a code snippet does not typecheck.
*/
object ShouldNotTypecheck {
def apply(code: String): Unit = macro applyImplNoExp
def apply(code: String, expected: String): Unit = macro applyImpl
def applyImplNoExp(ctx: Context)(code: ctx.Expr[String]) = applyImpl(ctx)(code, null)
def applyImpl(ctx: Context)(code: ctx.Expr[String], expected: ctx.Expr[String]): ctx.Expr[Unit] = {
import ctx.universe._
val Expr(Literal(Constant(codeStr: String))) = code
val (expStr, expMsg) = expected match {
case null => (null, "Expected error: <unspecified>")
case Expr(Literal(Constant(s: String))) => (s, "Expected error: "+s)
}
try ctx.typeCheck(ctx.parse("{ "+codeStr+" }")) catch { case e: TypecheckException =>
val msg = e.getMessage
if((expected ne null) && (expStr != msg))
ctx.abort(ctx.enclosingPosition, "Type-checking failed in an unexpected way.\n"+
expMsg+"\nActual error: "+msg)
else return reify(())
}
ctx.abort(ctx.enclosingPosition, "Type-checking succeeded unexpectedly.\n"+expMsg)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment