mirror of https://github.com/sbt/sbt.git
API documentation and comments related to natures
This commit is contained in:
parent
b8619f4aae
commit
30658f98bb
|
|
@ -16,7 +16,7 @@ The `select` method defines the conditions,
|
|||
Steps for plugin authors:
|
||||
1. Determine the natures that, when present (or absent), activate the AutoPlugin.
|
||||
2. Determine the settings/configurations to automatically inject when activated.
|
||||
3. Define a new, unique identifying [[Nature]] (which is a wrapper around a String ID).
|
||||
3. Define a new, unique identifying [[Nature]], which is a wrapper around a String ID.
|
||||
|
||||
For example, the following will automatically add the settings in `projectSettings`
|
||||
to a project that has both the `Web` and `Javascript` natures enabled. It will itself
|
||||
|
|
@ -26,7 +26,7 @@ For example, the following will automatically add the settings in `projectSettin
|
|||
object MyPlugin extends AutoPlugin {
|
||||
def select = Web && Javascript
|
||||
def provides = MyStuff
|
||||
def projectSettings = Seq(...)
|
||||
override def projectSettings = Seq(...)
|
||||
}
|
||||
|
||||
Steps for users:
|
||||
|
|
@ -92,6 +92,8 @@ object Natures
|
|||
{
|
||||
// TODO: allow multiple AutoPlugins to provide the same Nature?
|
||||
// TODO: translate error messages
|
||||
/** Given the available auto plugins `defined`, returns a function that selects [[AutoPlugin]]s for the provided [[Nature]]s.
|
||||
* The [[AutoPlugin]]s are topologically sorted so that a selected [[AutoPlugin]] comes before its selecting [[AutoPlugin]].*/
|
||||
def compile(defined: List[AutoPlugin]): Natures => Seq[AutoPlugin] =
|
||||
if(defined.isEmpty)
|
||||
Types.const(Nil)
|
||||
|
|
@ -101,10 +103,13 @@ object Natures
|
|||
val clauses = Clauses( defined.map(d => asClause(d)) )
|
||||
requestedNatures => {
|
||||
val results = Logic.reduce(clauses, flatten(requestedNatures).toSet)
|
||||
// results includes the originally requested (positive) atoms,
|
||||
// which won't have a corresponding AutoPlugin to map back to
|
||||
results.ordered.flatMap(a => byAtom.get(a).toList)
|
||||
}
|
||||
}
|
||||
|
||||
/** [[Natures]] instance that doesn't require any [[Nature]]s. */
|
||||
def empty: Natures = Empty
|
||||
private[sbt] final object Empty extends Natures {
|
||||
def &&(o: Basic): Natures = o
|
||||
|
|
@ -129,6 +134,7 @@ object Natures
|
|||
case b: Basic => a && b
|
||||
}
|
||||
|
||||
/** Defines a clause for `ap` such that the [[Nature]] provided by `ap` is the head and the selector for `ap` is the body. */
|
||||
private[sbt] def asClause(ap: AutoPlugin): Clause =
|
||||
Clause( convert(ap.select), Set(Atom(ap.provides.label)) )
|
||||
|
||||
|
|
|
|||
|
|
@ -30,30 +30,86 @@ final class StructureIndex(
|
|||
val keyIndex: KeyIndex,
|
||||
val aggregateKeyIndex: KeyIndex
|
||||
)
|
||||
|
||||
/** A resolved build unit. (`ResolvedBuildUnit` would be a better name to distinguish it from the loaded, but unresolved `BuildUnit`.)
|
||||
* @param unit The loaded, but unresolved [[BuildUnit]] this was resolved from.
|
||||
* @param defined The definitive map from project IDs to resolved projects.
|
||||
* These projects have had [[Reference]]s resolved and [[AutoPlugin]]s evaluated.
|
||||
* @param rootProjects The list of project IDs for the projects considered roots of this build.
|
||||
* The first root project is used as the default in several situations where a project is not otherwise selected.
|
||||
*/
|
||||
final class LoadedBuildUnit(val unit: BuildUnit, val defined: Map[String, ResolvedProject], val rootProjects: Seq[String], val buildSettings: Seq[Setting[_]]) extends BuildUnitBase
|
||||
{
|
||||
assert(!rootProjects.isEmpty, "No root projects defined for build unit " + unit)
|
||||
/** The project to use as the default when one is not otherwise selected.
|
||||
* [[LocalRootProject]] resolves to this from within the same build.*/
|
||||
val root = rootProjects.head
|
||||
|
||||
/** The base directory of the build unit (not the build definition).*/
|
||||
def localBase = unit.localBase
|
||||
|
||||
/** The classpath to use when compiling against this build unit's publicly visible code.
|
||||
* It includes build definition and plugin classes, but not classes for .sbt file statements and expressions. */
|
||||
def classpath: Seq[File] = unit.definitions.target ++ unit.plugins.classpath
|
||||
|
||||
/** The class loader to use for this build unit's publicly visible code.
|
||||
* It includes build definition and plugin classes, but not classes for .sbt file statements and expressions. */
|
||||
def loader = unit.definitions.loader
|
||||
|
||||
/** The imports to use for .sbt files, `consoleProject` and other contexts that use code from the build definition. */
|
||||
def imports = BuildUtil.getImports(unit)
|
||||
override def toString = unit.toString
|
||||
}
|
||||
|
||||
// TODO: figure out how to deprecate and drop buildNames
|
||||
/** The built and loaded build definition, including loaded but unresolved [[Project]]s, for a build unit (for a single URI).
|
||||
*
|
||||
* @param base The base directory of the build definition, typically `<build base>/project/`.
|
||||
* @param loader The ClassLoader containing all classes and plugins for the build definition project.
|
||||
* Note that this does not include classes for .sbt files.
|
||||
* @param builds The list of [[Build]]s for the build unit.
|
||||
* In addition to auto-discovered [[Build]]s, this includes any auto-generated default [[Build]]s.
|
||||
* @param projects The list of all [[Project]]s from all [[Build]]s.
|
||||
* These projects have not yet been resolved, but they have had auto-plugins applied.
|
||||
* In particular, each [[Project]]'s `autoPlugins` field is populated according to their configured `natures`
|
||||
* and their `settings` and `configurations` updated as appropriate.
|
||||
* @param buildNames No longer used and will be deprecated once feasible.
|
||||
*/
|
||||
final class LoadedDefinitions(val base: File, val target: Seq[File], val loader: ClassLoader, val builds: Seq[Build], val projects: Seq[Project], val buildNames: Seq[String])
|
||||
|
||||
final class DetectedModules[T](val modules: Seq[(String, T)]) {
|
||||
/** Auto-detected top-level modules (as in `object X`) of type `T` paired with their source names. */
|
||||
final class DetectedModules[T](val modules: Seq[(String, T)])
|
||||
{
|
||||
/** The source names of the modules. This is "X" in `object X`, as opposed to the implementation class name "X$".
|
||||
* The names are returned in a stable order such that `names zip values` pairs a name with the actual module. */
|
||||
def names: Seq[String] = modules.map(_._1)
|
||||
|
||||
/** The singleton value of the module.
|
||||
* The values are returned in a stable order such that `names zip values` pairs a name with the actual module. */
|
||||
def values: Seq[T] = modules.map(_._2)
|
||||
}
|
||||
|
||||
/** Auto-discovered modules for the build definition project. These include modules defined in build definition sources
|
||||
* as well as modules in binary dependencies.
|
||||
*
|
||||
* @param builds The [[Build]]s detected in the build definition. This does not include the default [[Build]] that sbt creates if none is defined.
|
||||
*/
|
||||
final class DetectedPlugins(val plugins: DetectedModules[Plugin], val autoImports: DetectedModules[AutoImport], val autoPlugins: DetectedModules[AutoPlugin], val builds: DetectedModules[Build])
|
||||
{
|
||||
/** Sequence of import expressions for the build definition. This includes the names of the [[Plugin]], [[Build]], and [[AutoImport]] modules, but not the [[AutoPlugin]] modules. */
|
||||
lazy val imports: Seq[String] = BuildUtil.getImports(plugins.names ++ builds.names ++ autoImports.names)
|
||||
|
||||
/** A function to select the right [[AutoPlugin]]s from [[autoPlugins]] given the defined [[Natures]] for a [[Project]]. */
|
||||
lazy val compileNatures: Natures => Seq[AutoPlugin] = Natures.compile(autoPlugins.values.toList)
|
||||
}
|
||||
|
||||
/** The built and loaded build definition project.
|
||||
* @param base The base directory for the build definition project (not the base of the project itself).
|
||||
* @param pluginData Evaluated tasks/settings from the build definition for later use.
|
||||
* This is necessary because the build definition project is discarded.
|
||||
* @param loader The class loader for the build definition project, notably excluding classes used for .sbt files.
|
||||
* @param detected Auto-detected modules in the build definition.
|
||||
*/
|
||||
final class LoadedPlugins(val base: File, val pluginData: PluginData, val loader: ClassLoader, val detected: DetectedPlugins)
|
||||
{
|
||||
/*
|
||||
|
|
@ -71,6 +127,11 @@ final class LoadedPlugins(val base: File, val pluginData: PluginData, val loader
|
|||
def classpath = data(fullClasspath)
|
||||
|
||||
}
|
||||
/** The loaded, but unresolved build unit.
|
||||
* @param uri The uniquely identifying URI for the build.
|
||||
* @param localBase The working location of the build on the filesystem.
|
||||
* For local URIs, this is the same as `uri`, but for remote URIs, this is the local copy or workspace allocated for the build.
|
||||
*/
|
||||
final class BuildUnit(val uri: URI, val localBase: File, val definitions: LoadedDefinitions, val plugins: LoadedPlugins)
|
||||
{
|
||||
override def toString = if(uri.getScheme == "file") localBase.toString else (uri + " (locally: " + localBase +")")
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ package sbt
|
|||
import Def.Setting
|
||||
import java.net.URI
|
||||
|
||||
final class GroupedAutoPlugins(val all: Seq[AutoPlugin], val byBuild: Map[URI, Seq[AutoPlugin]])
|
||||
private[sbt] final class GroupedAutoPlugins(val all: Seq[AutoPlugin], val byBuild: Map[URI, Seq[AutoPlugin]])
|
||||
{
|
||||
def globalSettings: Seq[Setting[_]] = all.flatMap(_.globalSettings)
|
||||
def buildSettings(uri: URI): Seq[Setting[_]] = byBuild.getOrElse(uri, Nil).flatMap(_.buildSettings)
|
||||
}
|
||||
|
||||
object GroupedAutoPlugins
|
||||
private[sbt] object GroupedAutoPlugins
|
||||
{
|
||||
private[sbt] def apply(units: Map[URI, LoadedBuildUnit]): GroupedAutoPlugins =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -469,6 +469,7 @@ object Load
|
|||
val autoConfigs = autoPlugins.flatMap(_.projectConfigurations)
|
||||
val loadedSbtFiles = loadSbtFiles(project.auto, project.base, autoPlugins)
|
||||
val newSettings = (project.settings: Seq[Setting[_]]) ++ loadedSbtFiles.settings
|
||||
// add the automatically selected settings, record the selected AutoPlugins, and register the automatically selected configurations
|
||||
val transformed = project.copy(settings = newSettings).setAutoPlugins(autoPlugins).overrideConfigs(autoConfigs : _*)
|
||||
(transformed, loadedSbtFiles.projects)
|
||||
}
|
||||
|
|
@ -621,6 +622,9 @@ object Load
|
|||
*/
|
||||
|
||||
def loadPlugins(dir: File, data: PluginData, loader: ClassLoader): sbt.LoadedPlugins =
|
||||
new sbt.LoadedPlugins(dir, data, loader, autoDetect(data, loader))
|
||||
|
||||
private[this] def autoDetect(data: PluginData, loader: ClassLoader): DetectedPlugins =
|
||||
{
|
||||
// TODO: binary detection for builds, autoImports, autoPlugins
|
||||
import AutoBinaryResource._
|
||||
|
|
@ -628,8 +632,7 @@ object Load
|
|||
val builds = detectModules[Build](data, loader, Builds)
|
||||
val autoImports = detectModules[AutoImport](data, loader, AutoImports)
|
||||
val autoPlugins = detectModules[AutoPlugin](data, loader, AutoPlugins)
|
||||
val detected = new DetectedPlugins(plugins, autoImports, autoPlugins, builds)
|
||||
new sbt.LoadedPlugins(dir, data, loader, detected)
|
||||
new DetectedPlugins(plugins, autoImports, autoPlugins, builds)
|
||||
}
|
||||
private[this] def detectModules[T](data: PluginData, loader: ClassLoader, resourceName: String)(implicit mf: reflect.ClassManifest[T]): DetectedModules[T] =
|
||||
{
|
||||
|
|
@ -677,6 +680,8 @@ TODO: UNCOMMENT BEFORE COMMIT
|
|||
binaryPlugins(classpath, loader, AutoBinaryResource.Plugins)
|
||||
*/
|
||||
|
||||
/** Relative paths of resources that list top-level modules that are available.
|
||||
* Normally, the classes for those modules will be in the same classpath entry as the resource. */
|
||||
object AutoBinaryResource {
|
||||
final val AutoPlugins = "sbt/sbt.autoplugins"
|
||||
final val Plugins = "sbt/sbt.plugins"
|
||||
|
|
|
|||
Loading…
Reference in New Issue