@@ -122,6 +122,10 @@ class TreeChecker extends Phase with SymTransformer {
122
122
val squahsedPhase = ctx.squashed(prevPhase)
123
123
ctx.echo(s " checking ${ctx.compilationUnit} after phase ${squahsedPhase}" )
124
124
125
+ if (ctx.isAfterTyper) {
126
+ WrappedNewChecker .assertSelectWrapsNew(ctx.compilationUnit.tpdTree)(ctx)
127
+ }
128
+
125
129
val checkingCtx = ctx
126
130
.fresh
127
131
.setMode(Mode .ImplicitsEnabled )
@@ -449,6 +453,53 @@ class TreeChecker extends Phase with SymTransformer {
449
453
tree
450
454
}
451
455
}
456
+
457
+ /**
458
+ * Checks that `New` nodes are always wrapped inside `Select` nodes.
459
+ */
460
+ private object WrappedNewChecker {
461
+
462
+ // Current state of the search. We return as soon as we see the first improperly wrapped `New`.
463
+ sealed trait State
464
+ case class NotFound (parent : Option [tpd.Tree ]) extends State
465
+ case class Found (parent : Option [tpd.Tree ], child : tpd.New ) extends State
466
+
467
+ def assertSelectWrapsNew (tree : tpd.Tree )(implicit ctx : Context ): Unit = {
468
+ val detect = new TreeAccumulator [State ] {
469
+ override def apply (st : State , tree : tpd.Tree )(implicit ctx : Context ): State = {
470
+ st match {
471
+ case _ : Found => st // thread the found pair
472
+ case NotFound (oldParent) =>
473
+ tree match {
474
+ case tree : tpd.New if ! canWrapNew(oldParent) => Found (oldParent, tree)
475
+ case _ =>
476
+ // replace the parent when folding over the children
477
+ foldOver(NotFound (Some (tree)), tree) match {
478
+ case found : Found => found
479
+ case _ => st // return the old parent so that my siblings see it
480
+ }
481
+ }
482
+ }
483
+ }
484
+ }
485
+
486
+ detect(NotFound (None ), tree) match {
487
+ case Found (Some (parent), child) =>
488
+ assert(assertion = false , i " `New` node must be wrapped in a `Select`: \n parent = ${parent.show}\n child = ${child.show}" )
489
+ case Found (None , child) =>
490
+ assert(assertion = false , i " `New` node without a parent: \n ${child.show}" )
491
+ case _ => ()
492
+ }
493
+ }
494
+
495
+ def canWrapNew (tree : Option [tpd.Tree ]): Boolean = {
496
+ tree match {
497
+ case Some (_ : tpd.Select ) => true
498
+ case _ => false
499
+ }
500
+ }
501
+ }
502
+
452
503
}
453
504
454
505
object TreeChecker {
0 commit comments