diff options
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.scala | 244 |
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) - - } - -} |