plugins.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 191 行

SCALA
191
字号
/* NSC -- new Scala compiler * Copyright 2007-2008 LAMP/EPFL * @author Lex Spoon */// $Id: Plugins.scala 14416 2008-03-19 01:17:25Z mihaylov $package scala.tools.nsc.pluginsimport java.io.File/** Support for run-time loading of compiler plugins. * *  @author Lex Spoon *  @version 1.0, 2007-5-21 */trait Plugins { self: Global =>  /** Load a rough list of the plugins.  For speed, it   *  does not instantiate a compiler run.  Therefore it cannot   *  test for same-named phases or other problems that are   *  filtered from the final list of plugins. */  protected def loadRoughPluginsList(): List[Plugin] = {    val jars = settings.plugin.value.map(new File(_))    val dirs =      for (name <- settings.pluginsDir.value.split(File.pathSeparator).toList)	yield new File(name)    for (plugClass <- Plugin.loadAllFrom(jars, dirs, settings.disable.value))    yield Plugin.instantiate(plugClass, this)  }  private var roughPluginsListCache: Option[List[Plugin]] = None  protected def roughPluginsList: List[Plugin] =    roughPluginsListCache match {      case Some(list) => list      case None =>	roughPluginsListCache = Some(loadRoughPluginsList)        roughPluginsListCache.get    }  /** Load all available plugins.  Skips plugins that   *  either have the same name as another one, or which   *  define a phase name that another one does.   */  protected def loadPlugins(): List[Plugin] = {    // remove any with conflicting names or subcomponent names    def pick(      plugins: List[Plugin],       plugNames: Set[String],       phaseNames: Set[String]): List[Plugin] =    {      plugins match {	case Nil => Nil	case plug :: rest =>	  val plugPhaseNames = Set.empty ++ plug.components.map(_.phaseName)	  def withoutPlug = pick(rest, plugNames, plugPhaseNames)	  def withPlug =	    (plug :: 	     pick(rest, 		  plugNames+plug.name,		  phaseNames++plugPhaseNames))	  if (plugNames.contains(plug.name)) {	    if (settings.verbose.value)	      inform("[skipping a repeated plugin: " + plug.name + "]")	    withoutPlug	  } else if (settings.disable.value contains(plug.name)) {	    if (settings.verbose.value)	      inform("[disabling plugin: " + plug.name + "]")	    withoutPlug	  } else {	    val commonPhases = phaseNames.intersect(plugPhaseNames)	    if (!commonPhases.isEmpty) {	      if (settings.verbose.value)		inform("[skipping plugin " + plug.name +		       "because it repeats phase names: " +		       commonPhases.mkString(", ") + "]")	      withoutPlug	    } else {	      if (settings.verbose.value)		inform("[loaded plugin " + plug.name + "]")	      withPlug	    }	  }      }    }    val plugs =    pick(roughPluginsList,	 Set.empty,	 Set.empty ++ builtInPhaseDescriptors.map(_.phaseName))    for (req <- settings.require.value; if !plugs.exists(p => p.name==req))      error("Missing required plugin: " + req)        for (plug <- plugs) {      val nameColon = plug.name + ":"      val opts = for {	raw <- settings.pluginOptions.value	if raw.startsWith(nameColon)      } yield raw.substring(nameColon.length)      if (!opts.isEmpty)	plug.processOptions(opts, error)    }    for {      opt <- settings.pluginOptions.value      if !plugs.exists(p => opt.startsWith(p.name + ":"))    } error("bad option: -P:" + opt)    plugs  }  private var pluginsCache: Option[List[Plugin]] = None  def plugins: List[Plugin] = {    if (pluginsCache.isEmpty)      pluginsCache = Some(loadPlugins)    pluginsCache.get  }  /** A description of all the plugins that are loaded */  def pluginDescriptions: String = {    val messages =      for (plugin <- roughPluginsList)	yield plugin.name + " - " + plugin.description    messages.mkString("\n")  }  /** Compute a full list of phase descriptors, including   *  both built-in phases and those coming from plugins. */  protected def computePhaseDescriptors: List[SubComponent] = {    def insert(descs: List[SubComponent], component: PluginComponent)    :List[SubComponent] =    {      descs match {	case Nil => assert(false); Nil        case hd::rest if "parser" == component.runsAfter =>          component :: hd :: rest	case hd::rest if hd.phaseName == component.runsAfter =>	  hd :: component :: rest	case hd :: rest =>	  hd :: (insert(rest, component))      }    }    var descriptors = builtInPhaseDescriptors    var plugsLeft = plugins.flatMap(_.components)    // Insert all the plugins, one by one.  Note that    // plugins are allowed to depend on each other, thus    // complicating the algorithm.	      while (!plugsLeft.isEmpty) {      val nextPlug = plugsLeft.find(plug =>        plug.runsAfter == "parser" ||         descriptors.exists(d => d.phaseName == plug.runsAfter))      nextPlug match {	case None =>	  error("Failed to load some plugin phases:")	  for (plug <- plugsLeft)	    error (plug.phaseName + " depends on " + plug.runsAfter)	  return descriptors	case Some(nextPlug) =>	  descriptors = insert(descriptors, nextPlug)          plugsLeft = plugsLeft.filter(p => !(p eq nextPlug))      }    }    descriptors  }  /** Summary of the options for all loaded plugins */  def pluginOptionsHelp: String = {    val buf = new StringBuffer    for (plug <- roughPluginsList; help <- plug.optionsHelp) {      buf append ("Options for plugin " + plug.name + ":\n")      buf append help      buf append "\n"    }    buf.toString  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?