1
+ import quoted .*
2
+ import scala .compiletime .testing .{typeChecks , typeCheckErrors }
3
+ import scala .compiletime .testing .{Error , ErrorKind }
4
+
5
+ transparent inline def assertCompiles (inline code : String ): Unit =
6
+ $ { assertCompilesImpl(' code , ' {typeCheckErrors(code)}) }
7
+
8
+ given FromExpr [ErrorKind ] with {
9
+ def unapply (expr : Expr [ErrorKind ])(using Quotes ) = expr match {
10
+ case ' { ErrorKind .Parser } => Some (ErrorKind .Parser )
11
+ case ' { ErrorKind .Typer } => Some (ErrorKind .Typer )
12
+ case _ => None
13
+ }
14
+ }
15
+
16
+ given FromExpr [Error ] with {
17
+ def unapply (expr : Expr [Error ])(using Quotes ) = expr match {
18
+ case ' { Error ($ {Expr (msg)}, $ {Expr (line)}, $ {Expr (col)}, $ {Expr (kind)}) } => Some (Error (msg, line, col, kind))
19
+ case _ => None
20
+ }
21
+ }
22
+
23
+ private def assertCompilesImpl (self : Expr [_], typeChecked : Expr [List [Error ]])(using Quotes ): Expr [Unit ] = {
24
+ import quotes .reflect ._
25
+
26
+ def checkCompile (code : String ): Expr [Unit ] = {
27
+ // For some reason `typeChecked.valueOrError` is failing here, so instead we grab
28
+ // the varargs argument to List.apply and use that to extract the list of errors
29
+ val errors = typeChecked.asTerm.underlyingArgument match {
30
+ case Apply (TypeApply (Select (Ident (" List" ), " apply" ), _), List (seq)) =>
31
+ seq.asExprOf[Seq [Error ]].valueOrError.toList
32
+ }
33
+
34
+ ' {}
35
+ }
36
+
37
+ self.asTerm.underlyingArgument match {
38
+
39
+ case Literal (StringConstant (code)) =>
40
+ checkCompile(code.toString)
41
+
42
+ case Apply (Select (_, " stripMargin" ), List (Literal (StringConstant (code)))) =>
43
+ checkCompile(code.toString.stripMargin)
44
+
45
+ case _ =>
46
+ report.throwError(" The 'assertCompiles' function only works with String literals." )
47
+ }
48
+ }
0 commit comments