@@ -106,71 +106,23 @@ import dotty.tools.dotc.transform.MegaPhase._
106106 * some point in the future.
107107 */
108108class JUnitBootstrappers extends MiniPhase {
109+ import JUnitBootstrappers ._
109110 import ast .tpd ._
111+ import JSDefinitions .jsdefn
110112
111113 def phaseName : String = " junitBootstrappers"
112114
113115 override def isEnabled (implicit ctx : Context ): Boolean =
114116 super .isEnabled && ctx.settings.scalajs.value
115117
116- private object Names {
117- val beforeClass : TermName = termName(" beforeClass" )
118- val afterClass : TermName = termName(" afterClass" )
119- val before : TermName = termName(" before" )
120- val after : TermName = termName(" after" )
121- val tests : TermName = termName(" tests" )
122- val invokeTest : TermName = termName(" invokeTest" )
123- val newInstance : TermName = termName(" newInstance" )
124-
125- val instance : TermName = termName(" instance" )
126- val name : TermName = termName(" name" )
127- val castInstance : TermName = termName(" castInstance" )
128- }
129-
130- private class MyDefinitions ()(implicit ctx : Context ) {
131- lazy val TestAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.Test" )
132- def TestAnnotClass (implicit ctx : Context ): ClassSymbol = TestAnnotType .symbol.asClass
133-
134- lazy val BeforeAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.Before" )
135- def BeforeAnnotClass (implicit ctx : Context ): ClassSymbol = BeforeAnnotType .symbol.asClass
136-
137- lazy val AfterAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.After" )
138- def AfterAnnotClass (implicit ctx : Context ): ClassSymbol = AfterAnnotType .symbol.asClass
139-
140- lazy val BeforeClassAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.BeforeClass" )
141- def BeforeClassAnnotClass (implicit ctx : Context ): ClassSymbol = BeforeClassAnnotType .symbol.asClass
142-
143- lazy val AfterClassAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.AfterClass" )
144- def AfterClassAnnotClass (implicit ctx : Context ): ClassSymbol = AfterClassAnnotType .symbol.asClass
145-
146- lazy val IgnoreAnnotType : TypeRef = ctx.requiredClassRef(" org.junit.Ignore" )
147- def IgnoreAnnotClass (implicit ctx : Context ): ClassSymbol = IgnoreAnnotType .symbol.asClass
148-
149- lazy val BootstrapperType : TypeRef = ctx.requiredClassRef(" org.scalajs.junit.Bootstrapper" )
150-
151- lazy val TestMetadataType : TypeRef = ctx.requiredClassRef(" org.scalajs.junit.TestMetadata" )
152-
153- lazy val NoSuchMethodExceptionType : TypeRef = ctx.requiredClassRef(" java.lang.NoSuchMethodException" )
154-
155- lazy val FutureType : TypeRef = ctx.requiredClassRef(" scala.concurrent.Future" )
156- def FutureClass (implicit ctx : Context ): ClassSymbol = FutureType .symbol.asClass
157-
158- private lazy val FutureModule_successfulR = ctx.requiredModule(" scala.concurrent.Future" ).requiredMethodRef(" successful" )
159- def FutureModule_successful (implicit ctx : Context ): Symbol = FutureModule_successfulR .symbol
160-
161- private lazy val SuccessModule_applyR = ctx.requiredModule(" scala.util.Success" ).requiredMethodRef(nme.apply)
162- def SuccessModule_apply (implicit ctx : Context ): Symbol = SuccessModule_applyR .symbol
163- }
164-
165118 // The actual transform -------------------------------
166119
167120 override def transformPackageDef (tree : PackageDef )(implicit ctx : Context ): Tree = {
168- // TODO Can we cache this better?
169- implicit val mydefn : MyDefinitions = new MyDefinitions ()
121+ val junitdefn = jsdefn.junit
170122
171123 @ tailrec
172124 def hasTests (sym : ClassSymbol ): Boolean = {
173- sym.info.decls.exists(m => m.is(Method ) && m.hasAnnotation(mydefn .TestAnnotClass )) ||
125+ sym.info.decls.exists(m => m.is(Method ) && m.hasAnnotation(junitdefn .TestAnnotClass )) ||
174126 sym.superClass.exists && hasTests(sym.superClass.asClass)
175127 }
176128
@@ -190,32 +142,39 @@ class JUnitBootstrappers extends MiniPhase {
190142 }
191143
192144 private def genBootstrapper (testClass : ClassSymbol )(
193- implicit ctx : Context , mydefn : MyDefinitions ): TypeDef = {
145+ implicit ctx : Context ): TypeDef = {
146+
147+ val junitdefn = jsdefn.junit
148+
149+ /* The name of the boostrapper module. It is derived from the test class name by
150+ * appending a specific suffix string mandated "by spec". It will indeed also be
151+ * computed as such at run-time by the Scala.js JUnit Runtime support. Therefore,
152+ * it must *not* be a dotc semantic name.
153+ */
154+ val bootstrapperName = (testClass.name ++ " $scalajs$junit$bootstrapper" ).toTermName
194155
195156 val owner = testClass.owner
196- val moduleSym = ctx.newCompleteModuleSymbol(owner,
197- (testClass.name ++ " $scalajs$junit$bootstrapper" ).toTermName,
157+ val moduleSym = ctx.newCompleteModuleSymbol(owner, bootstrapperName,
198158 Synthetic , Synthetic ,
199- List (defn.ObjectType , mydefn .BootstrapperType ), newScope,
159+ List (defn.ObjectType , junitdefn .BootstrapperType ), newScope,
200160 coord = testClass.span, assocFile = testClass.assocFile).entered
201161 val classSym = moduleSym.moduleClass.asClass
202162
203163 val constr = genConstructor(classSym)
204164
205- val testMethods = annotatedMethods(testClass, mydefn .TestAnnotClass )
165+ val testMethods = annotatedMethods(testClass, junitdefn .TestAnnotClass )
206166
207167 val defs = List (
208- genCallOnModule(classSym, Names .beforeClass, testClass.companionModule, mydefn .BeforeClassAnnotClass ),
209- genCallOnModule(classSym, Names .afterClass, testClass.companionModule, mydefn .AfterClassAnnotClass ),
210- genCallOnParam(classSym, Names .before, testClass, mydefn .BeforeAnnotClass ),
211- genCallOnParam(classSym, Names .after, testClass, mydefn .AfterAnnotClass ),
168+ genCallOnModule(classSym, junitNme .beforeClass, testClass.companionModule, junitdefn .BeforeClassAnnotClass ),
169+ genCallOnModule(classSym, junitNme .afterClass, testClass.companionModule, junitdefn .AfterClassAnnotClass ),
170+ genCallOnParam(classSym, junitNme .before, testClass, junitdefn .BeforeAnnotClass ),
171+ genCallOnParam(classSym, junitNme .after, testClass, junitdefn .AfterAnnotClass ),
212172 genTests(classSym, testMethods),
213173 genInvokeTest(classSym, testClass, testMethods),
214174 genNewInstance(classSym, testClass)
215175 )
216176
217- if (ctx.sbtCallback != null )
218- sbt.APIUtils .registerDummyClass(classSym)
177+ sbt.APIUtils .registerDummyClass(classSym)
219178
220179 ClassDef (classSym, constr, defs)
221180 }
@@ -247,7 +206,7 @@ class JUnitBootstrappers extends MiniPhase {
247206
248207 private def genCallOnParam (owner : ClassSymbol , name : TermName , testClass : ClassSymbol , annot : Symbol )(implicit ctx : Context ): DefDef = {
249208 val sym = ctx.newSymbol(owner, name, Synthetic | Method ,
250- MethodType (Names .instance :: Nil , defn.ObjectType :: Nil , defn.UnitType )).entered
209+ MethodType (junitNme .instance :: Nil , defn.ObjectType :: Nil , defn.UnitType )).entered
251210
252211 DefDef (sym, { (paramRefss : List [List [Tree ]]) =>
253212 val List (List (instanceParamRef)) = paramRefss
@@ -258,41 +217,45 @@ class JUnitBootstrappers extends MiniPhase {
258217 }
259218
260219 private def genTests (owner : ClassSymbol , tests : List [Symbol ])(
261- implicit ctx : Context , mydefn : MyDefinitions ): DefDef = {
220+ implicit ctx : Context ): DefDef = {
221+
222+ val junitdefn = jsdefn.junit
262223
263- val sym = ctx.newSymbol(owner, Names .tests, Synthetic | Method ,
264- MethodType (Nil , defn.ArrayOf (mydefn .TestMetadataType ))).entered
224+ val sym = ctx.newSymbol(owner, junitNme .tests, Synthetic | Method ,
225+ MethodType (Nil , defn.ArrayOf (junitdefn .TestMetadataType ))).entered
265226
266227 DefDef (sym, {
267228 val metadata = for (test <- tests) yield {
268229 val name = Literal (Constant (test.name.toString))
269- val ignored = Literal (Constant (test.hasAnnotation(mydefn .IgnoreAnnotClass )))
230+ val ignored = Literal (Constant (test.hasAnnotation(junitdefn .IgnoreAnnotClass )))
270231 // TODO Handle @Test annotations with arguments
271232 // val reifiedAnnot = New(mydefn.TestAnnotType, test.getAnnotation(mydefn.TestAnnotClass).get.arguments)
272- val testAnnot = test.getAnnotation(mydefn .TestAnnotClass ).get
233+ val testAnnot = test.getAnnotation(junitdefn .TestAnnotClass ).get
273234 if (testAnnot.arguments.nonEmpty)
274235 ctx.error(" @Test annotations with arguments are not yet supported in Scala.js for dotty" , testAnnot.tree.sourcePos)
275- val noArgConstr = mydefn .TestAnnotType .member(nme.CONSTRUCTOR ).suchThat(_.info.paramInfoss.head.isEmpty).symbol.asTerm
276- val reifiedAnnot = New (mydefn .TestAnnotType , noArgConstr, Nil )
277- New (mydefn .TestMetadataType , List (name, ignored, reifiedAnnot))
236+ val noArgConstr = junitdefn .TestAnnotType .member(nme.CONSTRUCTOR ).suchThat(_.info.paramInfoss.head.isEmpty).symbol.asTerm
237+ val reifiedAnnot = New (junitdefn .TestAnnotType , noArgConstr, Nil )
238+ New (junitdefn .TestMetadataType , List (name, ignored, reifiedAnnot))
278239 }
279- JavaSeqLiteral (metadata, TypeTree (mydefn .TestMetadataType ))
240+ JavaSeqLiteral (metadata, TypeTree (junitdefn .TestMetadataType ))
280241 })
281242 }
282243
283244 private def genInvokeTest (owner : ClassSymbol , testClass : ClassSymbol , tests : List [Symbol ])(
284- implicit ctx : Context , mydefn : MyDefinitions ): DefDef = {
245+ implicit ctx : Context ): DefDef = {
246+
247+ val junitdefn = jsdefn.junit
285248
286- val sym = ctx.newSymbol(owner, Names .invokeTest, Synthetic | Method ,
287- MethodType (List (Names .instance, Names .name), List (defn.ObjectType , defn.StringType ), mydefn .FutureType )).entered
249+ val sym = ctx.newSymbol(owner, junitNme .invokeTest, Synthetic | Method ,
250+ MethodType (List (junitNme .instance, junitNme .name), List (defn.ObjectType , defn.StringType ), junitdefn .FutureType )).entered
288251
289252 DefDef (sym, { (paramRefss : List [List [Tree ]]) =>
290253 val List (List (instanceParamRef, nameParamRef)) = paramRefss
291- val castInstanceSym = ctx.newSymbol(sym, Names .castInstance, Synthetic , testClass.typeRef, coord = owner.span)
254+ val castInstanceSym = ctx.newSymbol(sym, junitNme .castInstance, Synthetic , testClass.typeRef, coord = owner.span)
292255 Block (
293256 ValDef (castInstanceSym, instanceParamRef.cast(testClass.typeRef)) :: Nil ,
294257 tests.foldRight[Tree ] {
295- val tp = mydefn .NoSuchMethodExceptionType
258+ val tp = junitdefn .NoSuchMethodExceptionType
296259 val constr = tp.member(nme.CONSTRUCTOR ).suchThat { c =>
297260 c.info.paramInfoss.head.size == 1 &&
298261 c.info.paramInfoss.head.head.isRef(defn.StringClass )
@@ -308,16 +271,18 @@ class JUnitBootstrappers extends MiniPhase {
308271 }
309272
310273 private def genTestInvocation (testClass : ClassSymbol , testMethod : Symbol , instance : Tree )(
311- implicit ctx : Context , mydefn : MyDefinitions ): Tree = {
274+ implicit ctx : Context ): Tree = {
275+
276+ val junitdefn = jsdefn.junit
312277
313278 val resultType = testMethod.info.resultType
314279 if (resultType.isRef(defn.UnitClass )) {
315- val newSuccess = ref(mydefn .SuccessModule_apply ).appliedTo(ref(defn.BoxedUnit_UNIT ))
280+ val newSuccess = ref(junitdefn .SuccessModule_apply ).appliedTo(ref(defn.BoxedUnit_UNIT ))
316281 Block (
317282 instance.select(testMethod).appliedToNone :: Nil ,
318- ref(mydefn .FutureModule_successful ).appliedTo(newSuccess)
283+ ref(junitdefn .FutureModule_successful ).appliedTo(newSuccess)
319284 )
320- } else if (resultType.isRef(mydefn .FutureClass )) {
285+ } else if (resultType.isRef(junitdefn .FutureClass )) {
321286 instance.select(testMethod).appliedToNone
322287 } else {
323288 // We lie in the error message to not expose that we support async testing.
@@ -327,7 +292,7 @@ class JUnitBootstrappers extends MiniPhase {
327292 }
328293
329294 private def genNewInstance (owner : ClassSymbol , testClass : ClassSymbol )(implicit ctx : Context ): DefDef = {
330- val sym = ctx.newSymbol(owner, Names .newInstance, Synthetic | Method ,
295+ val sym = ctx.newSymbol(owner, junitNme .newInstance, Synthetic | Method ,
331296 MethodType (Nil , defn.ObjectType )).entered
332297
333298 DefDef (sym, New (testClass.typeRef, Nil ))
@@ -339,3 +304,21 @@ class JUnitBootstrappers extends MiniPhase {
339304 private def annotatedMethods (owner : ClassSymbol , annot : Symbol )(implicit ctx : Context ): List [Symbol ] =
340305 owner.info.decls.filter(m => m.is(Method ) && m.hasAnnotation(annot))
341306}
307+
308+ object JUnitBootstrappers {
309+
310+ private object junitNme {
311+ val beforeClass : TermName = termName(" beforeClass" )
312+ val afterClass : TermName = termName(" afterClass" )
313+ val before : TermName = termName(" before" )
314+ val after : TermName = termName(" after" )
315+ val tests : TermName = termName(" tests" )
316+ val invokeTest : TermName = termName(" invokeTest" )
317+ val newInstance : TermName = termName(" newInstance" )
318+
319+ val instance : TermName = termName(" instance" )
320+ val name : TermName = termName(" name" )
321+ val castInstance : TermName = termName(" castInstance" )
322+ }
323+
324+ }
0 commit comments