summaryrefslogtreecommitdiff
path: root/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala')
-rw-r--r--examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala143
1 files changed, 143 insertions, 0 deletions
diff --git a/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala b/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala
new file mode 100644
index 0000000..c3916ab
--- /dev/null
+++ b/examples/scala-js/compiler/src/main/scala/scala/scalajs/compiler/ScalaJSPlugin.scala
@@ -0,0 +1,143 @@
+/* Scala.js compiler
+ * Copyright 2013 LAMP/EPFL
+ * @author Sébastien Doeraene
+ */
+
+package scala.scalajs.compiler
+
+import scala.tools.nsc._
+import scala.tools.nsc.plugins.{
+ Plugin => NscPlugin, PluginComponent => NscPluginComponent
+}
+import scala.collection.{ mutable, immutable }
+
+import java.net.{ URI, URISyntaxException }
+
+import scala.scalajs.ir.Trees
+
+/** Main entry point for the Scala.js compiler plugin
+ *
+ * @author Sébastien Doeraene
+ */
+class ScalaJSPlugin(val global: Global) extends NscPlugin {
+ import global._
+
+ val name = "scalajs"
+ val description = "Compile to JavaScript"
+ val components = {
+ if (global.forScaladoc)
+ List[NscPluginComponent](PrepInteropComponent)
+ else
+ List[NscPluginComponent](PrepInteropComponent, GenCodeComponent)
+ }
+
+ /** Called when the JS ASTs are generated. Override for testing */
+ def generatedJSAST(clDefs: List[Trees.Tree]): Unit = {}
+
+ /** Addons for JavaScript platform */
+ object jsAddons extends {
+ val global: ScalaJSPlugin.this.global.type = ScalaJSPlugin.this.global
+ } with JSGlobalAddons with Compat210Component
+
+ object scalaJSOpts extends ScalaJSOptions {
+ import ScalaJSOptions.URIMap
+ var fixClassOf: Boolean = false
+ lazy val sourceURIMaps: List[URIMap] = {
+ if (_sourceURIMaps.nonEmpty)
+ _sourceURIMaps.reverse
+ else
+ relSourceMap.toList.map(URIMap(_, absSourceMap))
+ }
+ var _sourceURIMaps: List[URIMap] = Nil
+ var relSourceMap: Option[URI] = None
+ var absSourceMap: Option[URI] = None
+ }
+
+ object PrepInteropComponent extends {
+ val global: ScalaJSPlugin.this.global.type = ScalaJSPlugin.this.global
+ val jsAddons: ScalaJSPlugin.this.jsAddons.type = ScalaJSPlugin.this.jsAddons
+ val scalaJSOpts = ScalaJSPlugin.this.scalaJSOpts
+ override val runsAfter = List("typer")
+ override val runsBefore = List("pickle")
+ } with PrepJSInterop
+
+ object GenCodeComponent extends {
+ val global: ScalaJSPlugin.this.global.type = ScalaJSPlugin.this.global
+ val jsAddons: ScalaJSPlugin.this.jsAddons.type = ScalaJSPlugin.this.jsAddons
+ val scalaJSOpts = ScalaJSPlugin.this.scalaJSOpts
+ override val runsAfter = List("mixin")
+ override val runsBefore = List("delambdafy", "cleanup", "terminal")
+ } with GenJSCode {
+ def generatedJSAST(clDefs: List[Trees.Tree]) =
+ ScalaJSPlugin.this.generatedJSAST(clDefs)
+ }
+
+ override def processOptions(options: List[String],
+ error: String => Unit): Unit = {
+ import ScalaJSOptions.URIMap
+ import scalaJSOpts._
+
+ for (option <- options) {
+ if (option == "fixClassOf") {
+ fixClassOf = true
+
+ } else if (option.startsWith("mapSourceURI:")) {
+ val uris = option.stripPrefix("mapSourceURI:").split("->")
+
+ if (uris.length != 1 && uris.length != 2) {
+ error("relocateSourceMap needs one or two URIs as argument.")
+ } else {
+ try {
+ val from = new URI(uris.head)
+ val to = uris.lift(1).map(str => new URI(str))
+ _sourceURIMaps ::= URIMap(from, to)
+ } catch {
+ case e: URISyntaxException =>
+ error(s"${e.getInput} is not a valid URI")
+ }
+ }
+
+ // The following options are deprecated (how do we show this to the user?)
+ } else if (option.startsWith("relSourceMap:")) {
+ val uriStr = option.stripPrefix("relSourceMap:")
+ try { relSourceMap = Some(new URI(uriStr)) }
+ catch {
+ case e: URISyntaxException => error(s"$uriStr is not a valid URI")
+ }
+ } else if (option.startsWith("absSourceMap:")) {
+ val uriStr = option.stripPrefix("absSourceMap:")
+ try { absSourceMap = Some(new URI(uriStr)) }
+ catch {
+ case e: URISyntaxException => error(s"$uriStr is not a valid URI")
+ }
+ } else {
+ error("Option not understood: " + option)
+ }
+ }
+
+ // Verify constraints
+ if (_sourceURIMaps.nonEmpty && relSourceMap.isDefined)
+ error("You may not use mapSourceURI and relSourceMap together. " +
+ "Use another mapSourceURI option without second URI.")
+ else if (_sourceURIMaps.nonEmpty && absSourceMap.isDefined)
+ error("You may not use mapSourceURI and absSourceMap together. " +
+ "Use another mapSourceURI option.")
+ else if (absSourceMap.isDefined && relSourceMap.isEmpty)
+ error("absSourceMap requires the use of relSourceMap")
+ }
+
+ override val optionsHelp: Option[String] = Some(s"""
+ | -P:$name:mapSourceURI:FROM_URI[->TO_URI]
+ | change the location the source URIs in the emitted IR point to
+ | - strips away the prefix FROM_URI (if it matches)
+ | - optionally prefixes the TO_URI, where stripping has been performed
+ | - any number of occurences are allowed. Processing is done on a first match basis.
+ | -P:$name:fixClassOf repair calls to Predef.classOf that reach ScalaJS
+ | WARNING: This is a tremendous hack! Expect ugly errors if you use this option.
+ |Deprecated options
+ | -P:$name:relSourceMap:<URI> relativize emitted source maps with <URI>
+ | -P:$name:absSourceMap:<URI> absolutize emitted source maps with <URI>
+ | This option requires the use of relSourceMap
+ """.stripMargin)
+
+}