diff --git a/platforms/core-configuration/declarative-dsl-core/src/main/kotlin/org/gradle/internal/declarativedsl/analysis/AnalysisStatementFilter.kt b/platforms/core-configuration/declarative-dsl-core/src/main/kotlin/org/gradle/internal/declarativedsl/analysis/AnalysisStatementFilter.kt index 82cce731c7a2..0afb2cb0386d 100644 --- a/platforms/core-configuration/declarative-dsl-core/src/main/kotlin/org/gradle/internal/declarativedsl/analysis/AnalysisStatementFilter.kt +++ b/platforms/core-configuration/declarative-dsl-core/src/main/kotlin/org/gradle/internal/declarativedsl/analysis/AnalysisStatementFilter.kt @@ -17,11 +17,47 @@ package org.gradle.internal.declarativedsl.analysis import org.gradle.internal.declarativedsl.language.DataStatement +import org.gradle.internal.declarativedsl.language.FunctionArgument +import org.gradle.internal.declarativedsl.language.FunctionCall fun interface AnalysisStatementFilter { fun shouldAnalyzeStatement(statement: DataStatement, scopes: List): Boolean + + companion object { + val isConfiguringCall: AnalysisStatementFilter = AnalysisStatementFilter { statement, _ -> + statement is FunctionCall && statement.args.singleOrNull() is FunctionArgument.Lambda + } + + + val isTopLevelElement: AnalysisStatementFilter = AnalysisStatementFilter { _, scopes -> + scopes.last().receiver is ObjectOrigin.TopLevelReceiver + } + + + fun isCallNamed(name: String): AnalysisStatementFilter = AnalysisStatementFilter { statement, _ -> + statement is FunctionCall && statement.name == name + } + } +} + + +val analyzeEverything: AnalysisStatementFilter = AnalysisStatementFilter { _, _ -> true } + + +fun AnalysisStatementFilter.and(other: AnalysisStatementFilter): AnalysisStatementFilter = AnalysisStatementFilter { statement, scopes -> + shouldAnalyzeStatement(statement, scopes) && other.shouldAnalyzeStatement(statement, scopes) +} + + +fun AnalysisStatementFilter.or(other: AnalysisStatementFilter): AnalysisStatementFilter = AnalysisStatementFilter { statement, scopes -> + shouldAnalyzeStatement(statement, scopes) || other.shouldAnalyzeStatement(statement, scopes) } -val analyzeEverything = AnalysisStatementFilter { _, _ -> true } +fun AnalysisStatementFilter.implies(other: AnalysisStatementFilter) = this.not().or(other) + + +fun AnalysisStatementFilter.not(): AnalysisStatementFilter = AnalysisStatementFilter { statement, scopes -> + !shouldAnalyzeStatement(statement, scopes) +} diff --git a/platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/DeclarativeDslProjectSettingsIntegrationSpec.groovy b/platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/settings/DeclarativeDslProjectSettingsIntegrationSpec.groovy similarity index 54% rename from platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/DeclarativeDslProjectSettingsIntegrationSpec.groovy rename to platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/settings/DeclarativeDslProjectSettingsIntegrationSpec.groovy index d6b4c0dcc452..1159aa21a4e5 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/DeclarativeDslProjectSettingsIntegrationSpec.groovy +++ b/platforms/core-configuration/declarative-dsl-provider/src/integTest/groovy/org/gradle/internal/declarativedsl/settings/DeclarativeDslProjectSettingsIntegrationSpec.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.internal.declarativedsl +package org.gradle.internal.declarativedsl.settings import org.gradle.integtests.fixtures.AbstractIntegrationSpec @@ -85,4 +85,71 @@ class DeclarativeDslProjectSettingsIntegrationSpec extends AbstractIntegrationSp "language feature" | "@A dependencies { }" | "2:13: unsupported language feature: AnnotationUsage" "semantic" | "x = 1" | "2:13: unresolved reference 'x'" } + + def 'can apply settings plugins'() { + given: + file("included-settings-plugin/build.gradle") << """ + plugins { + id('java-gradle-plugin') + } + gradlePlugin { + plugins { + create("settingsPlugin") { + id = "com.example.restricted.settings" + implementationClass = "com.example.restricted.RestrictedSettingsPlugin" + } + } + } + """ + + file("included-settings-plugin/src/main/java/com/example/restricted/Extension.java") << """ + package com.example.restricted; + + import org.gradle.declarative.dsl.model.annotations.Restricted; + import org.gradle.api.provider.Property; + + import javax.inject.Inject; + + @Restricted + public abstract class Extension { + @Restricted + public abstract Property getId(); + } + """ + + file("included-settings-plugin/src/main/java/com/example/restricted/RestrictedSettingsPlugin.java") << """ + package com.example.restricted; + + import org.gradle.api.Plugin; + import org.gradle.api.initialization.Settings; + + public class RestrictedSettingsPlugin implements Plugin { + @Override + public void apply(Settings target) { + Extension restricted = target.getExtensions().create("restricted", Extension.class); + target.getGradle().settingsEvaluated(settings -> { + System.out.println("id = " + restricted.getId().get()); + }); + } + } + """ + + file("settings.gradle.something") << """ + pluginManagement { + includeBuild("included-settings-plugin") + } + + plugins { + id("com.example.restricted.settings") + } + + restricted { + id = "test" + } + """ + + expect: + succeeds("help") + outputContains("id = test") + } } diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluationSchema/InterpretationSequence.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluationSchema/InterpretationSequence.kt index 58c80147e489..abd137da0165 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluationSchema/InterpretationSequence.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluationSchema/InterpretationSequence.kt @@ -30,3 +30,19 @@ interface InterpretationSequenceStep { fun topLevelReceiver(): R fun whenEvaluated(resultReceiver: R) } + + +/** + * Implements a straightforward interpretation sequence step that uses the specified [topLevelReceiver] + * and produces an evaluation schema with [buildEvaluationSchema] immediately before the step runs. + */ +internal +class SimpleInterpretationSequenceStep( + override val stepIdentifier: String, + private val topLevelReceiver: T, + private val buildEvaluationSchema: () -> EvaluationSchema +) : InterpretationSequenceStep { + override fun evaluationSchemaForStep(): EvaluationSchema = buildEvaluationSchema() + override fun topLevelReceiver(): T = topLevelReceiver + override fun whenEvaluated(resultReceiver: T) = Unit +} diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DeclarativeKotlinScriptEvaluator.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DeclarativeKotlinScriptEvaluator.kt index 40cb212625f8..72c37fb7b27e 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DeclarativeKotlinScriptEvaluator.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DeclarativeKotlinScriptEvaluator.kt @@ -46,7 +46,6 @@ import org.gradle.internal.declarativedsl.objectGraph.ReflectionContext import org.gradle.internal.declarativedsl.objectGraph.reflect import org.gradle.internal.declarativedsl.parsing.DefaultLanguageTreeBuilder import org.gradle.internal.declarativedsl.parsing.parse -import org.gradle.internal.declarativedsl.plugins.PluginsTopLevelReceiver interface DeclarativeKotlinScriptEvaluator { @@ -73,21 +72,10 @@ interface DeclarativeKotlinScriptEvaluator { class ScriptPluginEvaluationContext( val targetScope: ClassLoaderScope ) : EvaluationContext - - object PluginsDslEvaluationContext : EvaluationContext } } -/** - * A default implementation of a declarative DSL script evaluator, for use when no additional information needs to be provided at the use site. - * TODO: The consumers should get an instance properly injected instead. - */ -val defaultDeclarativeKotlinScriptEvaluator: DeclarativeKotlinScriptEvaluator by lazy { - DefaultDeclarativeKotlinScriptEvaluator(DefaultInterpretationSchemaBuilder()) -} - - internal class DefaultDeclarativeKotlinScriptEvaluator( private val schemaBuilder: InterpretationSchemaBuilder @@ -180,13 +168,15 @@ class DefaultDeclarativeKotlinScriptEvaluator( target: Any, scriptSource: ScriptSource, evaluationContext: DeclarativeKotlinScriptEvaluator.EvaluationContext - ) = when (target) { - is Settings -> RestrictedScriptContext.SettingsScript - is Project -> { - require(evaluationContext is ScriptPluginEvaluationContext) { "declarative DSL for projects is only supported in script plugins" } - RestrictedScriptContext.ProjectScript(evaluationContext.targetScope, scriptSource) - } - is PluginsTopLevelReceiver -> RestrictedScriptContext.PluginsBlock + ): RestrictedScriptContext = when (target) { + is Settings -> RestrictedScriptContext.SettingsScript(requirePluginContext(evaluationContext).targetScope, scriptSource) + is Project -> RestrictedScriptContext.ProjectScript(requirePluginContext(evaluationContext).targetScope, scriptSource) else -> RestrictedScriptContext.UnknownScript } + + private + fun requirePluginContext(evaluationContext: DeclarativeKotlinScriptEvaluator.EvaluationContext): ScriptPluginEvaluationContext { + require(evaluationContext is ScriptPluginEvaluationContext) { "this target is not supported outside script plugins" } + return evaluationContext + } } diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DefaultInterpretationSchemaBuilder.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DefaultInterpretationSchemaBuilder.kt index f882df051a28..76b3629f24ae 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DefaultInterpretationSchemaBuilder.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/DefaultInterpretationSchemaBuilder.kt @@ -16,16 +16,12 @@ package org.gradle.internal.declarativedsl.evaluator -import org.gradle.api.initialization.Settings +import org.gradle.api.internal.SettingsInternal import org.gradle.api.internal.project.ProjectInternal -import org.gradle.internal.declarativedsl.evaluationSchema.EvaluationSchema -import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequence -import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequenceStep import org.gradle.internal.declarativedsl.evaluator.InterpretationSchemaBuildingResult.InterpretationSequenceAvailable import org.gradle.internal.declarativedsl.evaluator.InterpretationSchemaBuildingResult.SchemaNotBuilt -import org.gradle.internal.declarativedsl.plugins.schemaForPluginsBlock import org.gradle.internal.declarativedsl.project.projectInterpretationSequence -import org.gradle.internal.declarativedsl.settings.settingsEvaluationSchema +import org.gradle.internal.declarativedsl.settings.settingsInterpretationSequence internal @@ -36,22 +32,13 @@ class DefaultInterpretationSchemaBuilder : InterpretationSchemaBuilder { ): InterpretationSchemaBuildingResult = when (scriptContext) { is RestrictedScriptContext.UnknownScript -> SchemaNotBuilt - RestrictedScriptContext.PluginsBlock -> simpleInterpretation("plugins", EvaluationSchema(schemaForPluginsBlock), targetInstance) - is RestrictedScriptContext.SettingsScript -> simpleInterpretation("settings", settingsEvaluationSchema(targetInstance as Settings), targetInstance) - is RestrictedScriptContext.ProjectScript -> - InterpretationSequenceAvailable(projectInterpretationSequence(targetInstance as ProjectInternal, scriptContext.targetScope, scriptContext.scriptSource)) - } - private - fun simpleInterpretation(id: String, schema: EvaluationSchema, target: Any) = - InterpretationSequenceAvailable( - InterpretationSequence( - listOf(object : InterpretationSequenceStep { - override val stepIdentifier: String = id - override fun evaluationSchemaForStep(): EvaluationSchema = schema - override fun topLevelReceiver(): Any = target - override fun whenEvaluated(resultReceiver: Any) = Unit - }) + is RestrictedScriptContext.SettingsScript -> InterpretationSequenceAvailable( + settingsInterpretationSequence(targetInstance as SettingsInternal, scriptContext.targetScope, scriptContext.scriptSource) + ) + + is RestrictedScriptContext.ProjectScript -> InterpretationSequenceAvailable( + projectInterpretationSequence(targetInstance as ProjectInternal, scriptContext.targetScope, scriptContext.scriptSource) ) - ) + } } diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/InterpretationSchemaBuilder.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/InterpretationSchemaBuilder.kt index 6e4e49678249..c92d705d75f9 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/InterpretationSchemaBuilder.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/evaluator/InterpretationSchemaBuilder.kt @@ -44,8 +44,10 @@ sealed interface RestrictedScriptContext { val scriptSource: ScriptSource } - object SettingsScript : RestrictedScriptContext - object PluginsBlock : RestrictedScriptContext + data class SettingsScript( + override val targetScope: ClassLoaderScope, + override val scriptSource: ScriptSource + ) : ScriptDependentContext class ProjectScript( override val targetScope: ClassLoaderScope, diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/plugins/PluginsInterpretationSequenceStep.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/plugins/PluginsInterpretationSequenceStep.kt index 199f67fe441c..3388cbda37c8 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/plugins/PluginsInterpretationSequenceStep.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/plugins/PluginsInterpretationSequenceStep.kt @@ -21,12 +21,14 @@ import org.gradle.api.internal.initialization.ScriptHandlerFactory import org.gradle.api.internal.plugins.PluginManagerInternal import org.gradle.groovy.scripts.ScriptSource import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter -import org.gradle.internal.declarativedsl.analysis.ObjectOrigin +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isCallNamed +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isConfiguringCall +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isTopLevelElement +import org.gradle.internal.declarativedsl.analysis.and +import org.gradle.internal.declarativedsl.analysis.implies +import org.gradle.internal.declarativedsl.analysis.not import org.gradle.internal.declarativedsl.evaluationSchema.EvaluationSchema import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequenceStep -import org.gradle.internal.declarativedsl.language.DataStatement -import org.gradle.internal.declarativedsl.language.FunctionArgument -import org.gradle.internal.declarativedsl.language.FunctionCall import org.gradle.internal.service.ServiceRegistry import org.gradle.plugin.management.internal.DefaultPluginRequest import org.gradle.plugin.management.internal.PluginRequestInternal @@ -37,15 +39,15 @@ import org.gradle.plugin.use.internal.PluginRequestApplicator internal class PluginsInterpretationSequenceStep( + override val stepIdentifier: String = "plugins", private val target: T, private val targetScope: ClassLoaderScope, private val scriptSource: ScriptSource, private val getTargetServices: (T) -> ServiceRegistry, - override val stepIdentifier: String = "plugins", ) : InterpretationSequenceStep { override fun evaluationSchemaForStep(): EvaluationSchema = EvaluationSchema( schemaForPluginsBlock, - analysisStatementFilter = analyzeTopLevelPluginsBlockOnly + analysisStatementFilter = isTopLevelPluginsBlock ) override fun topLevelReceiver() = PluginsTopLevelReceiver() @@ -65,14 +67,13 @@ class PluginsInterpretationSequenceStep( } +private +val isPluginConfiguringCall: AnalysisStatementFilter = isConfiguringCall.and(isCallNamed("plugins")) + + internal -val analyzeTopLevelPluginsBlockOnly = AnalysisStatementFilter { statement, scopes -> - if (scopes.last().receiver is ObjectOrigin.TopLevelReceiver) { - isPluginsCall(statement) - } else true -} +val isTopLevelPluginsBlock: AnalysisStatementFilter = isTopLevelElement.implies(isPluginConfiguringCall) internal -fun isPluginsCall(statement: DataStatement) = - statement is FunctionCall && statement.name == "plugins" && statement.args.size == 1 && statement.args.single() is FunctionArgument.Lambda +val ignoreTopLevelPluginsBlock: AnalysisStatementFilter = isTopLevelElement.implies(isPluginConfiguringCall.not()) diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/ProjectSchema.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/ProjectSchema.kt index ffa7709231f2..972688acd970 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/ProjectSchema.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/ProjectSchema.kt @@ -19,16 +19,13 @@ package org.gradle.internal.declarativedsl.project import org.gradle.api.internal.initialization.ClassLoaderScope import org.gradle.api.internal.project.ProjectInternal import org.gradle.groovy.scripts.ScriptSource -import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter -import org.gradle.internal.declarativedsl.analysis.ObjectOrigin import org.gradle.internal.declarativedsl.evaluationSchema.EvaluationSchema import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequence -import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequenceStep +import org.gradle.internal.declarativedsl.evaluationSchema.SimpleInterpretationSequenceStep import org.gradle.internal.declarativedsl.evaluationSchema.buildEvaluationSchema import org.gradle.internal.declarativedsl.evaluationSchema.plus import org.gradle.internal.declarativedsl.plugins.PluginsInterpretationSequenceStep -import org.gradle.internal.declarativedsl.plugins.PluginsTopLevelReceiver -import org.gradle.internal.declarativedsl.plugins.isPluginsCall +import org.gradle.internal.declarativedsl.plugins.ignoreTopLevelPluginsBlock internal @@ -38,46 +35,21 @@ fun projectInterpretationSequence( scriptSource: ScriptSource ) = InterpretationSequence( listOf( - step1Plugins(target, targetScope, scriptSource), - step2Project(target, targetScope) + PluginsInterpretationSequenceStep("plugins", target, targetScope, scriptSource, ProjectInternal::getServices), + SimpleInterpretationSequenceStep("project", target) { projectEvaluationSchema(target, targetScope) } ) ) private -fun step1Plugins(target: ProjectInternal, targetScope: ClassLoaderScope, scriptSource: ScriptSource): InterpretationSequenceStep = - PluginsInterpretationSequenceStep(target, targetScope, scriptSource, ProjectInternal::getServices) - - -private -fun step2Project(target: ProjectInternal, targetScope: ClassLoaderScope) = object : InterpretationSequenceStep { - override val stepIdentifier: String = "project" - - override fun evaluationSchemaForStep(): EvaluationSchema = buildEvaluationSchema( - ProjectTopLevelReceiver::class, - projectEvaluationSchemaComponent(target, targetScope), - analysisStatementFilter = analyzeEverythingExceptPluginsBlock, - ) - - override fun topLevelReceiver(): ProjectInternal = target - - override fun whenEvaluated(resultReceiver: ProjectInternal) = Unit -} - - -private -fun projectEvaluationSchemaComponent( +fun projectEvaluationSchema( target: ProjectInternal, targetScope: ClassLoaderScope -) = gradleDslGeneralSchemaComponent() + - ThirdPartyExtensionsComponent(ProjectTopLevelReceiver::class, target, "projectExtension") + - DependencyConfigurationsComponent(target) + - TypesafeProjectAccessorsComponent(targetScope) - +): EvaluationSchema { + val component = gradleDslGeneralSchemaComponent() + + ThirdPartyExtensionsComponent(ProjectTopLevelReceiver::class, target, "projectExtension") + + DependencyConfigurationsComponent(target) + + TypesafeProjectAccessorsComponent(targetScope) -private -val analyzeEverythingExceptPluginsBlock = AnalysisStatementFilter { statement, scopes -> - if (scopes.last().receiver is ObjectOrigin.TopLevelReceiver) { - !isPluginsCall(statement) - } else true + return buildEvaluationSchema(ProjectTopLevelReceiver::class, component, ignoreTopLevelPluginsBlock) } diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/schemaFromGradleExtensions.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/schemaFromGradleExtensions.kt index 0019bc9509f9..0823cc847b0e 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/schemaFromGradleExtensions.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/project/schemaFromGradleExtensions.kt @@ -26,7 +26,6 @@ import org.gradle.internal.declarativedsl.schemaBuilder.DataSchemaBuilder import org.gradle.internal.declarativedsl.schemaBuilder.FunctionExtractor import org.gradle.internal.declarativedsl.schemaBuilder.TypeDiscovery import org.gradle.internal.declarativedsl.schemaBuilder.toDataTypeRef -import org.gradle.api.Project import org.gradle.api.plugins.ExtensionAware import org.gradle.declarative.dsl.model.annotations.Restricted import org.gradle.internal.declarativedsl.evaluationSchema.EvaluationSchemaComponent @@ -62,7 +61,7 @@ class ThirdPartyExtensionsComponent( ) override fun functionExtractors(): List = listOf( - projectExtensionConfiguringFunctions(extensions) + extensionConfiguringFunctions(schemaTypeToExtend, extensions) ) override fun runtimeCustomAccessors(): List = listOf( @@ -107,16 +106,14 @@ class RuntimeExtensionAccessors(info: List) : RuntimeCustomAccess val extensionsByIdentifier = info.associate { it.customAccessorId to it.extensionProvider() } override fun getObjectFromCustomAccessor(receiverObject: Any, accessor: ConfigureAccessor.Custom): Any? = - if (receiverObject is Project) - extensionsByIdentifier[accessor.customAccessorIdentifier] - else null + extensionsByIdentifier[accessor.customAccessorIdentifier] } private -fun projectExtensionConfiguringFunctions(extensionInfo: Iterable): FunctionExtractor = object : FunctionExtractor { +fun extensionConfiguringFunctions(typeToExtend: KClass<*>, extensionInfo: Iterable): FunctionExtractor = object : FunctionExtractor { override fun memberFunctions(kClass: KClass<*>, preIndex: DataSchemaBuilder.PreIndex): Iterable = - if (kClass == ProjectTopLevelReceiver::class) extensionInfo.map(ExtensionInfo::schemaFunction) else emptyList() + if (kClass == typeToExtend) extensionInfo.map(ExtensionInfo::schemaFunction) else emptyList() override fun constructors(kClass: KClass<*>, preIndex: DataSchemaBuilder.PreIndex): Iterable = emptyList() diff --git a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/settings/SettingsDslSchema.kt b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/settings/SettingsDslSchema.kt index 1e0d99f748d4..a245ab765d7b 100644 --- a/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/settings/SettingsDslSchema.kt +++ b/platforms/core-configuration/declarative-dsl-provider/src/main/kotlin/org/gradle/internal/declarativedsl/settings/SettingsDslSchema.kt @@ -17,18 +17,63 @@ package org.gradle.internal.declarativedsl.settings import org.gradle.api.initialization.Settings -import org.gradle.internal.declarativedsl.analysis.analyzeEverything +import org.gradle.api.internal.SettingsInternal +import org.gradle.api.internal.initialization.ClassLoaderScope +import org.gradle.groovy.scripts.ScriptSource +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isCallNamed +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isConfiguringCall +import org.gradle.internal.declarativedsl.analysis.AnalysisStatementFilter.Companion.isTopLevelElement +import org.gradle.internal.declarativedsl.analysis.and +import org.gradle.internal.declarativedsl.analysis.implies +import org.gradle.internal.declarativedsl.analysis.not import org.gradle.internal.declarativedsl.evaluationSchema.EvaluationSchema +import org.gradle.internal.declarativedsl.evaluationSchema.InterpretationSequence +import org.gradle.internal.declarativedsl.evaluationSchema.SimpleInterpretationSequenceStep import org.gradle.internal.declarativedsl.evaluationSchema.buildEvaluationSchema import org.gradle.internal.declarativedsl.evaluationSchema.plus +import org.gradle.internal.declarativedsl.plugins.PluginsInterpretationSequenceStep +import org.gradle.internal.declarativedsl.plugins.isTopLevelPluginsBlock import org.gradle.internal.declarativedsl.project.ThirdPartyExtensionsComponent import org.gradle.internal.declarativedsl.project.gradleDslGeneralSchemaComponent +internal +fun settingsInterpretationSequence( + settings: SettingsInternal, + targetScope: ClassLoaderScope, + scriptSource: ScriptSource +): InterpretationSequence = + InterpretationSequence( + listOf( + SimpleInterpretationSequenceStep("settingsPluginManagement", settings) { pluginManagementEvaluationSchema() }, + PluginsInterpretationSequenceStep("settingsPlugins", settings, targetScope, scriptSource) { it.services }, + SimpleInterpretationSequenceStep("settings", settings) { settingsEvaluationSchema(settings) } + ) + ) + + +internal +fun pluginManagementEvaluationSchema(): EvaluationSchema = + buildEvaluationSchema(Settings::class, gradleDslGeneralSchemaComponent(), isTopLevelPluginManagementBlock) + + internal fun settingsEvaluationSchema(settings: Settings): EvaluationSchema { val schemaBuildingComponent = gradleDslGeneralSchemaComponent() + ThirdPartyExtensionsComponent(Settings::class, settings, "settingsExtension") - return buildEvaluationSchema(Settings::class, schemaBuildingComponent, analyzeEverything) + return buildEvaluationSchema(Settings::class, schemaBuildingComponent, ignoreTopLevelPluginsAndPluginManagement) } + + +private +val isPluginManagementCall: AnalysisStatementFilter = isConfiguringCall.and(isCallNamed("pluginManagement")) + + +private +val isTopLevelPluginManagementBlock = isTopLevelElement.implies(isPluginManagementCall) + + +private +val ignoreTopLevelPluginsAndPluginManagement = isTopLevelElement.implies(isPluginManagementCall.not().and(isTopLevelPluginsBlock.not()))