@@ -106,71 +106,23 @@ import dotty.tools.dotc.transform.MegaPhase._
106
106
* some point in the future.
107
107
*/
108
108
class JUnitBootstrappers extends MiniPhase {
109
+ import JUnitBootstrappers ._
109
110
import ast .tpd ._
111
+ import JSDefinitions .jsdefn
110
112
111
113
def phaseName : String = " junitBootstrappers"
112
114
113
115
override def isEnabled (implicit ctx : Context ): Boolean =
114
116
super .isEnabled && ctx.settings.scalajs.value
115
117
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
-
165
118
// The actual transform -------------------------------
166
119
167
120
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
170
122
171
123
@ tailrec
172
124
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 )) ||
174
126
sym.superClass.exists && hasTests(sym.superClass.asClass)
175
127
}
176
128
@@ -190,32 +142,39 @@ class JUnitBootstrappers extends MiniPhase {
190
142
}
191
143
192
144
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
194
155
195
156
val owner = testClass.owner
196
- val moduleSym = ctx.newCompleteModuleSymbol(owner,
197
- (testClass.name ++ " $scalajs$junit$bootstrapper" ).toTermName,
157
+ val moduleSym = ctx.newCompleteModuleSymbol(owner, bootstrapperName,
198
158
Synthetic , Synthetic ,
199
- List (defn.ObjectType , mydefn .BootstrapperType ), newScope,
159
+ List (defn.ObjectType , junitdefn .BootstrapperType ), newScope,
200
160
coord = testClass.span, assocFile = testClass.assocFile).entered
201
161
val classSym = moduleSym.moduleClass.asClass
202
162
203
163
val constr = genConstructor(classSym)
204
164
205
- val testMethods = annotatedMethods(testClass, mydefn .TestAnnotClass )
165
+ val testMethods = annotatedMethods(testClass, junitdefn .TestAnnotClass )
206
166
207
167
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 ),
212
172
genTests(classSym, testMethods),
213
173
genInvokeTest(classSym, testClass, testMethods),
214
174
genNewInstance(classSym, testClass)
215
175
)
216
176
217
- if (ctx.sbtCallback != null )
218
- sbt.APIUtils .registerDummyClass(classSym)
177
+ sbt.APIUtils .registerDummyClass(classSym)
219
178
220
179
ClassDef (classSym, constr, defs)
221
180
}
@@ -247,7 +206,7 @@ class JUnitBootstrappers extends MiniPhase {
247
206
248
207
private def genCallOnParam (owner : ClassSymbol , name : TermName , testClass : ClassSymbol , annot : Symbol )(implicit ctx : Context ): DefDef = {
249
208
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
251
210
252
211
DefDef (sym, { (paramRefss : List [List [Tree ]]) =>
253
212
val List (List (instanceParamRef)) = paramRefss
@@ -258,41 +217,45 @@ class JUnitBootstrappers extends MiniPhase {
258
217
}
259
218
260
219
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
262
223
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
265
226
266
227
DefDef (sym, {
267
228
val metadata = for (test <- tests) yield {
268
229
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 )))
270
231
// TODO Handle @Test annotations with arguments
271
232
// 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
273
234
if (testAnnot.arguments.nonEmpty)
274
235
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))
278
239
}
279
- JavaSeqLiteral (metadata, TypeTree (mydefn .TestMetadataType ))
240
+ JavaSeqLiteral (metadata, TypeTree (junitdefn .TestMetadataType ))
280
241
})
281
242
}
282
243
283
244
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
285
248
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
288
251
289
252
DefDef (sym, { (paramRefss : List [List [Tree ]]) =>
290
253
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)
292
255
Block (
293
256
ValDef (castInstanceSym, instanceParamRef.cast(testClass.typeRef)) :: Nil ,
294
257
tests.foldRight[Tree ] {
295
- val tp = mydefn .NoSuchMethodExceptionType
258
+ val tp = junitdefn .NoSuchMethodExceptionType
296
259
val constr = tp.member(nme.CONSTRUCTOR ).suchThat { c =>
297
260
c.info.paramInfoss.head.size == 1 &&
298
261
c.info.paramInfoss.head.head.isRef(defn.StringClass )
@@ -308,16 +271,18 @@ class JUnitBootstrappers extends MiniPhase {
308
271
}
309
272
310
273
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
312
277
313
278
val resultType = testMethod.info.resultType
314
279
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 ))
316
281
Block (
317
282
instance.select(testMethod).appliedToNone :: Nil ,
318
- ref(mydefn .FutureModule_successful ).appliedTo(newSuccess)
283
+ ref(junitdefn .FutureModule_successful ).appliedTo(newSuccess)
319
284
)
320
- } else if (resultType.isRef(mydefn .FutureClass )) {
285
+ } else if (resultType.isRef(junitdefn .FutureClass )) {
321
286
instance.select(testMethod).appliedToNone
322
287
} else {
323
288
// We lie in the error message to not expose that we support async testing.
@@ -327,7 +292,7 @@ class JUnitBootstrappers extends MiniPhase {
327
292
}
328
293
329
294
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 ,
331
296
MethodType (Nil , defn.ObjectType )).entered
332
297
333
298
DefDef (sym, New (testClass.typeRef, Nil ))
@@ -339,3 +304,21 @@ class JUnitBootstrappers extends MiniPhase {
339
304
private def annotatedMethods (owner : ClassSymbol , annot : Symbol )(implicit ctx : Context ): List [Symbol ] =
340
305
owner.info.decls.filter(m => m.is(Method ) && m.hasAnnotation(annot))
341
306
}
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