Skip to content

Commit

Permalink
Remove core interfaces from precompiled Kotlin script template type h…
Browse files Browse the repository at this point in the history
…ierarchy

Support for a common script API will come in a subsequent commit.
  • Loading branch information
bamboo committed Sep 25, 2019
1 parent 8d97c00 commit 6279eda
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ open class AbstractPrecompiledScriptPluginTest : AbstractPluginTest() {
protected
inline fun <reified T> instantiatePrecompiledScriptOf(target: T, className: String): Any =
loadCompiledKotlinClass(className)
.getConstructor(T::class.java)
.newInstance(target)
.getConstructor(T::class.java, T::class.java)
.newInstance(target, target)

protected
fun loadCompiledKotlinClass(className: String): Class<*> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import org.gradle.kotlin.dsl.fixtures.assertInstanceOf
import org.gradle.kotlin.dsl.fixtures.assertStandardOutputOf
import org.gradle.kotlin.dsl.fixtures.withFolders

import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript
import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript
import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledInitScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledProjectScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledSettingsScript

import org.gradle.test.fixtures.file.LeaksFileHandles

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ import org.gradle.internal.classpath.DefaultClassPath
import org.gradle.internal.hash.HashCode

import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.precompile.PrecompiledInitScript
import org.gradle.kotlin.dsl.precompile.PrecompiledProjectScript
import org.gradle.kotlin.dsl.precompile.PrecompiledSettingsScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledInitScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledProjectScript
import org.gradle.kotlin.dsl.precompile.v1.PrecompiledSettingsScript

import org.gradle.kotlin.dsl.provider.PrecompiledScriptPluginsSupport
import org.gradle.kotlin.dsl.provider.inClassPathMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ fun PrecompiledScriptPlugin.writeScriptPluginAdapterTo(outputDir: File) {
try {
Class
.forName("$compiledScriptTypeName")
.getDeclaredConstructor($targetType::class.java)
.newInstance(target)
.getDeclaredConstructor($targetType::class.java, $targetType::class.java)
.newInstance(target, target)
} catch (e: java.lang.reflect.InvocationTargetException) {
throw e.targetException
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,18 @@ package org.gradle.kotlin.dsl.precompile

import org.gradle.api.internal.ProcessOperations
import org.gradle.api.invocation.Gradle

import org.gradle.kotlin.dsl.GradleDsl
import org.gradle.kotlin.dsl.InitScriptApi
import org.gradle.kotlin.dsl.fileOperationsFor
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.support.serviceOf

import kotlin.script.extensions.SamWithReceiverAnnotations
import kotlin.script.templates.ScriptTemplateDefinition


/**
* Script template definition for precompiled Kotlin script targeting [Gradle] instances.
* Legacy script template definition for precompiled Kotlin script targeting [Gradle] instances.
*
* Kept for compatibility with precompiled script plugins published with Gradle versions prior to 6.0.
*
* @see PrecompiledProjectScript
*/
@ScriptTemplateDefinition(
resolver = PrecompiledScriptDependenciesResolver::class,
scriptFilePattern = "^.+\\.init\\.gradle\\.kts$")
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
@Deprecated("Kept for backward compatibility")
open class PrecompiledInitScript(target: Gradle) : InitScriptApi(target), Gradle by target {

override val fileOperations by lazy { fileOperationsFor(delegate, null) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,18 @@
package org.gradle.kotlin.dsl.precompile

import org.gradle.api.Project

import org.gradle.kotlin.dsl.GradleDsl
import org.gradle.kotlin.dsl.ScriptHandlerScope
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.support.delegates.ProjectDelegate

import org.gradle.plugin.use.PluginDependenciesSpec
import org.gradle.plugin.use.PluginDependencySpec

import kotlin.script.extensions.SamWithReceiverAnnotations
import kotlin.script.templates.ScriptTemplateDefinition


/**
* Script template definition for precompiled Kotlin scripts targeting [Project] instances.
*
* A precompiled script is a script compiled as part of a regular Kotlin source-set and distributed
* in the usual way, java class files packaged in some library, meant to be consumed as a binary
* Gradle plugin.
*
* The Gradle plugin id by which the precompiled script can be referenced is derived from its name
* and package declaration - if any - in the following fashion:
*
* ```kotlin
* fun pluginIdFor(script: File, packageName: String?) =
* (packageName?.let { "$it." } ?: "") + script.nameWithoutExtension
* ```
* Legacy script template definition for precompiled Kotlin scripts targeting [Project] instances.
*
* Thus, the script `src/main/kotlin/code-quality.gradle.kts` would be exposed as the `code-quality`
* plugin (assuming it has no package declaration) whereas the script
* `src/main/kotlin/gradlebuild/code-quality.gradle.kts` would be exposed as the `gradlebuild.code-quality`
* plugin, again assuming it has the matching package declaration.
* Kept for compatibility with precompiled script plugins published with Gradle versions prior to 6.0.
*/
@ScriptTemplateDefinition(
resolver = PrecompiledScriptDependenciesResolver::class,
scriptFilePattern = "^.*\\.gradle\\.kts$")
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
@Deprecated("Kept for backward compatibility")
open class PrecompiledProjectScript(
override val delegate: Project
) : ProjectDelegate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,27 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver {

companion object {

fun hashOf(charSequence: CharSequence?) = Hashing.hashString(charSequence).toString()
fun hashOf(charSequence: CharSequence) = Hashing.hashString(charSequence).toString()

fun implicitImportsForScript(scriptText: CharSequence, environment: Environment?) =
implicitImportsFrom(environment) + precompiledScriptPluginImportsFrom(environment, scriptText)

private
fun implicitImportsFrom(environment: Environment?) =
environment.stringList(EnvironmentProperties.kotlinDslImplicitImports)

private
fun precompiledScriptPluginImportsFrom(environment: Environment?, scriptText: CharSequence): List<String> =
environment.stringList(hashOf(scriptText))

private
fun Environment?.stringList(key: String) =
string(key)?.split(':')
?: emptyList()

private
fun Environment?.string(key: String) =
this?.get(key) as? String
}

object EnvironmentProperties {
Expand All @@ -49,26 +69,9 @@ class PrecompiledScriptDependenciesResolver : ScriptDependenciesResolver {

PseudoFuture(
KotlinBuildScriptDependencies(
imports = implicitImportsFrom(environment) + precompiledScriptPluginImportsFrom(environment, script),
imports = implicitImportsForScript(script.text!!, environment),
classpath = emptyList(),
sources = emptyList()
)
)

private
fun implicitImportsFrom(environment: Environment?) =
environment.stringList(EnvironmentProperties.kotlinDslImplicitImports)

private
fun precompiledScriptPluginImportsFrom(environment: Environment?, script: ScriptContents): List<String> =
environment.stringList(hashOf(script.text))

private
fun Environment?.stringList(key: String) =
string(key)?.split(':')
?: emptyList()

private
fun Environment?.string(key: String) =
this?.get(key) as? String
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,18 @@ package org.gradle.kotlin.dsl.precompile

import org.gradle.api.initialization.Settings
import org.gradle.api.internal.ProcessOperations

import org.gradle.kotlin.dsl.GradleDsl
import org.gradle.kotlin.dsl.SettingsScriptApi
import org.gradle.kotlin.dsl.fileOperationsFor
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.support.serviceOf

import kotlin.script.extensions.SamWithReceiverAnnotations
import kotlin.script.templates.ScriptTemplateDefinition


/**
* Script template definition for precompiled Kotlin script targeting [Settings] instances.
* Legacy script template definition for precompiled Kotlin script targeting [Settings] instances.
*
* Kept for compatibility with precompiled script plugins published with Gradle versions prior to 6.0.
*
* @see PrecompiledProjectScript
*/
@ScriptTemplateDefinition(
resolver = PrecompiledScriptDependenciesResolver::class,
scriptFilePattern = "^(settings|.+\\.settings)\\.gradle\\.kts$")
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
@Deprecated("Kept for backward compatibility")
open class PrecompiledSettingsScript(target: Settings) : SettingsScriptApi(target), Settings by target {

override val fileOperations by lazy { fileOperationsFor(delegate) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright 2019 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.gradle.kotlin.dsl.precompile.v1

import org.gradle.api.Project
import org.gradle.api.initialization.Settings
import org.gradle.api.invocation.Gradle
import org.gradle.kotlin.dsl.*
import org.gradle.kotlin.dsl.precompile.PrecompiledScriptDependenciesResolver
import org.gradle.plugin.use.PluginDependenciesSpec
import org.gradle.plugin.use.PluginDependencySpec
import org.jetbrains.kotlin.scripting.definitions.getEnvironment
import kotlin.script.dependencies.Environment
import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.ScriptConfigurationRefinementContext
import kotlin.script.experimental.api.asSuccess
import kotlin.script.experimental.api.baseClass
import kotlin.script.experimental.api.defaultImports
import kotlin.script.experimental.api.hostConfiguration
import kotlin.script.experimental.api.implicitReceivers
import kotlin.script.experimental.api.refineConfiguration
import kotlin.script.experimental.api.with
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.extensions.SamWithReceiverAnnotations
import kotlin.script.templates.ScriptTemplateDefinition


/**
* Script template definition for precompiled Kotlin script targeting [Gradle] instances.
*
* @see PrecompiledProjectScript
*/
@ScriptTemplateDefinition
@KotlinScript(
fileExtension = "init.gradle.kts",
compilationConfiguration = PrecompiledInitScriptCompilationConfiguration::class
)
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
open class PrecompiledInitScript(@Suppress("unused_parameter") target: Gradle)


/**
* Script template definition for precompiled Kotlin script targeting [Settings] instances.
*
* @see PrecompiledProjectScript
*/
@ScriptTemplateDefinition
@KotlinScript(
fileExtension = "settings.gradle.kts",
compilationConfiguration = PrecompiledSettingsScriptCompilationConfiguration::class
)
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
open class PrecompiledSettingsScript(@Suppress("unused_parameter") target: Settings)


/**
* Script template definition for precompiled Kotlin scripts targeting [Project] instances.
*
* A precompiled script is a script compiled as part of a regular Kotlin source-set and distributed
* in the usual way, java class files packaged in some library, meant to be consumed as a binary
* Gradle plugin.
*
* The Gradle plugin id by which the precompiled script can be referenced is derived from its name
* and package declaration - if any - in the following fashion:
*
* ```kotlin
* fun pluginIdFor(script: File, packageName: String?) =
* (packageName?.let { "$it." } ?: "") + script.nameWithoutExtension
* ```
*
* Thus, the script `src/main/kotlin/code-quality.gradle.kts` would be exposed as the `code-quality`
* plugin (assuming it has no package declaration) whereas the script
* `src/main/kotlin/gradlebuild/code-quality.gradle.kts` would be exposed as the `gradlebuild.code-quality`
* plugin, again assuming it has the matching package declaration.
*/
@ScriptTemplateDefinition
@KotlinScript(
fileExtension = "gradle.kts",
compilationConfiguration = PrecompiledProjectScriptCompilationConfiguration::class
)
@SamWithReceiverAnnotations("org.gradle.api.HasImplicitReceiver")
@GradleDsl
open class PrecompiledProjectScript(
private val target: Project
) {

/**
* Configures the build script classpath for this project.
*
* @see [Project.buildscript]
*/
@Suppress("unused")
open fun buildscript(@Suppress("unused_parameter") block: ScriptHandlerScope.() -> Unit) {
throw IllegalStateException("The `buildscript` block is not supported on Kotlin script plugins, please use the `plugins` block or project level dependencies.")
}

/**
* Configures the plugin dependencies for this project.
*
* @see [PluginDependenciesSpec]
*/
@Suppress("unused")
fun plugins(@Suppress("unused_parameter") block: PluginDependenciesSpec.() -> Unit) {
block(
PluginDependenciesSpec { pluginId ->
target.pluginManager.apply(pluginId)
NullPluginDependencySpec
})
}

object NullPluginDependencySpec : PluginDependencySpec {
override fun apply(apply: Boolean) = this
override fun version(version: String?) = this
}
}


object PrecompiledInitScriptCompilationConfiguration : ScriptCompilationConfiguration({
baseClass(PrecompiledInitScript::class)
implicitReceivers(Gradle::class)
setUpDefaultImports()
})


object PrecompiledSettingsScriptCompilationConfiguration : ScriptCompilationConfiguration({
baseClass(PrecompiledSettingsScript::class)
implicitReceivers(Settings::class)
setUpDefaultImports()
})


object PrecompiledProjectScriptCompilationConfiguration : ScriptCompilationConfiguration({
baseClass(PrecompiledProjectScript::class)
implicitReceivers(Project::class)
setUpDefaultImports()
})


private
fun ScriptCompilationConfiguration.Builder.setUpDefaultImports() {
refineConfiguration {
beforeCompiling { context ->
val environment = scriptResolverEnvironmentOf(context)
require(environment != null)
context.compilationConfiguration.with {
defaultImports(
PrecompiledScriptDependenciesResolver.implicitImportsForScript(
context.script.text,
environment
)
)
}.asSuccess()
}
}
}


private
fun scriptResolverEnvironmentOf(context: ScriptConfigurationRefinementContext): Environment? =
context
.compilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]
?.get(ScriptingHostConfiguration.getEnvironment)
?.invoke()

0 comments on commit 6279eda

Please sign in to comment.