summaryrefslogtreecommitdiff
path: root/test/junit/scala/tools/nsc/symtab/FlagsTest.scala
blob: 4e78ca7f228da36e752a48e30adfd7c9a72a042a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package scala.tools.nsc
package symtab

import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

import scala.tools.testing.BytecodeTesting

@RunWith(classOf[JUnit4])
class FlagsTest extends BytecodeTesting {
  object symbolTable extends SymbolTableForUnitTesting
  import symbolTable._

  import Flags._

  def sym = NoSymbol.newTermSymbol(nme.EMPTY)

  def withFlagMask[A](mask: Long)(body: => A): A = enteringPhase(new Phase(NoPhase) {
    override def flagMask = mask
    def name = ""
    def run() = ()
  })(body)

  def testTimedFlag(flag: Long, test: Symbol => Boolean, enabling: Boolean) = {
    assertEquals(withFlagMask(InitialFlags)(test(sym.setFlag(flag))), !enabling)
    assertEquals(withFlagMask(InitialFlags | flag)(test(sym.setFlag(flag))), enabling)
  }

  def testLate(flag: Long, test: Symbol => Boolean) = testTimedFlag(flag, test, enabling = true)
  def testNot(flag: Long, test: Symbol => Boolean) = testTimedFlag(flag, test, enabling = false)

  @Test
  def testTimedFlags(): Unit = {
    testNot(PROTECTED | notPROTECTED, _.isProtected)
    testNot(PRIVATE | notPRIVATE, _.isPrivate)

    assertFalse(withFlagMask(AllFlags)(sym.setFlag(PRIVATE | notPRIVATE).isPrivate))

    assertEquals(withFlagMask(InitialFlags)(sym.setFlag(PRIVATE | notPRIVATE).flags & PRIVATE), PRIVATE)
    assertEquals(withFlagMask(AllFlags)(sym.setFlag(PRIVATE | notPRIVATE).flags & PRIVATE), 0)
  }

  @Test
  def normalLateOverlap(): Unit = {
    // late flags are shifted by LateShift == 47.
    // however, the first late flag is lateDEFERRED, which is DEFERRED << 47 == (1 << 4) << 47 == 1 << 51
    // the flags from 1 << 47 to 1 << 50 are not late flags. this is ensured by the LateFlags mask.

    for (i <- 0 to 3) {
      val f = 1L << i
      assertEquals(withFlagMask(AllFlags)(sym.setFlag(f << LateShift).flags & f), 0) // not treated as late flag
    }
    for (i <- 4 to 8) {
      val f = 1L << i
      assertEquals(withFlagMask(AllFlags)(sym.setFlag(f << LateShift).flags & f), f) // treated as late flag
    }
  }

  @Test
  def normalAnti(): Unit = {
    for (i <- 0 to 2) {
      val f = 1L << i
      assertEquals(withFlagMask(AllFlags)(sym.setFlag(f | (f << AntiShift)).flags & f), 0) // negated flags
    }
    for (i <- 3 to 7) {
      val f = 1L << i
      assertEquals(withFlagMask(AllFlags)(sym.setFlag(f | (f << AntiShift)).flags & f), f) // not negated
    }
  }

  @Test
  def lateAntiCrossCheck(): Unit = {
    val allButNegatable = AllFlags & ~(PROTECTED | OVERRIDE | PRIVATE)
    val lateable        = 0L | DEFERRED | FINAL | INTERFACE | METHOD | MODULE
    val lateFlags       = lateable << LateShift
    val allButLateable  = AllFlags & ~lateable

    assertEquals(withFlagMask(AllFlags)(sym.setFlag(AllFlags).flags), allButNegatable)
    assertEquals(withFlagMask(AllFlags)(sym.setFlag(allButLateable).flags), allButNegatable)

    assertEquals(withFlagMask(AllFlags)(sym.setFlag(lateFlags).flags), lateFlags | lateable)
  }

  @Test
  def javaClassMirrorAnnotationFlag(): Unit = {
    import scala.reflect.runtime.universe._
    val dep = typeOf[java.lang.Deprecated].typeSymbol
    assertTrue(dep.isJavaAnnotation && dep.isJava)
  }

  @Test
  def interfaceFlag(): Unit = {
    // scala traits are `isInterface` if they have only type defs and abstract methods / fields.
    // java interfaces are always `isInterface`.
    val scalaCode =
      """package p
        |trait T1 {
        |  import scala.collection
        |  def m: Int
        |  val f: Int
        |  type T <: AnyRef
        |}
        |trait T2 {
        |  def m = 1
        |}
        |trait T3 {
        |  val f = 1
        |}
        |trait T4 {
        |  println()
        |}
      """.stripMargin
    val javaI1 = "package p; interface I1 { int m(); }"
    val javaI2 = "package p; interface I2 { default int m() { return 1; } }"
    compiler.compileClasses(code = scalaCode, javaCode = (javaI1, "I1.java") :: (javaI2, "I2.java") :: Nil)
    import compiler.global.rootMirror._
    assert( getRequiredClass("p.T1").isInterface)
    assert(!getRequiredClass("p.T2").isInterface)
    assert(!getRequiredClass("p.T3").isInterface)
    assert(!getRequiredClass("p.T4").isInterface)
    assert( getRequiredClass("p.I1").isInterface)
    assert( getRequiredClass("p.I2").isInterface)
  }
}