diff --git a/.gitignore b/.gitignore
index ce181e5..4e67eeb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,27 @@
-.idea
+.kotlin
+.fleet
.gradle
-build
\ No newline at end of file
+
+# Build outputs
+build
+
+# Idea
+**/.idea/*
+!**/.idea/codeStyles
+!**/.idea/icon.png
+!**/.idea/runConfigurations
+!**/.idea/scopes
+!**/.idea/dictionaries
+*.iml
+
+# Place where the Android SDK path is set
+local.properties
+
+# XCode
+xcuserdata
+project.xcworkspace
+
+# Mac OS Finder
+.DS_Store
+Thumbs.db
+
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..aaa4877
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c937633..514c0f1 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Gratatouille is an opinionated framework to build Gradle plugins. Write pure Kotlin functions and the Gratatouille KSP processor generates tasks, workers, and wiring code for you.
-Gratatouille enforces a clear separation between your plugin logic (**implementation**) and your plugin wiring (**gradle-plugin**) making your plugin immune to [classloader issues](https://github.com/square/kotlinpoet/issues/1730#issuecomment-1819118527) 🛡️
+When used in classloader isolation mode, Gratatouille enforces a clear separation between your plugin logic (**implementation**) and your plugin wiring (**api**) making your plugin immune to [classloader issues](https://github.com/square/kotlinpoet/issues/1730#issuecomment-1819118527) 🛡️
**Key Features**:
@@ -10,37 +10,26 @@ Gratatouille enforces a clear separation between your plugin logic (**implementa
* [Kotlinx serialization support](#built-in-kotlinxserialization-support)
* [Comprehensive input/output types](#supported-input-and-output-types)
* [Non overlapping task outputs](#non-overlapping-task-outputs-by-default)
-* [Classloader isolation](#classloader-isolation-by-default)
* [Build cache](#build-cache-by-default)
* [Documentation](#easy-documentation)
* [Parallel execution](#parallel-task-execution-by-default)
* [Compile-time task wiring](#compile-time-task-wiring)
+* [Classloader isolation](#classloader-isolation-optional) (optional)
Check out the [sample-plugin](sample-plugin) and [sample-app](sample-app).
## Quick Start
-### Step 1/2: `com.gradleup.gratatouille.implementation`
-
-Create an `implementation` module for your plugin implementation and apply the `com.gradleup.gratatouille.implementation` plugin:
+Apply the `com.gradleup.gratatouille` plugin:
```kotlin
-// implementation/build.gradle.kts
plugins {
- id("com.gradleup.gratatouille.implementation").version("0.0.1")
-}
-
-dependencies {
- // Add the gratatouille annotations
- implementation("com.gradleup.gratatouille:gratatouille-core:0.0.1")
- // Add other dependencies
- implementation("com.squareup:kotlinpoet:1.14.2")
- implementation("org.ow2.asm:asm-commons:9.6")
- // do **not** add gradleApi() here
+ id("java-gradle-plugin")
+ id("com.gradleup.gratatouille").version("0.0.2")
}
```
-Write your task action as a pure top-level Kotlin function annotated with `@GTaskAction`:
+Define your task action using `@GTaskAction`:
```kotlin
@GTaskAction
@@ -65,35 +54,113 @@ Gratatouille automatically maps function parameters to Gradle inputs and the ret
Gratatouille generates entry points, tasks, workers and Gradle wiring code that you can then use to cook your plugin.
-### Step 2/2 `com.gradleup.gratatouille.plugin`
+
+Generated code
-To use the generated code in your plugin, create a `gradle-plugin` module next to your `implementation` module.
+```kotlin
+internal fun Project.registerPrepareIngredientsTask(
+ taskName: String = "prepareIngredients",
+ taskDescription: String? = null,
+ taskGroup: String? = null,
+ persons: Provider,
+): TaskProvider {
+ val configuration = this@registerPrepareIngredientsTask.configurations.detachedConfiguration()
+ configuration.dependencies.add(dependencies.create("sample-plugin:implementation:0.0.1"))
+ return tasks.register(taskName,PrepareIngredientsTask::class.java) {
+ it.description = taskDescription
+ it.group = taskGroup
+ it.classpath.from(configuration)
+ // infrastructure
+ // inputs
+ it.persons.set(persons)
+ // outputs
+ it.outputFile.set(this@registerPrepareIngredientsTask.layout.buildDirectory.file("gtask/${taskName}/outputFile"))
+ }
+}
-> [!IMPORTANT]
-> By using two different modules, Gratatouille ensures that Gradle classes do not leak in your plugin implementation and vice-versa.
+@CacheableTask
+internal abstract class PrepareIngredientsTask : DefaultTask() {
+ @get:InputFiles
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ public abstract val classpath: ConfigurableFileCollection
+
+ @get:Input
+ public abstract val persons: Property
+
+ @get:OutputFile
+ public abstract val outputFile: RegularFileProperty
+
+ @Inject
+ public abstract fun getWorkerExecutor(): WorkerExecutor
+
+ private fun T.isolate(): T {
+ @kotlin.Suppress("UNCHECKED_CAST")
+ when (this) {
+ is Set<*> -> {
+ return this.map { it.isolate() }.toSet() as T
+ }
+
+ is List<*> -> {
+ return this.map { it.isolate() } as T
+ }
+
+ is Map<*, *> -> {
+ return entries.map { it.key.isolate() to it.value.isolate() }.toMap() as T
+ }
+
+ else -> {
+ return this
+ }
+ }
+ }
+
+ @TaskAction
+ public fun taskAction() {
+ getWorkerExecutor().noIsolation().submit(PrepareIngredientsWorkAction::class.java) {
+ it.classpath = classpath.files.isolate()
+ it.persons = persons.get().isolate()
+ it.outputFile = outputFile.asFile.get().isolate()
+ }
+ }
+}
-Apply the `com.gradleup.gratatouille.plugin` plugin in your `gradle-plugin` module:
+private interface PrepareIngredientsWorkParameters : WorkParameters {
+ public var classpath: Set
-```kotlin
-// gradle-plugin/build.gradle.kts
-plugins {
- id("java-gradle-plugin")
- id("com.gradleup.gratatouille.plugin").version("0.0.1")
+ public var persons: Int
+
+ public var outputFile: File
}
-dependencies {
- // Add your implementation module to the "gratatouille" configuration.
- // This does not add `:implementation` to your plugin classpath.
- // Instead, the generated code uses reflection and a separate classloader to run
- // your implementation
- gratatouille(project(":implementation"))
+private abstract class PrepareIngredientsWorkAction : WorkAction {
+ override fun execute() {
+ with(parameters) {
+ URLClassLoader(
+ classpath.map { it.toURI().toURL() }.toTypedArray(),
+ ClassLoader.getPlatformClassLoader()
+ ).loadClass("recipes.PrepareIngredientsEntryPoint")
+ .declaredMethods.single()
+ .invoke(
+ null,
+ persons,
+ outputFile,
+ )
+ }
+ }
}
-// Create your plugin as usual, see https://docs.gradle.org/current/userguide/java_gradle_plugin.html
-gradlePlugin {
- // ...
+public class PrepareIngredientsEntryPoint {
+ public companion object {
+ @JvmStatic
+ public fun run(persons: Int, outputFile: File) {
+ prepareIngredients(
+ persons = persons,
+ ).encodeJsonTo(outputFile)
+ }
+ }
}
```
+
In your plugin code, use `Project.register${TaskAction}Task()` to register the task:
@@ -185,12 +252,6 @@ project.registerCookTask(
)
```
-### Classloader isolation by default
-
-Gratatouille creates a separate classloader for each task and calls your pure functions using reflection.
-
-This means your plugin can depend on popular dependencies such as the Kotlin stdlib, KotlinPoet or ASM without risking conflicts with other plugins or the Gradle classpath itself.
-
### Build cache by default
`@CacheableTask` is added by default. All input files use `PathSensitivity.RELATIVE` making your tasks relocatable.
@@ -227,3 +288,89 @@ Finally, Gratatouille encourages exposing extensions to users instead of task cl
When a task has a high number of inputs, it can become hard to track which ones have been wired and which ones haven't. By using a central registration point, Gratatouille enforces at build time that all inputs/outputs have been properly wired.
+## Classloader isolation (optional)
+
+Gradle uses [multiple classloaders](https://dev.to/autonomousapps/build-compile-run-a-crash-course-in-classpaths-f4g), and it's notoriously really hard to understand where a given class is loaded from.
+
+Especially, `buildSrc`/`build-logic` dependencies [leak in the main classpath](https://github.com/gradle/gradle/issues/4741) and override any dependencies from other plugin without conflict resolution. There are multiple workarounds such as declaring all plugins in `buildSrc` or in the top level `build.gradle[.kts]` file but the situation is confusing to Gradle newcomers and hard to debug.
+
+To guard against those issues, Gratatouille provides a "classloader isolation" mode where your task actions use a separate classloader.
+
+This means your plugin can depend on popular dependencies such as the Kotlin stdlib, KotlinPoet or ASM without risking conflicts with other plugins or the Gradle classpath itself.
+
+For classloader isolation to work, your plugin needs 2 modules:
+* The **implementation** module is where the task actions are defined and the work is done. This module can add dependencies.
+* The **api** module contains the glue code and Gradle API that calls the **implementation** module through reflection. This module must not add dependencies.
+
+### Step 1/2: `com.gradleup.gratatouille.implementation`
+
+Create an `implementation` module for your plugin implementation and apply the `com.gradleup.gratatouille.implementation` plugin:
+
+```kotlin
+// implementation/build.gradle.kts
+plugins {
+ id("com.gradleup.gratatouille.implementation").version("0.0.1")
+}
+
+dependencies {
+ // Add other dependencies
+ implementation("com.squareup:kotlinpoet:1.14.2")
+ implementation("org.ow2.asm:asm-commons:9.6")
+ // do **not** add gradleApi() here
+}
+```
+
+Write your task action as a pure top-level Kotlin function annotated with `@GTaskAction`:
+
+```kotlin
+@GTaskAction
+internal fun prepareIngredients(persons: Int): Ingredients {
+ return Ingredients(
+ tomatoes = (persons * 0.75).roundToInt(),
+ zucchinis = (persons * 0.3).roundToInt(),
+ eggplants = (persons * 0.3).roundToInt(),
+ )
+}
+
+// kotlinx.serialization is supported out of the box
+@Serializable
+internal data class Ingredients(
+ val tomatoes: Int,
+ val zucchinis: Int,
+ val eggplants: Int,
+)
+```
+
+When using this mode, the plugin wiring code is generated as resources that are included by the `com.gradleup.gratatouille.api` plugin.
+
+### Step 2/2 `com.gradleup.gratatouille.plugin`
+
+To use the generated code in your plugin, create an `api` module next to your `implementation` module.
+
+> [!IMPORTANT]
+> By using two different modules, Gratatouille ensures that Gradle classes do not leak in your plugin implementation and vice-versa.
+
+Apply the `com.gradleup.gratatouille.api` plugin in your `api` module:
+
+```kotlin
+// gradle-plugin/build.gradle.kts
+plugins {
+ id("java-gradle-plugin")
+ id("com.gradleup.gratatouille.api").version("0.0.1")
+}
+
+dependencies {
+ // Add your implementation module to the "gratatouille" configuration.
+ // This does not add `:implementation` to your plugin classpath.
+ // Instead, the generated code uses reflection and a separate classloader to run
+ // your implementation
+ gratatouille(project(":implementation"))
+}
+
+// Create your plugin as usual, see https://docs.gradle.org/current/userguide/java_gradle_plugin.html
+gradlePlugin {
+ // ...
+}
+```
+
+In your plugin code, use `Project.register${TaskAction}Task()` to register the task
diff --git a/build-logic/.idea/codeStyles b/build-logic/.idea/codeStyles
new file mode 120000
index 0000000..70d0521
--- /dev/null
+++ b/build-logic/.idea/codeStyles
@@ -0,0 +1 @@
+../../.idea/codeStyles
\ No newline at end of file
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index ebaee29..47f371c 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -1,5 +1,8 @@
+import com.gradleup.librarian.gradle.configureJavaCompatibility
+
plugins {
`embedded-kotlin`
+ alias(libs.plugins.librarian).apply(false)
}
dependencies {
@@ -13,3 +16,9 @@ dependencies {
}
group = "build-logic"
+
+/**
+ * Ideally would use Runtime.version().feature() but the current Gradle still ships with Kotlin 1.9
+ * that doesn't know about Java 22 🤷♂️
+ */
+configureJavaCompatibility(17)
diff --git a/build-logic/gradle/wrapper b/build-logic/gradle/wrapper
new file mode 120000
index 0000000..3232fe4
--- /dev/null
+++ b/build-logic/gradle/wrapper
@@ -0,0 +1 @@
+../../gradle/wrapper
\ No newline at end of file
diff --git a/build-logic/gradle/wrapper/gradle-wrapper.jar b/build-logic/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 7f93135..0000000
Binary files a/build-logic/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/build-logic/gradle/wrapper/gradle-wrapper.properties b/build-logic/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 3fa8f86..0000000
--- a/build-logic/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/build-logic/gradlew b/build-logic/gradlew
deleted file mode 100755
index 1aa94a4..0000000
--- a/build-logic/gradlew
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original 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
-#
-# https://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.
-#
-
-##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh Gradle
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-# This is normally unused
-# shellcheck disable=SC2034
-APP_BASE_NAME=${0##*/}
-# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- if ! command -v java >/dev/null 2>&1
- then
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
-# and any embedded shellness will be escaped.
-# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
-# treated as '${Hostname}' itself on the command line.
-
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
-
-# Stop when "xargs" is not available.
-if ! command -v xargs >/dev/null 2>&1
-then
- die "xargs is not available"
-fi
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/build-logic/gradlew b/build-logic/gradlew
new file mode 120000
index 0000000..502f5a2
--- /dev/null
+++ b/build-logic/gradlew
@@ -0,0 +1 @@
+../gradlew
\ No newline at end of file
diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat
deleted file mode 100644
index 6689b85..0000000
--- a/build-logic/gradlew.bat
+++ /dev/null
@@ -1,92 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%"=="" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat
new file mode 120000
index 0000000..2840132
--- /dev/null
+++ b/build-logic/gradlew.bat
@@ -0,0 +1 @@
+../gradlew.bat
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a80b22c..9355b41 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gratatouille-gradle-plugin/build.gradle.kts b/gratatouille-gradle-plugin/build.gradle.kts
index 05d91bd..de9835e 100644
--- a/gratatouille-gradle-plugin/build.gradle.kts
+++ b/gratatouille-gradle-plugin/build.gradle.kts
@@ -28,9 +28,13 @@ gradlePlugin {
this.implementationClass = "gratatouille.gradle.GratatouilleImplementationPlugin"
this.id = "com.gradleup.gratatouille.implementation"
}
- create("com.gradleup.gratatouille.plugin") {
- this.implementationClass = "gratatouille.gradle.GratatouilleGradlePluginPlugin"
- this.id = "com.gradleup.gratatouille.plugin"
+ create("com.gradleup.gratatouille.api") {
+ this.implementationClass = "gratatouille.gradle.GratatouilleApiPlugin"
+ this.id = "com.gradleup.gratatouille.api"
+ }
+ create("com.gradleup.gratatouille") {
+ this.implementationClass = "gratatouille.gradle.GratatouillePlugin"
+ this.id = "com.gradleup.gratatouille"
}
}
-}
\ No newline at end of file
+}
diff --git a/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleGradlePluginPlugin.kt b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleApiPlugin.kt
similarity index 96%
rename from gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleGradlePluginPlugin.kt
rename to gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleApiPlugin.kt
index 5da6138..dad49af 100644
--- a/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleGradlePluginPlugin.kt
+++ b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleApiPlugin.kt
@@ -7,7 +7,7 @@ import org.gradle.api.tasks.Copy
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import javax.inject.Inject
-class GratatouilleGradlePluginPlugin : Plugin {
+class GratatouilleApiPlugin : Plugin {
override fun apply(target: Project) {
target.configurations.create("gratatouille") {
it.isTransitive = false
diff --git a/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleImplementationPlugin.kt b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleImplementationPlugin.kt
index 0d08fbf..b937da3 100644
--- a/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleImplementationPlugin.kt
+++ b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouilleImplementationPlugin.kt
@@ -19,7 +19,7 @@ class GratatouilleImplementationPlugin : Plugin {
target.afterEvaluate {
target.extensions.getByName("ksp").apply {
this as KspExtension
- this.arg("gratatouilleCoordinates", "${target.group}:${target.name}:${target.version}")
+ this.arg("implementationCoordinates", "${target.group}:${target.name}:${target.version}")
}
}
}
diff --git a/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouillePlugin.kt b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouillePlugin.kt
new file mode 100644
index 0000000..ebd9b35
--- /dev/null
+++ b/gratatouille-gradle-plugin/src/main/kotlin/gratatouille/gradle/GratatouillePlugin.kt
@@ -0,0 +1,19 @@
+package gratatouille.gradle
+
+import com.gradleup.gratatouille.gradle.BuildConfig
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class GratatouillePlugin : Plugin {
+ override fun apply(target: Project) {
+ target.withPlugins("org.jetbrains.kotlin.jvm", "com.google.devtools.ksp") {
+ target.configurations.getByName("ksp").dependencies.add(
+ target.dependencies.create("${BuildConfig.group}:gratatouille-processor:${BuildConfig.version}")
+ )
+ target.configurations.getByName("implementation").dependencies.add(
+ target.dependencies.create("${BuildConfig.group}:gratatouille-core:${BuildConfig.version}")
+ )
+ }
+ }
+}
+
diff --git a/gratatouille-processor/src/main/kotlin/gratatouille/processor/GraskAction.kt b/gratatouille-processor/src/main/kotlin/gratatouille/processor/GTaskAction.kt
similarity index 91%
rename from gratatouille-processor/src/main/kotlin/gratatouille/processor/GraskAction.kt
rename to gratatouille-processor/src/main/kotlin/gratatouille/processor/GTaskAction.kt
index 692b4df..29396f9 100644
--- a/gratatouille-processor/src/main/kotlin/gratatouille/processor/GraskAction.kt
+++ b/gratatouille-processor/src/main/kotlin/gratatouille/processor/GTaskAction.kt
@@ -19,7 +19,12 @@ internal class GTaskAction(
val description: String?,
val group: String?,
val parameters: List,
- val returnValues: List
+ val returnValues: List,
+ /**
+ * The coordinates where to find the implementation for this action
+ * May be null if the plugin is not isolated
+ */
+ val implementationCoordinates: String?
)
internal sealed interface Type
@@ -42,10 +47,10 @@ internal class Property(
)
-internal fun KSFunctionDeclaration.toGTaskAction(): GTaskAction {
+internal fun KSFunctionDeclaration.toGTaskAction(implementationCoordinates: String?): GTaskAction {
val parameters = mutableListOf()
val returnValues = returnType.toReturnValues()
- val reservedNames = setOf(taskName, taskDescription, taskGroup, classpath, extraClasspath, workerExecutor)
+ val reservedNames = setOf(taskName, taskDescription, taskGroup, classpath, workerExecutor)
val returnValuesNames = returnValues.map { it.name }.toSet()
this.parameters.forEach { valueParameter ->
@@ -116,12 +121,12 @@ internal fun KSFunctionDeclaration.toGTaskAction(): GTaskAction {
)
}
- val GTaskActionAnnotation = annotations.first { it.shortName.asString() == "GTaskAction" }
- val name = GTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "name" }
+ val gTaskActionAnnotation = annotations.first { it.shortName.asString() == "GTaskAction" }
+ val name = gTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "name" }
?.takeIf { it.origin != Origin.SYNTHETIC }?.value?.toString()
- val description = GTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "description" }
+ val description = gTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "description" }
?.takeIf { it.origin != Origin.SYNTHETIC }?.value?.toString()
- val group = GTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "group" }
+ val group = gTaskActionAnnotation.arguments.firstOrNull { it.name?.asString() == "group" }
?.takeIf { it.origin != Origin.SYNTHETIC }?.value?.toString()
return GTaskAction(
@@ -131,7 +136,8 @@ internal fun KSFunctionDeclaration.toGTaskAction(): GTaskAction {
returnValues = returnValues,
annotationName = name,
description = description,
- group = group
+ group = group,
+ implementationCoordinates = implementationCoordinates
)
}
diff --git a/gratatouille-processor/src/main/kotlin/gratatouille/processor/GratatouilleProcessor.kt b/gratatouille-processor/src/main/kotlin/gratatouille/processor/GratatouilleProcessor.kt
index b656c92..be2b3d4 100644
--- a/gratatouille-processor/src/main/kotlin/gratatouille/processor/GratatouilleProcessor.kt
+++ b/gratatouille-processor/src/main/kotlin/gratatouille/processor/GratatouilleProcessor.kt
@@ -6,50 +6,59 @@ import com.google.devtools.ksp.symbol.KSFunctionDeclaration
import com.squareup.kotlinpoet.ksp.writeTo
class GratatouilleProcessor(
- private val codeGenerator: CodeGenerator,
- private val logger: KSPLogger,
- private val options: Map,
+ private val codeGenerator: CodeGenerator,
+ private val logger: KSPLogger,
+ private val options: Map,
) : SymbolProcessor {
- override fun process(resolver: Resolver): List {
- val symbols = resolver.getSymbolsWithAnnotation("gratatouille.GTaskAction")
+ override fun process(resolver: Resolver): List {
+ val symbols = resolver.getSymbolsWithAnnotation("gratatouille.GTaskAction")
- val coordinates = options.get("gratatouilleCoordinates") ?: error("Gratatouille requires coordinates of the implementation module")
- symbols.forEach {
- when (it) {
- is KSFunctionDeclaration -> {
- it.toGTaskAction().apply {
- entryPoint().writeTo(codeGenerator, Dependencies.ALL_FILES)
+ val coordinates = options.get("implementationCoordinates")
+ symbols.forEach {
+ when (it) {
+ is KSFunctionDeclaration -> {
+ it.toGTaskAction(coordinates).apply {
+ entryPoint().writeTo(codeGenerator, Dependencies.ALL_FILES)
- taskFile(coordinates).let { fileSpec ->
- codeGenerator.createNewFile(
- Dependencies.ALL_FILES,
- "",
- "META-INF/gratatouille/${fileSpec.packageName.replace(".", "/")}/${fileSpec.name}.kt",
- ""
- ).writer().use {
- fileSpec.writeTo(it)
- }
- }
- }
- }
-
- else -> error("@GTaskAction is only valid on functions")
+ taskFile().let { fileSpec ->
+ val file = if (implementationCoordinates != null) {
+ codeGenerator.createNewFile(
+ Dependencies.ALL_FILES,
+ "",
+ "META-INF/gratatouille/${fileSpec.packageName.replace(".", "/")}/${fileSpec.name}.kt",
+ ""
+ )
+ } else {
+ codeGenerator.createNewFile(
+ Dependencies.ALL_FILES,
+ fileSpec.packageName,
+ fileSpec.name,
+ )
+ }
+ file.writer().use {
+ fileSpec.writeTo(it)
+ }
}
+ }
}
- return emptyList()
+
+ else -> error("@GTaskAction is only valid on functions")
+ }
}
+ return emptyList()
+ }
}
class GratatouilleProcessorProvider : SymbolProcessorProvider {
- override fun create(
- environment: SymbolProcessorEnvironment
- ): SymbolProcessor {
- return GratatouilleProcessor(
- environment.codeGenerator,
- environment.logger,
- environment.options
- )
- }
+ override fun create(
+ environment: SymbolProcessorEnvironment
+ ): SymbolProcessor {
+ return GratatouilleProcessor(
+ environment.codeGenerator,
+ environment.logger,
+ environment.options
+ )
+ }
}
internal val classpathProperty = Property(InputFiles, classpath, false, false, false)
\ No newline at end of file
diff --git a/gratatouille-processor/src/main/kotlin/gratatouille/processor/Task.kt b/gratatouille-processor/src/main/kotlin/gratatouille/processor/Task.kt
index e6d8531..115407b 100644
--- a/gratatouille-processor/src/main/kotlin/gratatouille/processor/Task.kt
+++ b/gratatouille-processor/src/main/kotlin/gratatouille/processor/Task.kt
@@ -1,199 +1,172 @@
package gratatouille.processor
-import com.squareup.kotlinpoet.AnnotationSpec
-import com.squareup.kotlinpoet.ClassName
-import com.squareup.kotlinpoet.CodeBlock
-import com.squareup.kotlinpoet.FileSpec
-import com.squareup.kotlinpoet.FunSpec
-import com.squareup.kotlinpoet.KModifier
-import com.squareup.kotlinpoet.ParameterSpec
-import com.squareup.kotlinpoet.ParameterizedTypeName
+import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
-import com.squareup.kotlinpoet.PropertySpec
-import com.squareup.kotlinpoet.TypeName
-import com.squareup.kotlinpoet.TypeSpec
-import com.squareup.kotlinpoet.TypeVariableName
-
-internal fun GTaskAction.taskFile(coordinates: String): FileSpec {
- val className = taskClassName()
-
- val fileSpec = FileSpec.builder(className)
- .addFunction(register(coordinates))
- .addType(task())
- .addType(workParameters())
- .addType(workAction())
- .build()
- return fileSpec
+internal fun GTaskAction.taskFile(): FileSpec {
+ val className = taskClassName()
+
+ val fileSpec = FileSpec.builder(className)
+ .addFunction(register())
+ .addType(task())
+ .addType(workParameters())
+ .addType(workAction())
+ .build()
+
+ return fileSpec
}
-private fun GTaskAction.register(coordinates: String): FunSpec {
- val defaultTaskName = annotationName ?: taskName()
- return FunSpec.builder(registerName())
- .addModifiers(KModifier.INTERNAL)
- .receiver(ClassName("org.gradle.api", "Project"))
- .returns(ClassName("org.gradle.api.tasks", "TaskProvider").parameterizedBy(taskClassName()))
- .addParameter(
- ParameterSpec.builder(taskName, ClassName("kotlin", "String"))
- .defaultValue(defaultTaskName.toCodeBlock())
- .build()
- )
- .addParameter(
- ParameterSpec.builder(taskDescription, ClassName("kotlin", "String").copy(nullable = true))
- .defaultValue(description.toCodeBlock())
- .build()
- )
- .addParameter(
- ParameterSpec.builder(taskGroup, ClassName("kotlin", "String").copy(nullable = true))
- .defaultValue(group.toCodeBlock())
- .build()
+private fun GTaskAction.register(): FunSpec {
+ val defaultTaskName = annotationName ?: taskName()
+ return FunSpec.builder(registerName())
+ .addModifiers(KModifier.INTERNAL)
+ .receiver(ClassName("org.gradle.api", "Project"))
+ .returns(ClassName("org.gradle.api.tasks", "TaskProvider").parameterizedBy(taskClassName()))
+ .addParameter(
+ ParameterSpec.builder(taskName, ClassName("kotlin", "String"))
+ .defaultValue(defaultTaskName.toCodeBlock())
+ .build()
+ )
+ .addParameter(
+ ParameterSpec.builder(taskDescription, ClassName("kotlin", "String").copy(nullable = true))
+ .defaultValue(description.toCodeBlock())
+ .build()
+ )
+ .addParameter(
+ ParameterSpec.builder(taskGroup, ClassName("kotlin", "String").copy(nullable = true))
+ .defaultValue(group.toCodeBlock())
+ .build()
+ )
+ .apply {
+ this@register.parameters.filter { it.type.isInput() }.forEach {
+
+ addParameter(
+ ParameterSpec.builder(it.name, it.type.toProviderType())
+ .build()
)
- .addParameter(
- ParameterSpec.builder(
- extraClasspath,
- ClassName("org.gradle.api.file", "FileCollection").copy(nullable = true)
- )
- .defaultValue(CodeBlock.of("null"))
- .build()
+ }
+
+ (this@register.parameters.filter { !it.type.isInput() } + this@register.returnValues).forEach {
+ if (it.manuallyWired) {
+ addParameter(
+ ParameterSpec.builder(it.name, it.type.toProviderType())
+ .build()
+ )
+ }
+ }
+ }
+ .addCode(
+ buildCodeBlock {
+ add(
+ "val configuration = this@%L.configurations.detachedConfiguration()\n",
+ registerName(),
)
- .apply {
- this@register.parameters.filter { it.type.isInput() }.forEach {
-
- addParameter(
- ParameterSpec.builder(it.name, it.type.toProviderType())
- .build()
- )
+ if (implementationCoordinates != null) {
+ add("configuration.dependencies.add(dependencies.create(%S))\n", implementationCoordinates)
+ }
+ add("return tasks.register($taskName,%T::class.java) {\n", taskClassName())
+ withIndent {
+ add("it.description = $taskDescription\n")
+ add("it.group = $taskGroup\n")
+ add("it.$classpath.from(configuration)\n")
+ add("// infrastructure\n")
+ add("// inputs\n")
+ this@register.parameters.filter { it.type.isInput() }.forEach {
+ when (it.type) {
+ is InputFiles -> {
+ add("it.%L.from(%L)\n", it.name, it.name)
+ }
+
+ else -> {
+ add("it.%L.set(%L)\n", it.name, it.name)
+ }
}
-
- (this@register.parameters.filter { !it.type.isInput() } + this@register.returnValues).forEach {
- if (it.manuallyWired) {
- addParameter(
- ParameterSpec.builder(it.name, it.type.toProviderType())
- .build()
- )
- }
+ }
+
+ add("// outputs\n")
+ (this@register.parameters.filter { !it.type.isInput() } + this@register.returnValues).forEach {
+ if (it.manuallyWired) {
+ add("it.%L.set(%L)\n", it.name, it.name)
+ } else {
+ val method = when (it.type) {
+ is OutputDirectory -> "dir"
+ is KotlinxSerializableOutput, is OutputFile -> "file"
+ else -> error("Gratatouille: invalid output type for '${it.name}': ${it.type}")
+ }
+ add(
+ "it.%L.set(this@%L.layout.buildDirectory.$method(%L))\n",
+ it.name,
+ registerName(),
+ "\"gtask/\${$taskName}/${it.name}\""
+ )
}
+ }
}
- .addCode(
- CodeBlock.builder()
- .add(
- "val configuration = this@%L.configurations.detachedConfiguration(dependencies.create(%S))\n",
- registerName(),
- coordinates
- )
- .add("return tasks.register($taskName,%T::class.java) {\n", taskClassName())
- .indent()
- .add("it.description = $taskDescription\n")
- .add("it.group = $taskGroup\n")
- .add("it.$classpath.from(configuration)\n")
- .apply {
- add("// infrastructure\n")
- add("if ($extraClasspath != null) {\n")
- indent()
- add("it.$classpath.from($extraClasspath)\n")
- unindent()
- add("}\n")
- }
- .apply {
- add("// inputs\n")
- this@register.parameters.filter { it.type.isInput() }.forEach {
- when (it.type) {
- is InputFiles -> {
- add("it.%L.from(%L)\n", it.name, it.name)
- }
-
- else -> {
- add("it.%L.set(%L)\n", it.name, it.name)
- }
- }
- }
- }
- .apply {
- add("// outputs\n")
- (this@register.parameters.filter { !it.type.isInput() } + this@register.returnValues).forEach {
- if (it.manuallyWired) {
- add("it.%L.set(%L)\n", it.name, it.name)
- } else {
- val method = when (it.type) {
- is OutputDirectory -> "dir"
- is KotlinxSerializableOutput, is OutputFile -> "file"
- else -> error("Gratatouille: invalid output type for '${it.name}': ${it.type}")
- }
- add(
- "it.%L.set(this@%L.layout.buildDirectory.$method(%L))\n",
- it.name,
- registerName(),
- "\"gtask/\${$taskName}/${it.name}\""
- )
- }
- }
- }
- .unindent()
- .add("}\n")
- .build()
- )
- .build()
+ add("}\n")
+ }
+ )
+ .build()
}
private fun Type.isInput(): Boolean {
- return when (this) {
- is OutputDirectory, is OutputFile -> false
- else -> true
- }
+ return when (this) {
+ is OutputDirectory, is OutputFile -> false
+ else -> true
+ }
}
private fun Type.toProviderType(): TypeName {
- return when (this) {
- is OutputDirectory, InputDirectory -> ClassName("org.gradle.api.provider", "Provider")
- .parameterizedBy(ClassName("org.gradle.api.file", "Directory"))
-
- is KotlinxSerializableInput, is KotlinxSerializableOutput, is OutputFile, InputFile -> ClassName(
- "org.gradle.api.provider",
- "Provider"
- )
- .parameterizedBy(ClassName("org.gradle.api.file", "RegularFile"))
-
- InputFiles -> ClassName("org.gradle.api.file", "FileCollection")
- is JvmType -> typename.toGradleProvider()
- }
+ return when (this) {
+ is OutputDirectory, InputDirectory -> ClassName("org.gradle.api.provider", "Provider")
+ .parameterizedBy(ClassName("org.gradle.api.file", "Directory"))
+
+ is KotlinxSerializableInput, is KotlinxSerializableOutput, is OutputFile, InputFile -> ClassName(
+ "org.gradle.api.provider",
+ "Provider"
+ )
+ .parameterizedBy(ClassName("org.gradle.api.file", "RegularFile"))
+
+ InputFiles -> ClassName("org.gradle.api.file", "FileCollection")
+ is JvmType -> typename.toGradleProvider()
+ }
}
private fun GTaskAction.task(): TypeSpec {
- return TypeSpec.classBuilder(taskClassName().simpleName)
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "CacheableTask"))
- .build()
+ return TypeSpec.classBuilder(taskClassName().simpleName)
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "CacheableTask"))
+ .build()
+ )
+ .addModifiers(KModifier.ABSTRACT, KModifier.INTERNAL)
+ .superclass(ClassName("org.gradle.api", "DefaultTask"))
+ .apply {
+ (listOf(classpathProperty) + parameters + returnValues).forEach {
+ addProperty(
+ it.toPropertySpec()
)
- .addModifiers(KModifier.ABSTRACT, KModifier.INTERNAL)
- .superclass(ClassName("org.gradle.api", "DefaultTask"))
- .apply {
- (listOf(classpathProperty) + parameters + returnValues).forEach {
- addProperty(
- it.toPropertySpec()
- )
- }
- }
- .addFunction(
- FunSpec.builder(workerExecutor)
- .addModifiers(KModifier.ABSTRACT)
- .addAnnotation(
- AnnotationSpec.builder(ClassName("javax.inject", "Inject")).build()
- )
- .returns(ClassName("org.gradle.workers", "WorkerExecutor"))
- .build()
+ }
+ }
+ .addFunction(
+ FunSpec.builder(workerExecutor)
+ .addModifiers(KModifier.ABSTRACT)
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("javax.inject", "Inject")).build()
)
- .addFunction(isolate())
- .addFunction(taskAction())
+ .returns(ClassName("org.gradle.workers", "WorkerExecutor"))
.build()
+ )
+ .addFunction(isolate())
+ .addFunction(taskAction())
+ .build()
}
private fun isolate(): FunSpec {
- return FunSpec.builder("isolate")
- .addTypeVariable(TypeVariableName("T"))
- .receiver(TypeVariableName("T"))
- .returns(TypeVariableName("T"))
- .addCode(
- """
+ return FunSpec.builder("isolate")
+ .addTypeVariable(TypeVariableName("T"))
+ .receiver(TypeVariableName("T"))
+ .returns(TypeVariableName("T"))
+ .addCode(
+ """
@kotlin.Suppress("UNCHECKED_CAST")
when (this) {
is Set<*> -> {
@@ -213,254 +186,263 @@ private fun isolate(): FunSpec {
}
}
""".trimIndent()
- )
- .addModifiers(KModifier.PRIVATE)
- .build()
+ )
+ .addModifiers(KModifier.PRIVATE)
+ .build()
}
private fun GTaskAction.taskAction(): FunSpec {
- return FunSpec.builder("taskAction")
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "TaskAction"))
- .build()
- )
- .addCode(
- CodeBlock.builder()
- .add("$workerExecutor().noIsolation().submit(%T::class.java) {\n", workActionClassName())
- .indent()
- .apply {
- (listOf(classpathProperty) + parameters + returnValues).forEach {
- val extra = CodeBlock.builder()
- .apply {
- when (it.type) {
- InputDirectory,
- InputFile,
- is KotlinxSerializableInput,
- is KotlinxSerializableOutput,
- is OutputDirectory,
- is OutputFile
- -> {
- add(".asFile")
- }
-
- InputFiles -> {
- add(".files")
- }
-
- else -> Unit
- }
- if (it.type !is InputFiles) {
- if (it.optional) {
- add(".orNull?")
- } else {
- add(".get()")
- }
- }
- add(".isolate()")
- }
- .build()
- add("it.%L = %L%L\n", it.name, it.name, extra)
- }
+ return FunSpec.builder("taskAction")
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "TaskAction"))
+ .build()
+ )
+ .addCode(
+ CodeBlock.builder()
+ .add("$workerExecutor().noIsolation().submit(%T::class.java) {\n", workActionClassName())
+ .indent()
+ .apply {
+ (listOf(classpathProperty) + parameters + returnValues).forEach {
+ val extra = CodeBlock.builder()
+ .apply {
+ when (it.type) {
+ InputDirectory,
+ InputFile,
+ is KotlinxSerializableInput,
+ is KotlinxSerializableOutput,
+ is OutputDirectory,
+ is OutputFile
+ -> {
+ add(".asFile")
+ }
+
+ InputFiles -> {
+ add(".files")
+ }
+
+ else -> Unit
}
- .unindent()
- .add("}\n")
- .build()
- )
+ if (it.type !is InputFiles) {
+ if (it.optional) {
+ add(".orNull?")
+ } else {
+ add(".get()")
+ }
+ }
+ add(".isolate()")
+ }
+ .build()
+ add("it.%L = %L%L\n", it.name, it.name, extra)
+ }
+ }
+ .unindent()
+ .add("}\n")
.build()
+ )
+ .build()
}
private fun PropertySpec.Builder.annotateInput(
- packageName: String,
- simpleName: String,
- internal: Boolean,
- optional: Boolean
+ packageName: String,
+ simpleName: String,
+ internal: Boolean,
+ optional: Boolean
) = apply {
- if (internal) {
- addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "Internal"))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- } else {
- if (optional) {
- addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "Optional"))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
- addAnnotation(
- AnnotationSpec.builder(ClassName(packageName, simpleName))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
+ if (internal) {
+ addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "Internal"))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ } else {
+ if (optional) {
+ addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "Optional"))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
}
+ addAnnotation(
+ AnnotationSpec.builder(ClassName(packageName, simpleName))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ }
}
private fun Property.toPropertySpec(): PropertySpec {
- val builder = when (type) {
- is InputDirectory -> {
- PropertySpec.builder(name, ClassName("org.gradle.api.file", "DirectoryProperty"))
- .annotateInput("org.gradle.api.tasks", "InputDirectory", internal, optional)
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
- .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
+ val builder = when (type) {
+ is InputDirectory -> {
+ PropertySpec.builder(name, ClassName("org.gradle.api.file", "DirectoryProperty"))
+ .annotateInput("org.gradle.api.tasks", "InputDirectory", internal, optional)
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
+ .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ }
- is KotlinxSerializableInput, is InputFile -> {
- PropertySpec.builder(name, ClassName("org.gradle.api.file", "RegularFileProperty"))
- .annotateInput("org.gradle.api.tasks", "InputFile", internal, optional)
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
- .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
+ is KotlinxSerializableInput, is InputFile -> {
+ PropertySpec.builder(name, ClassName("org.gradle.api.file", "RegularFileProperty"))
+ .annotateInput("org.gradle.api.tasks", "InputFile", internal, optional)
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
+ .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ }
- is InputFiles -> {
- PropertySpec.builder(name, ClassName("org.gradle.api.file", "ConfigurableFileCollection"))
- .annotateInput("org.gradle.api.tasks", "InputFiles", internal, optional)
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
- .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
+ is InputFiles -> {
+ PropertySpec.builder(name, ClassName("org.gradle.api.file", "ConfigurableFileCollection"))
+ .annotateInput("org.gradle.api.tasks", "InputFiles", internal, optional)
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "PathSensitive"))
+ .addMember(CodeBlock.of("%T.RELATIVE", ClassName("org.gradle.api.tasks", "PathSensitivity")))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ }
- is JvmType -> {
- PropertySpec.builder(name, type.typename.toGradleProperty())
- .annotateInput("org.gradle.api.tasks", "Input", internal, optional)
- }
+ is JvmType -> {
+ PropertySpec.builder(name, type.typename.toGradleProperty())
+ .annotateInput("org.gradle.api.tasks", "Input", internal, optional)
+ }
- is OutputDirectory -> {
- PropertySpec.builder(name, ClassName("org.gradle.api.file", "DirectoryProperty"))
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "OutputDirectory"))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
+ is OutputDirectory -> {
+ PropertySpec.builder(name, ClassName("org.gradle.api.file", "DirectoryProperty"))
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "OutputDirectory"))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
+ }
- is KotlinxSerializableOutput, is OutputFile -> {
- PropertySpec.builder(name, ClassName("org.gradle.api.file", "RegularFileProperty"))
- .addAnnotation(
- AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "OutputFile"))
- .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
- .build()
- )
- }
+ is KotlinxSerializableOutput, is OutputFile -> {
+ PropertySpec.builder(name, ClassName("org.gradle.api.file", "RegularFileProperty"))
+ .addAnnotation(
+ AnnotationSpec.builder(ClassName("org.gradle.api.tasks", "OutputFile"))
+ .useSiteTarget(AnnotationSpec.UseSiteTarget.GET)
+ .build()
+ )
}
+ }
- return builder.addModifiers(KModifier.ABSTRACT).build()
+ return builder.addModifiers(KModifier.ABSTRACT).build()
}
private fun TypeName.toGradleProperty(): TypeName {
- return when {
- this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "Map") -> {
- ClassName("org.gradle.api.provider", "MapProperty").parameterizedBy(this.typeArguments)
- }
-
- this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "List") -> {
- ClassName("org.gradle.api.provider", "ListProperty").parameterizedBy(this.typeArguments)
- }
+ return when {
+ this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "Map") -> {
+ ClassName("org.gradle.api.provider", "MapProperty").parameterizedBy(this.typeArguments)
+ }
- this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "Set") -> {
- ClassName("org.gradle.api.provider", "SetProperty").parameterizedBy(this.typeArguments)
- }
+ this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "List") -> {
+ ClassName("org.gradle.api.provider", "ListProperty").parameterizedBy(this.typeArguments)
+ }
- this is ClassName -> ClassName("org.gradle.api.provider", "Property").parameterizedBy(this)
- else -> error("Gratatouille: cannot convert '$this' to a Gradle property")
+ this is ParameterizedTypeName && this.rawType == ClassName("kotlin.collections", "Set") -> {
+ ClassName("org.gradle.api.provider", "SetProperty").parameterizedBy(this.typeArguments)
}
+
+ this is ClassName -> ClassName("org.gradle.api.provider", "Property").parameterizedBy(this)
+ else -> error("Gratatouille: cannot convert '$this' to a Gradle property")
+ }
}
private fun TypeName.toGradleProvider(): TypeName {
- return ClassName("org.gradle.api.provider", "Provider").parameterizedBy(this)
+ return ClassName("org.gradle.api.provider", "Provider").parameterizedBy(this)
}
private fun GTaskAction.workAction(): TypeSpec {
- return TypeSpec.classBuilder(workActionClassName().simpleName)
- .addModifiers(KModifier.PRIVATE, KModifier.ABSTRACT)
- .addSuperinterface(ClassName("org.gradle.workers", "WorkAction").parameterizedBy(workParametersClassName()))
- .addFunction(workActionExecute())
+ return TypeSpec.classBuilder(workActionClassName().simpleName)
+ .addModifiers(KModifier.PRIVATE, KModifier.ABSTRACT)
+ .addSuperinterface(ClassName("org.gradle.workers", "WorkAction").parameterizedBy(workParametersClassName()))
+ .addFunction(workActionExecute())
- .build()
+ .build()
}
private fun GTaskAction.workActionExecute(): FunSpec {
- return FunSpec.builder("execute")
- .addModifiers(KModifier.OVERRIDE)
- .addCode(CodeBlock.builder()
- .add("with(parameters) {\n")
- .indent()
- .add("%T(\n", ClassName("java.net", "URLClassLoader"))
- .indent()
- .add("$classpath.map { it.toURI().toURL() }.toTypedArray(),\n")
- .add("%T.getPlatformClassLoader()\n", ClassName("java.lang", "ClassLoader"))
- .unindent()
- .add(")")
- .add(".loadClass(%S)\n", entryPointClassName().canonicalName)
- .add(".declaredMethods.single()\n")
- .add(".invoke(\n")
- .indent()
- .add("null,\n")
- .apply {
- (parameters + returnValues).forEach {
- add("%L,\n", it.name)
- }
- }
- .unindent()
- .add(")\n")
- .unindent()
- .add("}\n")
- .build())
- .build()
+ return FunSpec.builder("execute")
+ .addModifiers(KModifier.OVERRIDE)
+ .addCode(
+ buildCodeBlock {
+ add("with(parameters) {\n")
+ withIndent {
+ if (implementationCoordinates != null) {
+ add("%T(\n", ClassName("java.net", "URLClassLoader"))
+ withIndent {
+ add("$classpath.map { it.toURI().toURL() }.toTypedArray(),\n")
+ add("%T.getPlatformClassLoader()\n", ClassName("java.lang", "ClassLoader"))
+ }
+ add(")")
+ add(".loadClass(%S)\n", entryPointClassName().canonicalName)
+ add(".declaredMethods.single()\n")
+ add(".invoke(\n")
+ withIndent {
+ add("null,\n")
+ (parameters + returnValues).forEach {
+ add("%L,\n", it.name)
+ }
+ }
+ add(")\n")
+ } else {
+ add("%T.run(\n", entryPointClassName())
+ withIndent {
+ (parameters + returnValues).forEach {
+ add("%L,\n", it.name)
+ }
+ }
+ add(")\n")
+ }
+ }
+ add("}\n")
+ })
+ .build()
}
private fun GTaskAction.workParameters(): TypeSpec {
- return TypeSpec.interfaceBuilder(workParametersClassName().simpleName)
- .addModifiers(KModifier.PRIVATE)
- .addSuperinterface(ClassName("org.gradle.workers", "WorkParameters"))
- .apply {
- addProperty(
- PropertySpec.builder(
- classpath,
- ClassName("kotlin.collections", "Set")
- .parameterizedBy(ClassName("java.io", "File"))
- ).mutable(true).build()
- )
- (parameters + returnValues).forEach {
- addProperty(PropertySpec.builder(it.name, it.toTypeName()).mutable(true).build())
- }
- }
- .build()
+ return TypeSpec.interfaceBuilder(workParametersClassName().simpleName)
+ .addModifiers(KModifier.PRIVATE)
+ .addSuperinterface(ClassName("org.gradle.workers", "WorkParameters"))
+ .apply {
+ addProperty(
+ PropertySpec.builder(
+ classpath,
+ ClassName("kotlin.collections", "Set")
+ .parameterizedBy(ClassName("java.io", "File"))
+ ).mutable(true).build()
+ )
+ (parameters + returnValues).forEach {
+ addProperty(PropertySpec.builder(it.name, it.toTypeName()).mutable(true).build())
+ }
+ }
+ .build()
}
private fun GTaskAction.registerName(): String {
- return "register" + this.functionName.capitalizeFirstLetter() + "Task"
+ return "register" + this.functionName.capitalizeFirstLetter() + "Task"
}
private fun GTaskAction.taskName(): String {
- return this.functionName.decapitalizeFirstLetter()
+ return this.functionName.decapitalizeFirstLetter()
}
private fun GTaskAction.taskClassName(): ClassName {
- val simpleName = this.functionName.capitalizeFirstLetter() + "Task"
- return ClassName(this.packageName, simpleName)
+ val simpleName = this.functionName.capitalizeFirstLetter() + "Task"
+ return ClassName(this.packageName, simpleName)
}
internal fun GTaskAction.workParametersClassName(): ClassName {
- val simpleName = this.functionName.capitalizeFirstLetter() + "WorkParameters"
- return ClassName(this.packageName, simpleName)
+ val simpleName = this.functionName.capitalizeFirstLetter() + "WorkParameters"
+ return ClassName(this.packageName, simpleName)
}
private fun GTaskAction.workActionClassName(): ClassName {
- val simpleName = this.functionName.capitalizeFirstLetter() + "WorkAction"
- return ClassName(this.packageName, simpleName)
+ val simpleName = this.functionName.capitalizeFirstLetter() + "WorkAction"
+ return ClassName(this.packageName, simpleName)
}
diff --git a/gratatouille-processor/src/main/kotlin/gratatouille/processor/names.kt b/gratatouille-processor/src/main/kotlin/gratatouille/processor/names.kt
index 3fc77bc..203d0f5 100644
--- a/gratatouille-processor/src/main/kotlin/gratatouille/processor/names.kt
+++ b/gratatouille-processor/src/main/kotlin/gratatouille/processor/names.kt
@@ -5,5 +5,4 @@ internal val taskDescription = "taskDescription"
internal val taskGroup = "taskGroup"
internal val outputFile = "outputFile"
internal val classpath = "classpath"
-internal val extraClasspath = "extraClasspath"
internal val workerExecutor = "getWorkerExecutor"
diff --git a/libs.versions.toml b/libs.versions.toml
index 5c9d1b8..e9fa635 100644
--- a/libs.versions.toml
+++ b/libs.versions.toml
@@ -1,8 +1,9 @@
[versions]
-ksp = "1.9.22-1.0.16"
-kotlin = "1.9.22"
-coroutines = "1.8.0-RC2"
+ksp = "2.0.20-1.0.24"
+kotlin = "2.0.20"
+coroutines = "1.8.0"
kotlinpoet = "1.14.2"
+librarian = "0.0.6"
[libraries]
ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }
@@ -17,3 +18,8 @@ gradle-api = { group = "dev.gradleplugins", name = "gradle-api", version = "8.0"
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.6.2" }
kotlinpoet = { group = "com.squareup", name = "kotlinpoet", version.ref = "kotlinpoet" }
kotlinpoet-ksp = { group = "com.squareup", name = "kotlinpoet-ksp", version.ref = "kotlinpoet" }
+librarian = { module = "com.gradleup.librarian:librarian-gradle-plugin", version.ref = "librarian" }
+okio = "com.squareup.okio:okio:3.9.0"
+
+[plugins]
+librarian = { id = "com.gradleup.librarian", version.ref = "librarian"}
\ No newline at end of file
diff --git a/sample-app/gradle/wrapper b/sample-app/gradle/wrapper
new file mode 120000
index 0000000..3232fe4
--- /dev/null
+++ b/sample-app/gradle/wrapper
@@ -0,0 +1 @@
+../../gradle/wrapper
\ No newline at end of file
diff --git a/sample-app/gradlew b/sample-app/gradlew
deleted file mode 100644
index 1aa94a4..0000000
--- a/sample-app/gradlew
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original 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
-#
-# https://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.
-#
-
-##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh Gradle
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-# This is normally unused
-# shellcheck disable=SC2034
-APP_BASE_NAME=${0##*/}
-# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- if ! command -v java >/dev/null 2>&1
- then
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
-# and any embedded shellness will be escaped.
-# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
-# treated as '${Hostname}' itself on the command line.
-
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
-
-# Stop when "xargs" is not available.
-if ! command -v xargs >/dev/null 2>&1
-then
- die "xargs is not available"
-fi
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/sample-app/gradlew b/sample-app/gradlew
new file mode 120000
index 0000000..502f5a2
--- /dev/null
+++ b/sample-app/gradlew
@@ -0,0 +1 @@
+../gradlew
\ No newline at end of file
diff --git a/sample-app/gradlew.bat b/sample-app/gradlew.bat
deleted file mode 100644
index 7101f8e..0000000
--- a/sample-app/gradlew.bat
+++ /dev/null
@@ -1,92 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%"=="" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
-
-echo. 1>&2
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo. 1>&2
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/sample-app/gradlew.bat b/sample-app/gradlew.bat
new file mode 120000
index 0000000..2840132
--- /dev/null
+++ b/sample-app/gradlew.bat
@@ -0,0 +1 @@
+../gradlew.bat
\ No newline at end of file
diff --git a/sample-plugin/gradle-plugin/build.gradle.kts b/sample-plugin/gradle-plugin/build.gradle.kts
index 9162d8e..d188378 100644
--- a/sample-plugin/gradle-plugin/build.gradle.kts
+++ b/sample-plugin/gradle-plugin/build.gradle.kts
@@ -1,7 +1,7 @@
plugins {
id("org.jetbrains.kotlin.jvm")
id("java-gradle-plugin")
- id("com.gradleup.gratatouille.plugin")
+ id("com.gradleup.gratatouille.api")
}
version = rootProject.version
diff --git a/test-app/.idea/codeStyles b/test-app/.idea/codeStyles
new file mode 120000
index 0000000..70d0521
--- /dev/null
+++ b/test-app/.idea/codeStyles
@@ -0,0 +1 @@
+../../.idea/codeStyles
\ No newline at end of file
diff --git a/test-app/build.gradle.kts b/test-app/build.gradle.kts
index e7cff27..bbe3260 100644
--- a/test-app/build.gradle.kts
+++ b/test-app/build.gradle.kts
@@ -1,3 +1,44 @@
+import kotlin.test.assertFailsWith
+
plugins {
- id("testplugin")
+ id("testplugin")
+ id("testplugin.isolated")
+}
+
+testExtension {
+ stringInput.set("input")
+ internalInput.set("internalInput")
+ //optionalInput.set()
+
+ setInput.add(42)
+ listInput.add(43)
+ mapInput.put("key", "value")
+
+ filesInput.from(fileTree("inputs/fileInputs"))
+ //optionalFileInput.set()
+ fileInput.set(file("inputs/fileInput"))
+ directoryInput.set(layout.projectDirectory.dir("inputs/directoryInput"))
+ serializableInput.set(file("inputs/serializableInput"))
+
+ stringInput2.set("input2")
+ stringInput3.set("input3")
+
+ fileOutput3.set(file("build/output"))
+}
+
+testExtensionIsolated {
+ stringInput.set("world")
+}
+
+tasks.register("build") {
+ dependsOn("taskAction2", "taskAction3", "taskActionIsolated")
+
+ doLast {
+ check(file("build/gtask/taskActionIsolated/outputFile").readText() == "hello world - okio.Buffer")
+
+ // Make sure we don't have okio in the classpath
+ assertFailsWith {
+ Class.forName("okio.Buffer")
+ }
+ }
}
\ No newline at end of file
diff --git a/test-app/gradle/wrapper b/test-app/gradle/wrapper
new file mode 120000
index 0000000..3232fe4
--- /dev/null
+++ b/test-app/gradle/wrapper
@@ -0,0 +1 @@
+../../gradle/wrapper
\ No newline at end of file
diff --git a/test-app/gradle/wrapper/gradle-wrapper.jar b/test-app/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index d64cd49..0000000
Binary files a/test-app/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/test-app/gradle/wrapper/gradle-wrapper.properties b/test-app/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index a80b22c..0000000
--- a/test-app/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/test-app/gradlew b/test-app/gradlew
deleted file mode 100644
index 1aa94a4..0000000
--- a/test-app/gradlew
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original 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
-#
-# https://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.
-#
-
-##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh Gradle
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-
-# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
-done
-
-# This is normally unused
-# shellcheck disable=SC2034
-APP_BASE_NAME=${0##*/}
-# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
-
-warn () {
- echo "$*"
-} >&2
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-} >&2
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD=java
- if ! command -v java >/dev/null 2>&1
- then
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-fi
-
-# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
-fi
-
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-
-# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
-fi
-
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
-# and any embedded shellness will be escaped.
-# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
-# treated as '${Hostname}' itself on the command line.
-
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
-
-# Stop when "xargs" is not available.
-if ! command -v xargs >/dev/null 2>&1
-then
- die "xargs is not available"
-fi
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
-
-exec "$JAVACMD" "$@"
diff --git a/test-app/gradlew b/test-app/gradlew
new file mode 120000
index 0000000..502f5a2
--- /dev/null
+++ b/test-app/gradlew
@@ -0,0 +1 @@
+../gradlew
\ No newline at end of file
diff --git a/test-app/gradlew.bat b/test-app/gradlew.bat
deleted file mode 100644
index 7101f8e..0000000
--- a/test-app/gradlew.bat
+++ /dev/null
@@ -1,92 +0,0 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%"=="" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
-
-echo. 1>&2
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo. 1>&2
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/test-app/gradlew.bat b/test-app/gradlew.bat
new file mode 120000
index 0000000..2840132
--- /dev/null
+++ b/test-app/gradlew.bat
@@ -0,0 +1 @@
+../gradlew.bat
\ No newline at end of file
diff --git a/test-app/settings.gradle.kts b/test-app/settings.gradle.kts
index 3cfdf09..ed9b107 100644
--- a/test-app/settings.gradle.kts
+++ b/test-app/settings.gradle.kts
@@ -16,3 +16,4 @@ dependencyResolutionManagement {
}
includeBuild("../test-plugin")
+includeBuild("../test-plugin-isolated")
diff --git a/test-plugin-isolated/api/build.gradle.kts b/test-plugin-isolated/api/build.gradle.kts
new file mode 100644
index 0000000..ff8d5de
--- /dev/null
+++ b/test-plugin-isolated/api/build.gradle.kts
@@ -0,0 +1,20 @@
+plugins {
+ id("org.jetbrains.kotlin.jvm")
+ id("org.jetbrains.kotlin.plugin.serialization")
+ id("com.google.devtools.ksp")
+ id("com.gradleup.gratatouille.api")
+ id("java-gradle-plugin")
+}
+
+dependencies {
+ gratatouille(project(":implementation"))
+}
+
+gradlePlugin {
+ plugins {
+ create("testplugin.isolated") {
+ this.implementationClass = "testplugin.isolated.TestPluginIsolated"
+ this.id = "testplugin.isolated"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test-plugin-isolated/api/src/main/kotlin/testplugin/isolated/TestPluginIsolated.kt b/test-plugin-isolated/api/src/main/kotlin/testplugin/isolated/TestPluginIsolated.kt
new file mode 100644
index 0000000..88343b6
--- /dev/null
+++ b/test-plugin-isolated/api/src/main/kotlin/testplugin/isolated/TestPluginIsolated.kt
@@ -0,0 +1,20 @@
+package testplugin.isolated
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.provider.Property
+import testplugin.isolated.registerTaskActionIsolatedTask
+
+class TestPluginIsolated : Plugin {
+ override fun apply(target: Project) {
+ val extension = target.extensions.create("testExtensionIsolated", TestExtensionIsolated::class.java)
+
+ val task1 = target.registerTaskActionIsolatedTask(
+ stringInput = extension.stringInput,
+ )
+ }
+}
+
+abstract class TestExtensionIsolated {
+ abstract val stringInput: Property
+}
\ No newline at end of file
diff --git a/test-plugin-isolated/build.gradle.kts b/test-plugin-isolated/build.gradle.kts
new file mode 100644
index 0000000..561988b
--- /dev/null
+++ b/test-plugin-isolated/build.gradle.kts
@@ -0,0 +1,10 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ }
+ dependencies {
+ classpath("build-logic:build-logic")
+ classpath("com.gradleup.gratatouille:gratatouille-gradle-plugin")
+ }
+}
diff --git a/sample-app/gradle/wrapper/gradle-wrapper.jar b/test-plugin-isolated/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from sample-app/gradle/wrapper/gradle-wrapper.jar
rename to test-plugin-isolated/gradle/wrapper/gradle-wrapper.jar
diff --git a/sample-app/gradle/wrapper/gradle-wrapper.properties b/test-plugin-isolated/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from sample-app/gradle/wrapper/gradle-wrapper.properties
rename to test-plugin-isolated/gradle/wrapper/gradle-wrapper.properties
diff --git a/test-plugin-isolated/gradlew b/test-plugin-isolated/gradlew
new file mode 100644
index 0000000..1aa94a4
--- /dev/null
+++ b/test-plugin-isolated/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original 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
+#
+# https://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.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/test-plugin-isolated/gradlew.bat b/test-plugin-isolated/gradlew.bat
new file mode 100644
index 0000000..7101f8e
--- /dev/null
+++ b/test-plugin-isolated/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/test-plugin/implementation/build.gradle.kts b/test-plugin-isolated/implementation/build.gradle.kts
similarity index 78%
rename from test-plugin/implementation/build.gradle.kts
rename to test-plugin-isolated/implementation/build.gradle.kts
index da27000..f886b6b 100644
--- a/test-plugin/implementation/build.gradle.kts
+++ b/test-plugin-isolated/implementation/build.gradle.kts
@@ -6,6 +6,5 @@ plugins {
}
dependencies {
- implementation(libs.kotlinx.serialization.json)
-}
-
+ implementation(libs.okio)
+}
\ No newline at end of file
diff --git a/test-plugin-isolated/implementation/src/main/kotlin/testplugin/isolated/tasks.kt b/test-plugin-isolated/implementation/src/main/kotlin/testplugin/isolated/tasks.kt
new file mode 100644
index 0000000..3a45976
--- /dev/null
+++ b/test-plugin-isolated/implementation/src/main/kotlin/testplugin/isolated/tasks.kt
@@ -0,0 +1,15 @@
+package testplugin.isolated
+
+import gratatouille.*
+import okio.buffer
+import okio.sink
+
+@GTaskAction
+internal fun taskActionIsolated(
+ stringInput: String,
+ outputFile: GOutputFile
+) {
+ outputFile.sink().buffer().use {
+ it.writeUtf8("hello $stringInput - ${Class.forName("okio.Buffer").name}")
+ }
+}
diff --git a/test-plugin-isolated/settings.gradle.kts b/test-plugin-isolated/settings.gradle.kts
new file mode 100644
index 0000000..4ac25dc
--- /dev/null
+++ b/test-plugin-isolated/settings.gradle.kts
@@ -0,0 +1,21 @@
+pluginManagement {
+ listOf(repositories, dependencyResolutionManagement.repositories).forEach {
+ it.apply {
+ mavenCentral()
+ google()
+ gradlePluginPortal()
+ }
+ }
+}
+
+dependencyResolutionManagement {
+ versionCatalogs {
+ create("libs") {
+ from(files("../libs.versions.toml"))
+ }
+ }
+}
+
+includeBuild("..")
+includeBuild("../build-logic")
+include(":api", ":implementation")
diff --git a/test-plugin/build.gradle.kts b/test-plugin/build.gradle.kts
index d3f98ff..561988b 100644
--- a/test-plugin/build.gradle.kts
+++ b/test-plugin/build.gradle.kts
@@ -8,6 +8,3 @@ buildscript {
classpath("com.gradleup.gratatouille:gratatouille-gradle-plugin")
}
}
-
-
-group = "sample-plugin"
\ No newline at end of file
diff --git a/test-plugin/gradle-plugin/src/main/kotlin/testplugin/TestPlugin.kt b/test-plugin/gradle-plugin/src/main/kotlin/testplugin/TestPlugin.kt
deleted file mode 100644
index 0092d73..0000000
--- a/test-plugin/gradle-plugin/src/main/kotlin/testplugin/TestPlugin.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package testplugin
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.file.RegularFile
-import org.gradle.api.file.RegularFileProperty
-
-class TestPlugin : Plugin {
- override fun apply(target: Project) {
- val task1 = target.registerTaskAction1Task(
- stringInput = target.provider { "stringInput" },
- internalInput = target.provider { "internalInput" },
- optionalInput = target.objects.property(String::class.java),
- setInput = target.provider { setOf(0) },
- listInput = target.provider { listOf(0) },
- mapInput = target.provider { mapOf("key" to "value") },
- filesInput = target.files("inputs/filesInput"),
- optionalFileInput = target.objects.fileProperty(),
- fileInput = target.provider { target.layout.projectDirectory.file("inputs/fileInput") },
- directoryInput = target.provider { target.layout.projectDirectory.dir("inputs/directoryInput") },
- serializableInput = target.provider { target.layout.projectDirectory.file("inputs/serializableInput") },
- )
-
- target.registerTaskAction2Task(
- input = target.provider { "input2" },
- myData = task1.flatMap { it.outputFile }
- )
-
- target.registerTaskAction3Task(
- input = target.provider { "input3" },
- outputFile = target.layout.buildDirectory.file("output3")
- )
- }
-}
\ No newline at end of file
diff --git a/test-plugin/settings.gradle.kts b/test-plugin/settings.gradle.kts
index f9b830b..2a1d566 100644
--- a/test-plugin/settings.gradle.kts
+++ b/test-plugin/settings.gradle.kts
@@ -18,4 +18,4 @@ dependencyResolutionManagement {
includeBuild("..")
includeBuild("../build-logic")
-include(":implementation", ":gradle-plugin")
+include(":test-plugin")
diff --git a/test-plugin/gradle-plugin/build.gradle.kts b/test-plugin/test-plugin/build.gradle.kts
similarity index 67%
rename from test-plugin/gradle-plugin/build.gradle.kts
rename to test-plugin/test-plugin/build.gradle.kts
index 8188d56..1613f66 100644
--- a/test-plugin/gradle-plugin/build.gradle.kts
+++ b/test-plugin/test-plugin/build.gradle.kts
@@ -1,13 +1,11 @@
plugins {
id("org.jetbrains.kotlin.jvm")
- id("com.gradleup.gratatouille.plugin")
+ id("org.jetbrains.kotlin.plugin.serialization")
+ id("com.google.devtools.ksp")
+ id("com.gradleup.gratatouille")
id("java-gradle-plugin")
}
-dependencies {
- gratatouille(project(":implementation"))
-}
-
gradlePlugin {
plugins {
create("testplugin") {
diff --git a/test-plugin/test-plugin/src/main/kotlin/testplugin/TestPlugin.kt b/test-plugin/test-plugin/src/main/kotlin/testplugin/TestPlugin.kt
new file mode 100644
index 0000000..413c406
--- /dev/null
+++ b/test-plugin/test-plugin/src/main/kotlin/testplugin/TestPlugin.kt
@@ -0,0 +1,62 @@
+package testplugin
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.MapProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.SetProperty
+
+class TestPlugin : Plugin {
+ override fun apply(target: Project) {
+ val extension = target.extensions.create("testExtension", TestExtension::class.java)
+
+ val task1 = target.registerTaskAction1Task(
+ stringInput = extension.stringInput,
+ internalInput = extension.internalInput,
+ optionalInput = extension.optionalInput,
+ setInput = extension.setInput,
+ listInput = extension.listInput,
+ mapInput = extension.mapInput,
+ filesInput = extension.filesInput,
+ optionalFileInput = extension.optionalFileInput,
+ fileInput = extension.fileInput,
+ directoryInput = extension.directoryInput,
+ serializableInput = extension.serializableInput,
+ )
+
+ target.registerTaskAction2Task(
+ input = extension.stringInput2,
+ myData = task1.flatMap { it.outputFile }
+ )
+
+ target.registerTaskAction3Task(
+ input = extension.stringInput3,
+ outputFile = extension.fileOutput3
+ )
+ }
+}
+
+abstract class TestExtension {
+ abstract val stringInput: Property
+ abstract val internalInput: Property
+ abstract val optionalInput: Property
+
+ abstract val setInput: SetProperty
+ abstract val listInput: ListProperty
+ abstract val mapInput: MapProperty
+
+ abstract val filesInput: ConfigurableFileCollection
+ abstract val optionalFileInput: RegularFileProperty
+ abstract val fileInput: RegularFileProperty
+ abstract val directoryInput: DirectoryProperty
+ abstract val serializableInput: RegularFileProperty
+
+ abstract val stringInput2: Property
+ abstract val stringInput3: Property
+
+ abstract val fileOutput3: RegularFileProperty
+}
\ No newline at end of file
diff --git a/test-plugin/implementation/src/main/kotlin/testplugin/tasks.kt b/test-plugin/test-plugin/src/main/kotlin/testplugin/tasks.kt
similarity index 100%
rename from test-plugin/implementation/src/main/kotlin/testplugin/tasks.kt
rename to test-plugin/test-plugin/src/main/kotlin/testplugin/tasks.kt