summaryrefslogblamecommitdiff
path: root/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/JSInteropTest.scala
blob: 99c274fda6a3ad0267ca60762c75a59349e86933 (plain) (tree)





























































































































































































































































































































































                                                                                                                                                                       
package scala.scalajs.compiler.test

import scala.scalajs.compiler.test.util._

import org.junit.Test
import org.junit.Ignore

class JSInteropTest extends DirectTest with TestHelpers {

  override def preamble =
    """import scala.scalajs.js
    """

  @Test
  def noInnerClassTraitObject: Unit = {

    val objs = List("class", "trait", "object")

    for {
      outer <- objs
      inner <- objs
    } yield {
      s"""
      $outer A extends js.Object {
        $inner A
      }
      """ hasErrors
      s"""
        |newSource1.scala:4: error: Traits, classes and objects extending js.Any may not have inner traits, classes or objects
        |        $inner A
        |         ${" " * inner.length}^
      """
    }

  }

  @Test
  def noBadSetters = {

    """
    class A extends js.Object {
      def foo_=(x: Int): Int = js.native
    }
    """ hasErrors
    """
      |newSource1.scala:4: error: Setters that do not return Unit are not allowed in types extending js.Any
      |      def foo_=(x: Int): Int = js.native
      |          ^
    """

  }

  @Test
  def onlyJSRawTraits = {

    """
    trait A
    class B extends js.Object with A
    """ hasErrors
    """
      |newSource1.scala:4: error: B extends A which does not extend js.Any.
      |    class B extends js.Object with A
      |          ^
    """

    """
    trait A
    class B extends js.Object with Serializable
    """ hasErrors
    """
      |newSource1.scala:4: error: B extends scala.Serializable which does not extend js.Any.
      |    class B extends js.Object with Serializable
      |          ^
    """

  }

  @Test
  def noAnonymousClass = {

    """
    class A {
      val x = new js.Object {
        def a: Int = js.native
      }
    }
    """ hasErrors
    """
      |newSource1.scala:4: error: Anonymous classes may not extend js.Any
      |      val x = new js.Object {
      |                  ^
    """

  }

  @Test
  def noCaseClassObject = {

    """
    case class A(x: Int) extends js.Object
    """ hasErrors
    """
      |newSource1.scala:3: error: Classes and objects extending js.Any may not have a case modifier
      |    case class A(x: Int) extends js.Object
      |               ^
    """

    """
    case object B extends js.Object
    """ hasErrors
    """
      |newSource1.scala:3: error: Classes and objects extending js.Any may not have a case modifier
      |    case object B extends js.Object
      |                ^
    """

  }

  @Test
  def notNested: Unit = {

    val outers = List("class", "trait")
    val inners = List("trait", "class", "object")

    for {
      outer <- outers
      inner <- inners
    } yield {

      val errTrg = if (inner == "object") "Objects" else "Classes"

      s"""
      $outer A {
        $inner Inner extends js.Object
      }
      """ hasErrors
      s"""
        |newSource1.scala:4: error: $errTrg extending js.Any may not be defined inside a class or trait
        |        $inner Inner extends js.Object
        |         ${" " * inner.length}^
      """
    }

  }

  @Test
  def noGlobalScopeClass = {

    """
    class A extends js.GlobalScope
    """ hasErrors
    """
      |newSource1.scala:3: error: Only objects may extend js.GlobalScope
      |    class A extends js.GlobalScope
      |          ^
    """

    """
    trait A extends js.GlobalScope
    """ hasErrors
    """
      |newSource1.scala:3: error: Only objects may extend js.GlobalScope
      |    trait A extends js.GlobalScope
      |          ^
    """

  }

  @Test
  def noLocalClass = {

    """
    object A {
      def a = {
        class B extends js.Object
      }
    }
    """ hasErrors
    """
      |newSource1.scala:5: error: Local classes and objects may not extend js.Any
      |        class B extends js.Object
      |              ^
    """

  }

  @Test
  def noLocalObject = {

    """
    object A {
      def a = {
        object B extends js.Object
      }
    }
    """ hasErrors
    """
      |newSource1.scala:5: error: Local classes and objects may not extend js.Any
      |        object B extends js.Object
      |               ^
    """

  }

  @Test
  def noExtendJSAny = {

    """
    class A extends js.Any
    """ hasErrors
    """
      |newSource1.scala:3: error: illegal inheritance from sealed trait Any
      |    class A extends js.Any
      |                       ^
    """

  }

  @Test
  def noNativeInJSAny = {

    """
    class A extends js.Object {
      @native
      def value: Int = js.native
    }
    """ hasErrors
    """
      |newSource1.scala:5: error: Methods in a js.Any may not be @native
      |      def value: Int = js.native
      |          ^
    """

  }

  @Test
  def warnJSAnyBody = {

    """
    class A extends js.Object {
      def value: Int = ???
      val x: Int = ???
    }
    """ hasWarns
    """
      |newSource1.scala:4: warning: Members of traits, classes and objects extending js.Any may only contain members that call js.native. This will be enforced in 1.0.
      |      def value: Int = ???
      |                       ^
      |newSource1.scala:5: warning: Members of traits, classes and objects extending js.Any may only contain members that call js.native. This will be enforced in 1.0.
      |      val x: Int = ???
      |                   ^
    """

    """
    trait A extends js.Object {
      def value: Int
      val x: Int
    }
    """ hasWarns
    """
      |newSource1.scala:4: warning: Members of traits, classes and objects extending js.Any may only contain members that call js.native. This will be enforced in 1.0.
      |      def value: Int
      |          ^
      |newSource1.scala:5: warning: Members of traits, classes and objects extending js.Any may only contain members that call js.native. This will be enforced in 1.0.
      |      val x: Int
      |          ^
    """

  }

  @Test
  def noCallSecondaryCtor = {

    """
    class A(x: Int, y: Int) extends js.Object {
      def this(x: Int) = this(x, 5)
      def this() = this(7)
    }
    """ hasErrors
    """
      |newSource1.scala:5: error: A secondary constructor of a class extending js.Any may only call the primary constructor
      |      def this() = this(7)
      |          ^
    """

  }

  @Test
  def noUseJsNative = {

    """
    class A {
      def foo = js.native
    }
    """ hasErrors
    """
      |newSource1.scala:4: error: js.native may only be used as stub implementation in facade types
      |      def foo = js.native
      |                   ^
    """

  }

  @Test
  def warnNothingRaw = {

    """
    class A extends js.Object {
      def foo = js.native
      val bar = js.native
    }
    """ hasWarns
    """
      |newSource1.scala:4: warning: The type of foo got inferred as Nothing. To suppress this warning, explicitly ascribe the type.
      |      def foo = js.native
      |          ^
      |newSource1.scala:5: warning: The type of bar got inferred as Nothing. To suppress this warning, explicitly ascribe the type.
      |      val bar = js.native
      |          ^
    """

  }

  @Test
  def noNonLiteralJSName = {

    """
    import js.annotation.JSName

    object A {
      val a = "Hello"
      final val b = "World"
    }

    class B extends js.Object {
      @JSName(A.a)
      def foo: Int = js.native
      @JSName(A.b)
      def bar: Int = js.native
    }
    """ hasErrors
    """
      |newSource1.scala:11: error: The argument to JSName must be a literal string
      |      @JSName(A.a)
      |       ^
    """

  }

}