mirror of https://github.com/sbt/sbt.git
[2.x] fix: Cache AutoPlugin projectSettings/projectConfigurations (#9077)
- Cache AutoPlugin.projectSettings and projectConfigurations via AutoPluginCache so they are evaluated once per plugin instance during build loading, not once per subproject (N×M → M) - Make GroupedAutoPlugins.globalSettings a lazy val and pre-compute buildSettingsMap to avoid repeated aggregation
This commit is contained in:
parent
4ebacc6e05
commit
ac0f3f5c6f
|
|
@ -16,9 +16,11 @@ private[sbt] final class GroupedAutoPlugins(
|
|||
val all: Seq[AutoPlugin],
|
||||
val byBuild: Map[URI, Seq[AutoPlugin]]
|
||||
) {
|
||||
def globalSettings: Seq[Setting[?]] = all.flatMap(_.globalSettings)
|
||||
lazy val globalSettings: Seq[Setting[?]] = all.flatMap(_.globalSettings)
|
||||
private lazy val buildSettingsMap: Map[URI, Seq[Setting[?]]] =
|
||||
byBuild.view.mapValues(_.flatMap(_.buildSettings)).toMap
|
||||
def buildSettings(uri: URI): Seq[Setting[?]] =
|
||||
byBuild.getOrElse(uri, Nil).flatMap(_.buildSettings)
|
||||
buildSettingsMap.getOrElse(uri, Nil)
|
||||
}
|
||||
|
||||
private[sbt] object GroupedAutoPlugins {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,23 @@ import scala.annotation.tailrec
|
|||
import scala.collection.mutable
|
||||
import sbt.internal.util.Util
|
||||
|
||||
/**
|
||||
* Caches `AutoPlugin.projectSettings` and `projectConfigurations` so they are
|
||||
* evaluated only once per plugin instance during build loading, regardless of how
|
||||
* many subprojects activate the plugin. See https://github.com/sbt/sbt/issues/5166
|
||||
*/
|
||||
private[sbt] final class AutoPluginCache {
|
||||
private val settingsCache: mutable.HashMap[AutoPlugin, Seq[Def.Setting[?]]] =
|
||||
mutable.HashMap.empty
|
||||
private val configCache: mutable.HashMap[AutoPlugin, Seq[Configuration]] = mutable.HashMap.empty
|
||||
|
||||
def projectSettings(plugin: AutoPlugin): Seq[Def.Setting[?]] =
|
||||
settingsCache.getOrElseUpdate(plugin, plugin.projectSettings)
|
||||
|
||||
def projectConfigurations(plugin: AutoPlugin): Seq[Configuration] =
|
||||
configCache.getOrElseUpdate(plugin, plugin.projectConfigurations)
|
||||
}
|
||||
|
||||
private[sbt] object Load {
|
||||
// note that there is State passed in but not pulled out
|
||||
def defaultLoad(
|
||||
|
|
@ -832,6 +849,7 @@ private[sbt] object Load {
|
|||
defsScala.exists(_.rootProject.isDefined) || rootFromExtra.nonEmpty
|
||||
|
||||
val memoSettings = new mutable.HashMap[VirtualFile, LoadedSbtFile]
|
||||
val pluginCache = new AutoPluginCache
|
||||
def loadProjects(ps: Seq[Project], createRoot: Boolean) =
|
||||
loadTransitive(
|
||||
ps,
|
||||
|
|
@ -849,6 +867,7 @@ private[sbt] object Load {
|
|||
Nil,
|
||||
s.get(BasicKeys.extraMetaSbtFiles).getOrElse(Nil),
|
||||
converter = config.converter,
|
||||
pluginCache = pluginCache,
|
||||
)
|
||||
val loadedProjectsRaw = timed("Load.loadUnit: loadedProjectsRaw", log) {
|
||||
loadProjects(initialProjects, !hasRootAlreadyDefined)
|
||||
|
|
@ -1010,6 +1029,7 @@ private[sbt] object Load {
|
|||
generatedConfigClassFiles: Seq[Path],
|
||||
extraSbtFiles: Seq[VirtualFile],
|
||||
converter: MappedFileConverter,
|
||||
pluginCache: AutoPluginCache,
|
||||
): LoadedProjects =
|
||||
// alias for parameter forwarding
|
||||
def loadTransitive1(
|
||||
|
|
@ -1034,6 +1054,7 @@ private[sbt] object Load {
|
|||
generated,
|
||||
Nil,
|
||||
converter,
|
||||
pluginCache,
|
||||
)
|
||||
|
||||
// alias for parameter forwarding
|
||||
|
|
@ -1085,6 +1106,7 @@ private[sbt] object Load {
|
|||
extraSbtFiles = extraFiles,
|
||||
converter = converter,
|
||||
log = log,
|
||||
pluginCache = pluginCache,
|
||||
)
|
||||
val projectLevelExtra =
|
||||
if (expand) {
|
||||
|
|
@ -1207,12 +1229,13 @@ private[sbt] object Load {
|
|||
machineWideUserSettings: InjectSettings,
|
||||
memoSettings: mutable.Map[VirtualFile, LoadedSbtFile],
|
||||
extraSbtFiles: Seq[VirtualFile],
|
||||
pluginCache: AutoPluginCache,
|
||||
converter: MappedFileConverter,
|
||||
log: Logger
|
||||
): Project =
|
||||
timed(s"Load.resolveProjectSettings(${p.id})", log) {
|
||||
import AddSettings.*
|
||||
val autoConfigs = projectPlugins.flatMap(_.projectConfigurations)
|
||||
val autoConfigs = projectPlugins.flatMap(pluginCache.projectConfigurations)
|
||||
val auto = AddSettings.allDefaults
|
||||
// 3. Use AddSettings instance to order all Setting[_]s appropriately
|
||||
// Settings are ordered as:
|
||||
|
|
@ -1221,7 +1244,7 @@ private[sbt] object Load {
|
|||
// Filter the AutoPlugin settings we included based on which ones are
|
||||
// intended in the AddSettings.AutoPlugins filter.
|
||||
def autoPluginSettings(f: AutoPlugins) =
|
||||
projectPlugins.withFilter(f.include).flatMap(_.projectSettings)
|
||||
projectPlugins.withFilter(f.include).flatMap(pluginCache.projectSettings)
|
||||
// Expand the AddSettings instance into a real Seq[Setting[_]] we'll use on the project
|
||||
def expandPluginSettings(auto: AddSettings): Seq[Setting[?]] =
|
||||
auto match
|
||||
|
|
|
|||
Loading…
Reference in New Issue