Skip to content

Commit 90371d2

Browse files
committed
Add typeChecks to tasty reflect
1 parent a7b67c4 commit 90371d2

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ package tastyreflect
33

44
import dotty.tools.dotc.ast.{Trees, tpd, untpd}
55
import dotty.tools.dotc.ast.tpd.TreeOps
6+
import dotty.tools.dotc.typer.Typer
67
import dotty.tools.dotc.core._
78
import dotty.tools.dotc.core.Flags._
89
import dotty.tools.dotc.core.StdNames.nme
910
import dotty.tools.dotc.core.quoted.PickledQuotes
1011
import dotty.tools.dotc.core.Symbols._
1112
import dotty.tools.dotc.core.Decorators._
1213
import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFromSym}
14+
import dotty.tools.dotc.parsing.Parsers.Parser
15+
import dotty.tools.dotc.util.SourceFile
1316

1417
import scala.tasty.reflect.Kernel
1518

@@ -47,6 +50,23 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
4750

4851
def Settings_color(self: Settings): Boolean = self.color.value(rootContext) == "always"
4952

53+
//
54+
// MISC
55+
//
56+
/** Whether the code type checks in the given context?
57+
*
58+
* @param code The code to be type checked
59+
*
60+
* The code should be a sequence of expressions or statements that may appear in a block.
61+
*/
62+
def typeChecks(code: String)(implicit ctx: Context): Boolean = {
63+
val tree = new Parser(SourceFile.virtual("tasty-reflect", code)).block()
64+
65+
val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer)
66+
ctx2.typer.typed(tree)(ctx2)
67+
!ctx2.reporter.hasErrors
68+
}
69+
5070
//
5171
// TREES
5272
//

library/src/scala/tasty/Reflection.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ abstract class Reflection
2727
def typeOf[T: scala.quoted.Type]: Type =
2828
implicitly[scala.quoted.Type[T]].unseal.tpe
2929

30+
31+
/** Whether the code type checks in the given context?
32+
*
33+
* @param code The code to be type checked
34+
*
35+
* The code should be a sequence of expressions or statements that may appear in a block.
36+
*/
37+
def typeChecks(code: String)(implicit ctx: Context): Boolean = kernel.typeChecks(code)(ctx)
38+
3039
val util: reflect.utils.TreeUtils { val reflect: self.type } = new reflect.utils.TreeUtils {
3140
val reflect: self.type = self
3241
}

library/src/scala/tasty/reflect/Kernel.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,17 @@ trait Kernel {
153153

154154
def Settings_color(self: Settings): Boolean
155155

156+
//
157+
// MISC
158+
//
159+
/** Whether the code type checks in the given context?
160+
*
161+
* @param code The code to be type checked
162+
*
163+
* The code should be a sequence of expressions or statements that may appear in a block.
164+
*/
165+
def typeChecks(code: String)(implicit ctx: Context): Boolean
166+
156167
//
157168
// TREES
158169
//
@@ -695,7 +706,7 @@ trait Kernel {
695706
//
696707
// PATTERNS
697708
//
698-
709+
699710
/** Pattern tree of the pattern part of a CaseDef */
700711
type Pattern <: AnyRef
701712

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.quoted._
2+
import scala.tasty._
3+
4+
object scalatest {
5+
6+
inline def assertCompiles(inline code: String): Unit = ${ assertImpl(code, true) }
7+
inline def assertNotCompile(inline code: String): Unit = ${ assertImpl(code, false) }
8+
9+
def assertImpl(code: String, expect: Boolean)(implicit refl: Reflection): Expr[Unit] = {
10+
import refl._
11+
12+
val actual = typeChecks(code)
13+
14+
'{ assert(${expect.toExpr} == ${actual.toExpr}) }
15+
}
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object Test {
2+
import scalatest._
3+
4+
trait Eq[T]
5+
implicit val eq: Eq[Int] = new Eq[Int] {}
6+
7+
implicit class AnyOps[T](x: T) {
8+
def === (y: T)(implicit c: Eq[T]) = x == y
9+
}
10+
11+
def main(args: Array[String]): Unit = {
12+
assertCompiles("5 === 5")
13+
assertNotCompile("5.6 === 7.7")
14+
}
15+
}

0 commit comments

Comments
 (0)