summaryrefslogtreecommitdiff
path: root/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala')
-rw-r--r--examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala244
1 files changed, 0 insertions, 244 deletions
diff --git a/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala b/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala
deleted file mode 100644
index 3621050..0000000
--- a/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/JSGlobalAddons.scala
+++ /dev/null
@@ -1,244 +0,0 @@
-/* Scala.js compiler
- * Copyright 2013 LAMP/EPFL
- * @author Sébastien Doeraene
- */
-
-package scala.scalajs.compiler
-
-import scala.tools.nsc._
-
-import scala.collection.mutable
-
-/** Additions to Global meaningful for the JavaScript backend
- *
- * @author Sébastien Doeraene
- */
-trait JSGlobalAddons extends JSDefinitions
- with Compat210Component {
- val global: Global
-
- import global._
- import jsDefinitions._
- import definitions._
-
- /** JavaScript primitives, used in jscode */
- object jsPrimitives extends JSPrimitives {
- val global: JSGlobalAddons.this.global.type = JSGlobalAddons.this.global
- val jsAddons: ThisJSGlobalAddons =
- JSGlobalAddons.this.asInstanceOf[ThisJSGlobalAddons]
- }
-
- /** global javascript interop related helpers */
- object jsInterop {
- import scala.reflect.NameTransformer
- import scala.reflect.internal.Flags
-
- private val exportPrefix = "$js$exported$"
- private val methodExportPrefix = exportPrefix + "meth$"
- private val propExportPrefix = exportPrefix + "prop$"
-
- case class ExportInfo(jsName: String, pos: Position, isNamed: Boolean)
-
- /** retrieves the names a sym should be exported to from its annotations
- *
- * Note that for accessor symbols, the annotations of the accessed symbol
- * are used, rather than the annotations of the accessor itself.
- */
- def exportsOf(sym: Symbol): List[ExportInfo] = {
- val exports = directExportsOf(sym) ++ inheritedExportsOf(sym)
-
- // Calculate the distinct exports for this symbol (eliminate double
- // occurrences of (name, isNamed) pairs).
- val buf = new mutable.ListBuffer[ExportInfo]
- val seen = new mutable.HashSet[(String, Boolean)]
- for (exp <- exports) {
- if (!seen.contains((exp.jsName, exp.isNamed))) {
- buf += exp
- seen += ((exp.jsName, exp.isNamed))
- }
- }
-
- buf.toList
- }
-
- private def directExportsOf(sym: Symbol): List[ExportInfo] = {
- val trgSym = {
- // For accessors, look on the val/var def
- if (sym.isAccessor) sym.accessed
- // For primary class constructors, look on the class itself
- else if (sym.isPrimaryConstructor && !sym.owner.isModuleClass) sym.owner
- else sym
- }
-
- // Annotations that are directly on the member
- val directAnnots = for {
- annot <- trgSym.annotations
- if annot.symbol == JSExportAnnotation ||
- annot.symbol == JSExportNamedAnnotation
- } yield annot
-
- // Annotations for this member on the whole unit
- val unitAnnots = {
- if (sym.isMethod && sym.isPublic &&
- !sym.isConstructor && !sym.isSynthetic)
- sym.owner.annotations.filter(_.symbol == JSExportAllAnnotation)
- else
- Nil
- }
-
- for {
- annot <- directAnnots ++ unitAnnots
- } yield {
- // Is this a named export or a normal one?
- val named = annot.symbol == JSExportNamedAnnotation
-
- def explicitName = annot.stringArg(0).getOrElse {
- reporter.error(annot.pos,
- s"The argument to ${annot.symbol.name} must be a literal string")
- "dummy"
- }
-
- val name =
- if (annot.args.nonEmpty) explicitName
- else if (sym.isConstructor) decodedFullName(sym.owner)
- else if (sym.isModuleClass) decodedFullName(sym)
- else sym.unexpandedName.decoded.stripSuffix("_=")
-
- // Enforce that methods ending with _= are exported as setters
- if (sym.isMethod && !sym.isConstructor &&
- sym.name.decoded.endsWith("_=") && !isJSSetter(sym)) {
- reporter.error(annot.pos, "A method ending in _= will be exported " +
- s"as setter. But ${sym.name.decoded} does not have the right " +
- "signature to do so (single argument, unit return type).")
- }
-
- // Enforce no __ in name
- if (name.contains("__")) {
- // Get position for error message
- val pos = if (annot.stringArg(0).isDefined)
- annot.args.head.pos
- else trgSym.pos
-
- reporter.error(pos,
- "An exported name may not contain a double underscore (`__`)")
- }
-
- // Make sure we do not override the default export of toString
- if (!sym.isConstructor && name == "toString" && !named &&
- sym.name != nme.toString_ && sym.tpe.params.isEmpty &&
- !isJSGetter(sym)) {
- reporter.error(annot.pos, "You may not export a zero-argument " +
- "method named other than 'toString' under the name 'toString'")
- }
-
- if (named && isJSProperty(sym)) {
- reporter.error(annot.pos,
- "You may not export a getter or a setter as a named export")
- }
-
- ExportInfo(name, annot.pos, named)
- }
- }
-
- private def inheritedExportsOf(sym: Symbol): List[ExportInfo] = {
- // The symbol from which we (potentially) inherit exports. It also
- // gives the exports their name
- val trgSym = {
- if (sym.isModuleClass)
- sym
- else if (sym.isConstructor && sym.isPublic &&
- sym.owner.isConcreteClass && !sym.owner.isModuleClass)
- sym.owner
- else NoSymbol
- }
-
- if (trgSym == NoSymbol) {
- Nil
- } else {
- val trgAnnot =
- if (sym.isModuleClass) JSExportDescendentObjectsAnnotation
- else JSExportDescendentClassesAnnotation
-
- val forcingSym =
- trgSym.ancestors.find(_.annotations.exists(_.symbol == trgAnnot))
-
- val name = decodedFullName(trgSym)
-
- forcingSym.map { fs =>
- // Enfore no __ in name
- if (name.contains("__")) {
- // Get all annotation positions for error message
- reporter.error(sym.pos,
- s"""${trgSym.name} may not have a double underscore (`__`) in its fully qualified
- |name, since it is forced to be exported by a @${trgAnnot.name} on ${fs}""".stripMargin)
- }
-
- ExportInfo(name, sym.pos, false)
- }.toList
- }
- }
-
- /** Just like sym.fullName, but does not encode components */
- private def decodedFullName(sym: Symbol): String = {
- if (sym.isRoot || sym.isRootPackage || sym == NoSymbol) sym.name.decoded
- else if (sym.owner.isEffectiveRoot) sym.name.decoded
- else decodedFullName(sym.effectiveOwner.enclClass) + '.' + sym.name.decoded
- }
-
- /** creates a name for an export specification */
- def scalaExportName(jsName: String, isProp: Boolean): TermName = {
- val pref = if (isProp) propExportPrefix else methodExportPrefix
- val encname = NameTransformer.encode(jsName)
- newTermName(pref + encname)
- }
-
- /** checks if the given symbol is a JSExport */
- def isExport(sym: Symbol): Boolean =
- sym.unexpandedName.startsWith(exportPrefix) &&
- !sym.hasFlag(Flags.DEFAULTPARAM)
-
- /** retrieves the originally assigned jsName of this export and whether it
- * is a property
- */
- def jsExportInfo(name: Name): (String, Boolean) = {
- def dropPrefix(prefix: String) ={
- if (name.startsWith(prefix)) {
- // We can't decode right away due to $ separators
- val enc = name.encoded.substring(prefix.length)
- Some(NameTransformer.decode(enc))
- } else None
- }
-
- dropPrefix(methodExportPrefix).map((_,false)) orElse
- dropPrefix(propExportPrefix).map((_,true)) getOrElse
- sys.error("non-exported name passed to jsInfoSpec")
- }
-
- def isJSProperty(sym: Symbol): Boolean = isJSGetter(sym) || isJSSetter(sym)
-
- /** has this symbol to be translated into a JS getter (both directions)? */
- def isJSGetter(sym: Symbol): Boolean = {
- sym.tpe.params.isEmpty && enteringPhase(currentRun.uncurryPhase) {
- sym.tpe.isInstanceOf[NullaryMethodType]
- }
- }
-
- /** has this symbol to be translated into a JS setter (both directions)? */
- def isJSSetter(sym: Symbol) = {
- sym.unexpandedName.decoded.endsWith("_=") &&
- sym.tpe.resultType.typeSymbol == UnitClass &&
- enteringPhase(currentRun.uncurryPhase) {
- sym.tpe.paramss match {
- case List(List(arg)) => !isScalaRepeatedParamType(arg.tpe)
- case _ => false
- }
- }
- }
-
- /** has this symbol to be translated into a JS bracket access (JS to Scala) */
- def isJSBracketAccess(sym: Symbol) =
- sym.hasAnnotation(JSBracketAccessAnnotation)
-
- }
-
-}