mirror of https://github.com/sbt/sbt.git
AutoPlugins appropriately participate in AddSettings.
* Add new AutoPlugins type to AddSettings.
* Ensure any Plugins filter doesn't just automatically always add
autoplugins every time.
* Load.scala can now adjust AutoPlugins ordering
Note: Adjusting autoplugin ordering is dangerous BUT doing a glob
of "put autoplugin settings here" is generally ok.
This commit is contained in:
parent
ac9391066b
commit
a44a14f2c8
|
|
@ -12,22 +12,23 @@ object AddSettings
|
|||
private[sbt] final class Sequence(val sequence: Seq[AddSettings]) extends AddSettings
|
||||
private[sbt] final object User extends AddSettings
|
||||
private[sbt] final class Plugins(val include: Plugin => Boolean) extends AddSettings
|
||||
private[sbt] final class AutoPlugins(val include: AutoPlugin => Boolean) extends AddSettings
|
||||
private[sbt] final class DefaultSbtFiles(val include: File => Boolean) extends AddSettings
|
||||
private[sbt] final class SbtFiles(val files: Seq[File]) extends AddSettings
|
||||
// Settings created with the Project().settings() commands in build.scala files.
|
||||
private[sbt] final object ProjectSettings extends AddSettings
|
||||
|
||||
/** Adds all settings from a plugin to a project. */
|
||||
val allPlugins: AddSettings = plugins(const(true))
|
||||
|
||||
/** Adds all settings from autoplugins. */
|
||||
val autoPlugins: AddSettings = plugins(_.isInstanceOf[AutoPlugin])
|
||||
val autoPlugins: AddSettings = new AutoPlugins(const(true))
|
||||
|
||||
/** Settings specified in Build.scala `Project` constructors. */
|
||||
val projectSettings: AddSettings = ProjectSettings
|
||||
|
||||
/** All plugins that aren't auto plugins. */
|
||||
val nonAutoPlugins: AddSettings = plugins(!_.isInstanceOf[AutoPlugin])
|
||||
val nonAutoPlugins: AddSettings = plugins(const(true))
|
||||
|
||||
/** Adds all settings from a plugin to a project. */
|
||||
val allPlugins: AddSettings = seq(autoPlugins, nonAutoPlugins)
|
||||
|
||||
/** Allows the plugins whose names match the `names` filter to automatically add settings to a project. */
|
||||
def plugins(include: Plugin => Boolean): AddSettings = new Plugins(include)
|
||||
|
|
|
|||
|
|
@ -505,19 +505,23 @@ object Load
|
|||
def loadSettingsFile(src: File): LoadedSbtFile =
|
||||
EvaluateConfigurations.evaluateSbtFile(eval(), src, IO.readLines(src), loadedPlugins.detected.imports, 0)(loader)
|
||||
|
||||
import AddSettings.{User,SbtFiles,DefaultSbtFiles,Plugins,Sequence, ProjectSettings}
|
||||
import AddSettings.{User,SbtFiles,DefaultSbtFiles,Plugins,AutoPlugins,Sequence, ProjectSettings}
|
||||
def pluginSettings(f: Plugins) = {
|
||||
val included = loadedPlugins.detected.plugins.values.filter(f.include) // don't apply the filter to AutoPlugins, only Plugins
|
||||
val oldStyle = included.flatMap(p => p.settings.filter(isProjectThis) ++ p.projectSettings)
|
||||
val autoStyle = autoPlugins.flatMap(_.projectSettings)
|
||||
oldStyle ++ autoStyle
|
||||
included.flatMap(p => p.settings.filter(isProjectThis) ++ p.projectSettings)
|
||||
}
|
||||
// Filter the AutoPlugin settings we included based on which ones are
|
||||
// intended in the AddSettings.AutoPlugins filter.
|
||||
def autoPluginSettings(f: AutoPlugins) =
|
||||
autoPlugins.filter(f.include).flatMap(_.projectSettings)
|
||||
|
||||
def expand(auto: AddSettings): LoadedSbtFile = auto match {
|
||||
case ProjectSettings => settings(projectSettings)
|
||||
case User => settings(injectSettings.projectLoaded(loader))
|
||||
case sf: SbtFiles => loadSettings( sf.files.map(f => IO.resolve(projectBase, f)))
|
||||
case sf: DefaultSbtFiles => loadSettings( defaultSbtFiles.filter(sf.include))
|
||||
case p: Plugins => settings(pluginSettings(p))
|
||||
case p: AutoPlugins => settings(autoPluginSettings(p))
|
||||
case q: Sequence => (LoadedSbtFile.empty /: q.sequence) { (b,add) => b.merge( expand(add) ) }
|
||||
}
|
||||
expand(auto)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,24 @@ abstract class AutoPlugin extends Plugins.Basic
|
|||
// TODO?: def commands: Seq[Command]
|
||||
|
||||
def unary_! : Exclude = Exclude(this)
|
||||
|
||||
|
||||
/** If this plugin requries itself to be included, it means we're actually a nature,
|
||||
* not a normal plugin. The user must specifically enable this plugin
|
||||
* but other plugins can rely on its existence.
|
||||
*/
|
||||
final def isRoot: Boolean =
|
||||
this match {
|
||||
case _: RootAutoPlugin => true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A root AutoPlugin is a plugin which must be explicitly enabled by users in their `setPlugins` method
|
||||
* on a project. However, RootAutoPlugins represent the "root" of a tree of dependent auto-plugins.
|
||||
*/
|
||||
abstract class RootAutoPlugin extends AutoPlugin {
|
||||
final def select: Plugins = this
|
||||
}
|
||||
|
||||
/** An error that occurs when auto-plugins aren't configured properly.
|
||||
|
|
@ -104,7 +122,10 @@ object Plugins
|
|||
val byAtom = defined.map(x => (Atom(x.label), x))
|
||||
val byAtomMap = byAtom.toMap
|
||||
if(byAtom.size != byAtomMap.size) duplicateProvidesError(byAtom)
|
||||
val clauses = Clauses( defined.map(d => asClause(d)) )
|
||||
// Ignore clauses for plugins that just require themselves be specified.
|
||||
// Avoids the requirement for pure Nature strings *and* possible
|
||||
// circular dependencies in the logic.
|
||||
val clauses = Clauses( defined.filterNot(_.isRoot).map(d => asClause(d)) )
|
||||
requestedPlugins =>
|
||||
Logic.reduce(clauses, flattenConvert(requestedPlugins).toSet) match {
|
||||
case Left(problem) => throw AutoPluginException(problem)
|
||||
|
|
|
|||
Loading…
Reference in New Issue