Skip to content

Commit 227cd73

Browse files
authored
Merge pull request #2557 from dotty-staging/fix-junit4
Fix #2556, make JUnit4 work in dotty compiled classes.
2 parents 4e1c918 + 85b0c0f commit 227cd73

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

compiler/src/dotty/tools/dotc/transform/MixinOps.scala

+10-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@ import Symbols._, Types._, Contexts._, SymDenotations._, DenotTransformers._, Fl
66
import util.Positions._
77
import SymUtils._
88
import StdNames._, NameOps._
9+
import Decorators._
910

1011
class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: Context) {
1112
import ast.tpd._
1213

1314
val superCls: Symbol = cls.superClass
1415
val mixins: List[ClassSymbol] = cls.mixins
1516

17+
lazy val JUnit4Annotations: List[Symbol] = List("Test", "Ignore", "Before", "After", "BeforeClass", "AfterClass").
18+
map(n => ctx.getClassIfDefined("org.junit." + n)).
19+
filter(_.exists)
20+
1621
def implementation(member: TermSymbol): TermSymbol = {
1722
val res = member.copy(
1823
owner = cls,
@@ -59,10 +64,14 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
5964
def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available
6065
def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class
6166
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
62-
(meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition ) &&
67+
(meth.owner.is(Scala2x) || needsDisambiguation || hasNonInterfaceDefinition || needsJUnit4Fix(meth) ) &&
6368
isCurrent(meth)
6469
}
6570

71+
private def needsJUnit4Fix(meth: Symbol): Boolean = {
72+
meth.annotations.nonEmpty && JUnit4Annotations.exists(annot => meth.hasAnnotation(annot))
73+
}
74+
6675
/** Get `sym` of the method that needs a forwarder
6776
* Method needs a forwarder in those cases:
6877
* - there is a trait that defines a primitive version of implemented polymorphic method.

tests/run/junitForwarders/C_1.scala

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait T {
2+
@org.junit.Test def foo = 0
3+
}
4+
5+
class C extends T
6+
7+
object Test extends App {
8+
def check(c: Class[_], e: String) = {
9+
val s = c.getDeclaredMethods.sortBy(_.getName).map(m => s"${m.getName} - ${m.getDeclaredAnnotations.mkString(", ")}").mkString(";")
10+
assert(s == e, s"found: $s\nexpected: $e")
11+
}
12+
check(classOf[C], "foo - @org.junit.Test()")
13+
// TODO scala-dev#213: should `foo$` really carry the @Test annotation?
14+
check(classOf[T], "$init$ - ;foo - @org.junit.Test()")
15+
}

tests/run/junitForwarders/Test.java

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.junit;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target({ElementType.METHOD})
10+
public @interface Test { }

0 commit comments

Comments
 (0)