@@ -66,7 +66,9 @@ object Inliner {
66
66
* and body that replace it.
67
67
*/
68
68
def inlineCall (tree : Tree )(implicit ctx : Context ): Tree = {
69
- if (tree.symbol == defn.CompiletimeTesting_typeChecks ) return Intrinsics .typeChecks(tree)
69
+ if tree.symbol.owner.companionModule == defn.CompiletimeTestingPackageObject
70
+ if (tree.symbol == defn.CompiletimeTesting_typeChecks ) return Intrinsics .typeChecks(tree)
71
+ if (tree.symbol == defn.CompiletimeTesting_typeCheckErrors ) return Intrinsics .typeCheckErrors(tree)
70
72
71
73
/** Set the position of all trees logically contained in the expansion of
72
74
* inlined call `call` to the position of `call`. This transform is necessary
@@ -193,10 +195,12 @@ object Inliner {
193
195
}
194
196
195
197
object Intrinsics {
198
+ import dotty .tools .dotc .reporting .diagnostic .messages .Error
199
+ private enum ErrorKind
200
+ case Parser , Typer
196
201
197
- /** Expand call to scala.compiletime.testing.typeChecks */
198
- def typeChecks (tree : Tree )(implicit ctx : Context ): Tree = {
199
- assert(tree.symbol == defn.CompiletimeTesting_typeChecks )
202
+ private def compileForErrors (tree : Tree , stopAfterParser : Boolean )(given ctx : Context ): List [(ErrorKind , Error )] =
203
+ assert(tree.symbol == defn.CompiletimeTesting_typeChecks || tree.symbol == defn.CompiletimeTesting_typeCheckErrors )
200
204
def stripTyped (t : Tree ): Tree = t match {
201
205
case Typed (t2, _) => stripTyped(t2)
202
206
case _ => t
@@ -205,20 +209,49 @@ object Inliner {
205
209
val Apply (_, codeArg :: Nil ) = tree
206
210
ConstFold (stripTyped(codeArg.underlyingArgument)).tpe.widenTermRefExpr match {
207
211
case ConstantType (Constant (code : String )) =>
208
- val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer )
209
- val tree2 = new Parser (SourceFile .virtual(" tasty-reflect" , code))(ctx2).block()
210
- val res =
211
- if (ctx2.reporter.hasErrors) false
212
- else {
213
- ctx2.typer.typed(tree2)(ctx2)
214
- ! ctx2.reporter.hasErrors
215
- }
216
- Literal (Constant (res))
212
+ val source2 = SourceFile .virtual(" tasty-reflect" , code)
213
+ val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer ).setSource(source2)
214
+ val tree2 = new Parser (source2)(ctx2).block()
215
+ val res = collection.mutable.ListBuffer .empty[(ErrorKind , Error )]
216
+
217
+ val parseErrors = ctx2.reporter.allErrors.toList
218
+ res ++= parseErrors.map(e => ErrorKind .Parser -> e)
219
+ if ! stopAfterParser || res.isEmpty
220
+ ctx2.typer.typed(tree2)(ctx2)
221
+ val typerErrors = ctx2.reporter.allErrors.filterNot(parseErrors.contains)
222
+ res ++= typerErrors.map(e => ErrorKind .Typer -> e)
223
+ res.toList
217
224
case t =>
218
225
assert(ctx.reporter.hasErrors) // at least: argument to inline parameter must be a known value
219
- EmptyTree
226
+ Nil
220
227
}
221
- }
228
+
229
+ private def packError (kind : ErrorKind , error : Error )(given Context ): Tree =
230
+ def lit (x : Any ) = Literal (Constant (x))
231
+ val constructor : Tree = ref(defn.CompiletimeTesting_Error_apply )
232
+ val parserErrorKind : Tree = ref(defn.CompiletimeTesting_ErrorKind_Parser )
233
+ val typerErrorKind : Tree = ref(defn.CompiletimeTesting_ErrorKind_Typer )
234
+
235
+ constructor.appliedTo(
236
+ lit(error.message),
237
+ lit(error.pos.lineContent.reverse.dropWhile(" \n " .contains).reverse),
238
+ lit(error.pos.column),
239
+ if kind == ErrorKind .Parser then parserErrorKind else typerErrorKind)
240
+
241
+ private def packErrors (errors : List [(ErrorKind , Error )])(given Context ): Tree =
242
+ val individualErrors : List [Tree ] = errors.map(packError)
243
+ val errorTpt = ref(defn.CompiletimeTesting_ErrorClass )
244
+ mkList(individualErrors, errorTpt)
245
+
246
+ /** Expand call to scala.compiletime.testing.typeChecks */
247
+ def typeChecks (tree : Tree )(given Context ): Tree =
248
+ val errors = compileForErrors(tree, true )
249
+ Literal (Constant (errors.isEmpty))
250
+
251
+ /** Expand call to scala.compiletime.testing.typeCheckErrors */
252
+ def typeCheckErrors (tree : Tree )(given Context ): Tree =
253
+ val errors = compileForErrors(tree, false )
254
+ packErrors(errors)
222
255
}
223
256
}
224
257
0 commit comments