All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.scalajs.macroimpls.JSMembers.scala Maven / Gradle / Ivy

The newest version!
/*                     __                                               *\
**     ________ ___   / /  ___      __ ____  Scala.js API               **
**    / __/ __// _ | / /  / _ | __ / // __/  (c) 2013-2015, LAMP/EPFL   **
**  __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \    http://scala-lang.org/     **
** /____/\___/_/ |_/____/_/ | |__/ /____/                               **
**                          |/____/                                     **
\*                                                                      */


package scala.scalajs.macroimpls

import Compat210._

/** JSMember is an ADT more or less equivalent to Scala's MethodType
 *  that allows to distinguish setters and getters from methods.
 *
 *  It also allows to check method conformance based on Scala.js' JavaScript
 *  calling conventions.
 *
 *  Currently does not support polymorphic method types.
 *
 *  @author Tobias Schlatter
 */
private[macroimpls] trait JSMembers {
  // Import macros only here, otherwise we collide with Compat210._
  import scala.reflect.macros._
  import blackbox.Context

  val c: Context

  import c.universe._

  sealed trait JSMember {
    /** Whether this JSMember conforms to that JSMember */
    def conformsTo(that: JSMember): Boolean

    /** Create a display string of this member with a given name */
    def displayStr(name: String): String
  }

  case class JSMethodParam(info: Type, isDefault: Boolean) {
    def conformsTo(that: JSMethodParam): Boolean =
      (!that.isDefault || this.isDefault) && that.info <:< this.info

    override def toString(): String =
      if (isDefault) s"$info = ???"
      else info.toString
  }

  case class JSMethod(params: List[JSMethodParam],
      resultType: Type) extends JSMember {

    def conformsTo(that: JSMember): Boolean = that match {
      case JSMethod(thatParams, thatResultType) =>
        val (used, unused) = params.splitAt(thatParams.size)

        params.size >= thatParams.size &&
        resultType <:< thatResultType &&
        unused.forall(_.isDefault) &&
        (used zip thatParams).forall { case (x, y) => x.conformsTo(y) }

      case _ =>
        false
    }

    def displayStr(name: String): String =
      s"method $name(${params.mkString(", ")}): $resultType"
  }

  case class JSGetter(tpe: Type) extends JSMember {
    def conformsTo(that: JSMember): Boolean = that match {
      case JSGetter(thatTpe) => tpe <:< thatTpe
      case _                 => false
    }

    def displayStr(name: String): String = s"getter $name: $tpe"
  }

  case class JSSetter(tpe: Type) extends JSMember {
    def conformsTo(that: JSMember): Boolean = that match {
      case JSSetter(thatTpe) => thatTpe <:< tpe
      case _                 => false
    }

    def displayStr(name: String): String = s"setter $name: $tpe"
  }

  /** Place holder for unsupported members.
   *
   *  In source type position, these members can be ignored.
   *  In target type position, these members will trigger errors.
   */
  case class UnsupportedMember(sym: Symbol, tpe: Type) extends JSMember {
    def conformsTo(that: JSMember): Boolean = false
    def displayStr(name: String): String = s"unsupported $name ($sym)"
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy