From 186fdeaa2f0e13de51bae888c6a7b35c35149903 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 10 Nov 2022 17:30:02 +0100 Subject: [PATCH] Allow arbitrary code snippets to be added in a Gradle build This commit provides an escape hatch for the DSL that we currently don't support in a gradle build. Snippets can be added with a callback to an IndentingWriter. For convenience, imports can be added as well. Snippets are rendered at the end of the file. Closes gh-1079 --- .../buildsystem/gradle/GradleBuild.java | 13 ++- .../buildsystem/gradle/GradleBuildWriter.java | 18 ++- .../buildsystem/gradle/GradleSnippet.java | 52 +++++++++ .../gradle/GradleSnippetContainer.java | 79 +++++++++++++ .../gradle/GradleBuildWriterTests.java | 93 +++++++++++++++ .../GroovyDslGradleBuildWriterTests.java | 4 +- .../KotlinDslGradleBuildWriterTests.java | 107 +++++++++--------- 7 files changed, 306 insertions(+), 60 deletions(-) create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippet.java create mode 100644 initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippetContainer.java create mode 100644 initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriterTests.java diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuild.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuild.java index 54655e0e07..0288f1fe95 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuild.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuild.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,8 @@ public class GradleBuild extends Build { private final GradleTaskContainer tasks = new GradleTaskContainer(); + private final GradleSnippetContainer snippets = new GradleSnippetContainer(); + private final GradleBuildscript.Builder buildscript = new GradleBuildscript.Builder(); /** @@ -92,6 +94,15 @@ public GradleTaskContainer tasks() { return this.tasks; } + /** + * Return the {@linkplain GradleSnippetContainer snippet container} to use to apply + * snippets. + * @return the {@link GradleSnippetContainer} + */ + public GradleSnippetContainer snippets() { + return this.snippets; + } + /** * Customize the {@code buildscript} of the build using the specified consumer. * @param buildscript a consumer of the current buildscript diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriter.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriter.java index d5ce0c2731..e225919cc1 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriter.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriter.java @@ -29,6 +29,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import io.spring.initializr.generator.buildsystem.BillOfMaterials; import io.spring.initializr.generator.buildsystem.Dependency; @@ -59,7 +60,7 @@ public abstract class GradleBuildWriter { */ public final void writeTo(IndentingWriter writer, GradleBuild build) { GradleBuildSettings settings = build.getSettings(); - writeImports(writer, build.tasks()); + writeImports(writer, build.tasks(), build.snippets()); writeBuildscript(writer, build); writePlugins(writer, build); writeProperty(writer, "group", settings.getGroup()); @@ -72,10 +73,11 @@ public final void writeTo(IndentingWriter writer, GradleBuild build) { writeDependencies(writer, build); writeBoms(writer, build); writeTasks(writer, build.tasks()); + writeSnippets(writer, build.snippets()); } - private void writeImports(IndentingWriter writer, GradleTaskContainer tasks) { - List imports = tasks.importedTypes().sorted().toList(); + private void writeImports(IndentingWriter writer, GradleTaskContainer tasks, GradleSnippetContainer snippets) { + List imports = Stream.concat(tasks.importedTypes(), snippets.importedTypes()).sorted().toList(); imports.forEach((importedType) -> writer.println("import " + importedType)); if (!imports.isEmpty()) { writer.println(); @@ -202,6 +204,16 @@ protected final void writeTaskCustomization(IndentingWriter writer, GradleTask t protected abstract String invocationAsString(GradleTask.Invocation invocation); + private void writeSnippets(IndentingWriter writer, GradleSnippetContainer snippets) { + if (!snippets.isEmpty()) { + writer.println(); + } + snippets.values().forEach((snippet) -> { + snippet.apply(writer); + writer.println(); + }); + } + protected final void writeNestedCollection(IndentingWriter writer, String name, Collection collection, Function itemToStringConverter) { this.writeNestedCollection(writer, name, collection, itemToStringConverter, null); diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippet.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippet.java new file mode 100644 index 0000000000..4df2fda4c8 --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippet.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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. + */ + +package io.spring.initializr.generator.buildsystem.gradle; + +import java.util.Set; +import java.util.function.Consumer; + +import io.spring.initializr.generator.io.IndentingWriter; + +/** + * A free-form {@code snippet} to add to a Gradle build. + * + * @author Stephane Nicoll + */ +public class GradleSnippet { + + private final Set importedTypes; + + private final Consumer writer; + + GradleSnippet(Set importedTypes, Consumer writer) { + this.importedTypes = Set.copyOf(importedTypes); + this.writer = writer; + } + + Set getImportedTypes() { + return this.importedTypes; + } + + /** + * Apply the snippet using the specified {@link IndentingWriter}. + * @param indentingWriter the writer to use + */ + public void apply(IndentingWriter indentingWriter) { + this.writer.accept(indentingWriter); + } + +} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippetContainer.java b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippetContainer.java new file mode 100644 index 0000000000..b9b0dd9f0b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippetContainer.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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. + */ + +package io.spring.initializr.generator.buildsystem.gradle; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import io.spring.initializr.generator.io.IndentingWriter; + +/** + * A container for {@linkplain GradleSnippet Gradle snippets}. + * + * @author Stephane Nicoll + */ +public class GradleSnippetContainer { + + private final List snippets = new ArrayList<>(); + + /** + * Specify if this container is empty. + * @return {@code true} if no snippet is registered + */ + public boolean isEmpty() { + return this.snippets.isEmpty(); + } + + /** + * Return the {@link GradleSnippet Gradle snippets} to apply. + * @return the gradle snippets + */ + public Stream values() { + return this.snippets.stream(); + } + + /** + * Return the fully qualified name of types to import. + * @return the imported types + */ + public Stream importedTypes() { + return this.snippets.stream().map(GradleSnippet::getImportedTypes).flatMap(Collection::stream); + } + + /** + * Register a {@code snippet} with the specified types to import and writer. + * @param importedTypes the types to import + * @param writer the writer to use. + */ + public void add(Set importedTypes, Consumer writer) { + this.snippets.add(new GradleSnippet(importedTypes, writer)); + } + + /** + * Register a {@code snippet} with no import. + * @param writer the writer to use. + */ + public void add(Consumer writer) { + add(Collections.emptySet(), writer); + } + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriterTests.java new file mode 100644 index 0000000000..bf8bc74d6c --- /dev/null +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GradleBuildWriterTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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. + */ + +package io.spring.initializr.generator.buildsystem.gradle; + +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Common tests for {@link GradleBuildWriter} implementations. + * + * @author Stephane Nicoll + */ +public abstract class GradleBuildWriterTests { + + @Test + void gradleBuildWithSnippet() { + GradleBuild build = new GradleBuild(); + build.snippets().add((writer) -> { + writer.println("custom {"); + writer.indented(() -> { + writer.println("first = 1"); + writer.println("second = 2"); + }); + writer.println("}"); + }); + assertThat(write(build)).contains(""" + custom { + first = 1 + second = 2 + } + """); + } + + @Test + void gradleBuildWithSnippetsAreSeparated() { + GradleBuild build = new GradleBuild(); + build.snippets().add((writer) -> { + writer.println("custom {"); + writer.indented(() -> { + writer.println("first = 1"); + writer.println("second = 2"); + }); + writer.println("}"); + }); + build.snippets().add((writer) -> { + writer.println("another {"); + writer.indented(() -> { + writer.println("third = 3"); + writer.println("fourth = 4"); + }); + writer.println("}"); + }); + + assertThat(write(build)).contains(""" + custom { + first = 1 + second = 2 + } + + another { + third = 3 + fourth = 4 + } + """); + } + + @Test + void gradleBuildWithSnippetAndImports() { + GradleBuild build = new GradleBuild(); + build.snippets().add(Set.of("com.example.CustomTask"), (writer) -> writer.println("custom { }")); + assertThat(write(build)).containsOnlyOnce("import com.example.CustomTask"); + } + + protected abstract String write(GradleBuild build); + +} diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GroovyDslGradleBuildWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GroovyDslGradleBuildWriterTests.java index dcf92554e7..4c7028de83 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GroovyDslGradleBuildWriterTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/GroovyDslGradleBuildWriterTests.java @@ -39,7 +39,7 @@ * @author Jean-Baptiste Nizet * @author Stephane Nicoll */ -class GroovyDslGradleBuildWriterTests { +class GroovyDslGradleBuildWriterTests extends GradleBuildWriterTests { @Test void gradleBuildWithCoordinates() { @@ -556,7 +556,7 @@ void gradleBuildWithCustomVersion() { assertThat(write(build)).contains("version = '1.2.4.RELEASE'"); } - private String write(GradleBuild build) { + protected String write(GradleBuild build) { return write(new GroovyDslGradleBuildWriter(), build); } diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/KotlinDslGradleBuildWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/KotlinDslGradleBuildWriterTests.java index a3b4b6725f..0fbb96158d 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/KotlinDslGradleBuildWriterTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/buildsystem/gradle/KotlinDslGradleBuildWriterTests.java @@ -43,13 +43,13 @@ * @author Jean-Baptiste Nizet * @author Stephane Nicoll */ -class KotlinDslGradleBuildWriterTests { +class KotlinDslGradleBuildWriterTests extends GradleBuildWriterTests { @Test void gradleBuildWithCoordinates() { GradleBuild build = new GradleBuild(); build.settings().group("com.example").version("1.0.1-SNAPSHOT"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" group = "com.example" version = "1.0.1-SNAPSHOT" """); @@ -60,7 +60,7 @@ void gradleBuildWithCoordinates() { void gradleBuildWithSourceCompatibility15(String sourceCompatibility, String javaVersionConstant) { GradleBuild build = new GradleBuild(); build.settings().sourceCompatibility(sourceCompatibility); - assertThat(generateBuild(build)).contains("java.sourceCompatibility = " + javaVersionConstant); + assertThat(write(build)).contains("java.sourceCompatibility = " + javaVersionConstant); } static Stream sourceCompatibilityParameters() { @@ -86,14 +86,14 @@ void gradleBuildWithBuildscriptDependency() { GradleBuild build = new GradleBuild(); build.buildscript((buildscript) -> buildscript .dependency("org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RELEASE")); - assertThatIllegalStateException().isThrownBy(() -> generateBuild(build)); + assertThatIllegalStateException().isThrownBy(() -> write(build)); } @Test void gradleBuildWithBuildscriptExtProperty() { GradleBuild build = new GradleBuild(); build.buildscript((buildscript) -> buildscript.ext("kotlinVersion", "\1.2.51\"")); - assertThatIllegalStateException().isThrownBy(() -> generateBuild(build)); + assertThatIllegalStateException().isThrownBy(() -> write(build)); } @Test @@ -101,7 +101,7 @@ void gradleBuildWithBuiltinPlugin() { GradleBuild build = new GradleBuild(); build.plugins().add("java"); build.plugins().add("war"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" plugins { java war @@ -113,7 +113,7 @@ void gradleBuildWithKotlinPluginAndVersion() { GradleBuild build = new GradleBuild(); build.plugins().add("org.jetbrains.kotlin.jvm", (plugin) -> plugin.setVersion("1.3.21")); build.plugins().add("org.jetbrains.kotlin.plugin.spring", (plugin) -> plugin.setVersion("1.3.21")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" plugins { kotlin("jvm") version "1.3.21" kotlin("plugin.spring") version "1.3.21" @@ -124,7 +124,7 @@ void gradleBuildWithKotlinPluginAndVersion() { void gradleBuildWithPluginAndVersion() { GradleBuild build = new GradleBuild(); build.plugins().add("org.springframework.boot", (plugin) -> plugin.setVersion("2.1.0.RELEASE")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" plugins { id("org.springframework.boot") version "2.1.0.RELEASE" }"""); @@ -134,14 +134,14 @@ void gradleBuildWithPluginAndVersion() { void gradleBuildWithApplyPlugin() { GradleBuild build = new GradleBuild(); build.plugins().apply("io.spring.dependency-management"); - assertThatIllegalStateException().isThrownBy(() -> generateBuild(build)); + assertThatIllegalStateException().isThrownBy(() -> write(build)); } @Test void gradleBuildWithMavenCentralRepository() { GradleBuild build = new GradleBuild(); build.repositories().add("maven-central"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" repositories { mavenCentral() }"""); @@ -151,7 +151,7 @@ void gradleBuildWithMavenCentralRepository() { void gradleBuildWithRepository() { GradleBuild build = new GradleBuild(); build.repositories().add(MavenRepository.withIdAndUrl("spring-milestones", "https://repo.spring.io/milestone")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" repositories { maven { url = uri("https://repo.spring.io/milestone") } }"""); @@ -162,7 +162,7 @@ void gradleBuildWithSnapshotRepository() { GradleBuild build = new GradleBuild(); build.repositories().add( MavenRepository.withIdAndUrl("spring-snapshots", "https://repo.spring.io/snapshot").onlySnapshots()); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" repositories { maven { url = uri("https://repo.spring.io/snapshot") } }"""); @@ -173,7 +173,7 @@ void gradleBuildWithPluginRepository() { GradleBuild build = new GradleBuild(); build.pluginRepositories() .add(MavenRepository.withIdAndUrl("spring-milestones", "https://repo.spring.io/milestone")); - assertThat(generateBuild(build)).doesNotContain("repositories {"); + assertThat(write(build)).doesNotContain("repositories {"); } @Test @@ -184,21 +184,20 @@ void gradleBuildWithTaskWithTypesCustomizedWithNestedAssignments() { (kotlinOptions) -> kotlinOptions.attribute("freeCompilerArgs", "listOf(\"-Xjsr305=strict\")"))); build.tasks().customizeWithType("org.jetbrains.kotlin.gradle.tasks.KotlinCompile", (task) -> task .nested("kotlinOptions", (kotlinOptions) -> kotlinOptions.attribute("jvmTarget", "\"1.8\""))); - assertThat(generateBuild(build)).containsOnlyOnce("import org.jetbrains.kotlin.gradle.tasks.KotlinCompile") - .contains(""" - tasks.withType { - kotlinOptions { - freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "1.8" - } - }"""); + assertThat(write(build)).containsOnlyOnce("import org.jetbrains.kotlin.gradle.tasks.KotlinCompile").contains(""" + tasks.withType { + kotlinOptions { + freeCompilerArgs = listOf("-Xjsr305=strict") + jvmTarget = "1.8" + } + }"""); } @Test void gradleBuildWithTaskWithTypesAndShortTypes() { GradleBuild build = new GradleBuild(); build.tasks().customizeWithType("JavaCompile", (javaCompile) -> javaCompile.attribute("options.fork", "true")); - assertThat(generateBuild(build)).doesNotContain("import JavaCompile").contains(""" + assertThat(write(build)).doesNotContain("import JavaCompile").contains(""" tasks.withType { options.fork = true }"""); @@ -211,7 +210,7 @@ void gradleBuildWithTaskCustomizedWithInvocations() { task.invoke("inputs.dir", "snippetsDir"); task.invoke("dependsOn", "test"); }); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" tasks.asciidoctor { inputs.dir(snippetsDir) dependsOn(test) @@ -225,7 +224,7 @@ void gradleBuildWithTaskCustomizedWithAssignments() { task.attribute("kotlinOptions.freeCompilerArgs", "listOf(\"-Xjsr305=strict\")"); task.attribute("kotlinOptions.jvmTarget", "\"1.8\""); }); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" tasks.compileKotlin { kotlinOptions.freeCompilerArgs = listOf("-Xjsr305=strict") kotlinOptions.jvmTarget = "1.8" @@ -240,7 +239,7 @@ void gradleBuildWithTaskCustomizedWithNestedCustomization() { kotlinOptions.attribute("freeCompilerArgs", "listOf(\"-Xjsr305=strict\")"); kotlinOptions.attribute("jvmTarget", "\"1.8\""); })); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" tasks.compileKotlin { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") @@ -253,7 +252,7 @@ void gradleBuildWithTaskCustomizedWithNestedCustomization() { void gradleBuildWithExt() { GradleBuild build = new GradleBuild(); build.properties().property("java.version", "\"1.8\"").property("alpha", "file(\"build/example\")"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" extra["alpha"] = file("build/example") extra["java.version"] = "1.8" """); @@ -264,7 +263,7 @@ void gradleBuildWithVersionProperties() { GradleBuild build = new GradleBuild(); build.properties().version(VersionProperty.of("version.property", false), "1.2.3") .version(VersionProperty.of("internal.property", true), "4.5.6").version("external.property", "7.8.9"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" extra["external.property"] = "7.8.9" extra["internalProperty"] = "4.5.6" extra["version.property"] = "1.2.3" @@ -277,7 +276,7 @@ void gradleBuildWithVersionedDependency() { build.dependencies().add("kotlin-stdlib", Dependency.withCoordinates("org.jetbrains.kotlin", "kotlin-stdlib-jdk8") .version(VersionReference.ofProperty("kotlin.version")).scope(DependencyScope.COMPILE)); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${property("kotlinVersion")}") }"""); @@ -290,7 +289,7 @@ void gradleBuildWithExternalVersionedDependency() { Dependency.withCoordinates("com.example", "acme") .version(VersionReference.ofProperty(VersionProperty.of("acme.version", false))) .scope(DependencyScope.COMPILE)); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("com.example:acme:${property("acme.version")}") }"""); @@ -301,7 +300,7 @@ void gradleBuildWithExtAndVersionProperties() { GradleBuild build = new GradleBuild(); build.properties().version(VersionProperty.of("test-version", true), "1.0").version("alpha-version", "0.1") .property("myProperty", "42"); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" extra["myProperty"] = 42 extra["alpha-version"] = "0.1" extra["testVersion"] = "1.0" @@ -312,7 +311,7 @@ void gradleBuildWithExtAndVersionProperties() { void gradleBuildWithConfiguration() { GradleBuild build = new GradleBuild(); build.configurations().add("developmentOnly"); - assertThat(generateBuild(build)).contains("val developmentOnly by configurations.creating"); + assertThat(write(build)).contains("val developmentOnly by configurations.creating"); } @Test @@ -321,7 +320,7 @@ void gradleBuildWithConfigurationCustomization() { build.configurations().add("custom"); build.configurations().customize("runtimeClasspath", (configuration) -> configuration.extendsFrom("custom")); build.configurations().customize("runtimeClasspath", (configuration) -> configuration.extendsFrom("builtIn")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" val custom by configurations.creating configurations { runtimeClasspath { @@ -338,7 +337,7 @@ void gradleBuildWithConfigurationCustomizations() { build.configurations().customize("runtimeClasspath", (configuration) -> configuration.extendsFrom("custom")); build.configurations().customize("testRuntimeClasspath", (configuration) -> configuration.extendsFrom("builtIn")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" val custom by configurations.creating configurations { runtimeClasspath { @@ -356,7 +355,7 @@ void gradleBuildWithAnnotationProcessorDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("annotation-processor", "org.springframework.boot", "spring-boot-configuration-processor", DependencyScope.ANNOTATION_PROCESSOR); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") }"""); @@ -366,7 +365,7 @@ void gradleBuildWithAnnotationProcessorDependency() { void gradleBuildWithCompileDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("root", "org.springframework.boot", "spring-boot-starter", DependencyScope.COMPILE); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("org.springframework.boot:spring-boot-starter") }"""); @@ -376,7 +375,7 @@ void gradleBuildWithCompileDependency() { void gradleBuildWithNoScopeDependencyDefaultsToCompile() { GradleBuild build = new GradleBuild(); build.dependencies().add("root", Dependency.withCoordinates("org.springframework.boot", "spring-boot-starter")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("org.springframework.boot:spring-boot-starter") }"""); @@ -387,7 +386,7 @@ void gradleBuildWithRuntimeDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("driver", Dependency.withCoordinates("com.example", "jdbc-driver") .version(VersionReference.ofValue("1.0.0")).scope(DependencyScope.RUNTIME)); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { runtimeOnly("com.example:jdbc-driver:1.0.0") }"""); @@ -398,7 +397,7 @@ void gradleBuildWithProvidedRuntimeDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("tomcat", "org.springframework.boot", "spring-boot-starter-tomcat", DependencyScope.PROVIDED_RUNTIME); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") }"""); @@ -409,7 +408,7 @@ void gradleBuildWithTestCompileDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("test", "org.springframework.boot", "spring-boot-starter-test", DependencyScope.TEST_COMPILE); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") }"""); @@ -420,7 +419,7 @@ void gradleBuildWithCompileOnlyDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("test", "org.springframework.boot", "spring-boot-starter-foobar", DependencyScope.COMPILE_ONLY); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { compileOnly("org.springframework.boot:spring-boot-starter-foobar") }"""); @@ -431,7 +430,7 @@ void gradleBuildWithTestRuntimeDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("embed-mongo", "de.flapdoodle.embed", "de.flapdoodle.embed.mongo", DependencyScope.TEST_RUNTIME); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { testRuntimeOnly("de.flapdoodle.embed:de.flapdoodle.embed.mongo") }"""); @@ -442,7 +441,7 @@ void gradleBuildWithClassifierDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("root", Dependency.withCoordinates("com.example", "acme") .scope(DependencyScope.COMPILE).classifier("test-jar")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("com.example:acme:test-jar") }"""); @@ -455,7 +454,7 @@ void gradleBuildWithExclusions() { Dependency.withCoordinates("com.example", "test").scope(DependencyScope.COMPILE).exclusions( new Exclusion("com.example.legacy", "legacy-one"), new Exclusion("com.example.another", "legacy-two"))); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("com.example:test") { exclude(group = "com.example.legacy", module = "legacy-one") @@ -470,7 +469,7 @@ void gradleBuildWithCustomDependencyConfiguration() { build.dependencies().add("test", GradleDependency.withCoordinates("org.springframework.boot", "spring-boot-starter-foobar") .scope(DependencyScope.RUNTIME).configuration("myRuntime")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { myRuntime("org.springframework.boot:spring-boot-starter-foobar") }"""); @@ -481,7 +480,7 @@ void gradleBuildWithNonNullArtifactTypeDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("root", Dependency.withCoordinates("org.springframework.boot", "spring-boot-starter") .scope(DependencyScope.COMPILE).type("tar.gz")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("org.springframework.boot:spring-boot-starter@tar.gz") }"""); @@ -492,7 +491,7 @@ void gradleBuildWithNonNullArtifactTypeAndClassifierDependency() { GradleBuild build = new GradleBuild(); build.dependencies().add("root", Dependency.withCoordinates("com.example", "acme") .scope(DependencyScope.COMPILE).type("tar.gz").classifier("test-jar")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("com.example:acme:test-jar@tar.gz") }"""); @@ -506,7 +505,7 @@ void gradleBuildWithOrderedDependencies() { build.dependencies().add("web", Dependency.withCoordinates("org.springframework.boot", "spring-boot-starter-web")); build.dependencies().add("root", Dependency.withCoordinates("org.springframework.boot", "spring-boot-starter")); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencies { implementation("org.springframework.boot:spring-boot-starter") implementation("org.springframework.boot:spring-boot-starter-web") @@ -530,7 +529,7 @@ protected Comparator getDependencyComparator() { return Comparator.comparing(Dependency::getArtifactId); } }; - assertThat(generateBuild(writer, build)).contains(""" + assertThat(write(writer, build)).contains(""" dependencies { implementation("com.example:alpha") implementation("com.example:beta") @@ -544,7 +543,7 @@ void gradleBuildWithBom() { GradleBuild build = new GradleBuild(); build.boms().add("test", BillOfMaterials.withCoordinates("com.example", "my-project-dependencies") .version(VersionReference.ofValue("1.0.0.RELEASE"))); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencyManagement { imports { mavenBom("com.example:my-project-dependencies:1.0.0.RELEASE") @@ -559,7 +558,7 @@ void gradleBuildWithOrderedBoms() { .version(VersionReference.ofValue("1.0.0.RELEASE")).order(5)); build.boms().add("bom2", BillOfMaterials.withCoordinates("com.example", "root-dependencies") .version(VersionReference.ofProperty("root.version")).order(2)); - assertThat(generateBuild(build)).contains(""" + assertThat(write(build)).contains(""" dependencyManagement { imports { mavenBom("com.example:my-project-dependencies:1.0.0.RELEASE") @@ -572,14 +571,14 @@ void gradleBuildWithOrderedBoms() { void gradleBuildWithCustomVersion() { GradleBuild build = new GradleBuild(); build.settings().version("1.2.4.RELEASE"); - assertThat(generateBuild(build)).contains("version = \"1.2.4.RELEASE\""); + assertThat(write(build)).contains("version = \"1.2.4.RELEASE\""); } - private String generateBuild(GradleBuild build) { - return generateBuild(new KotlinDslGradleBuildWriter(), build); + protected String write(GradleBuild build) { + return write(new KotlinDslGradleBuildWriter(), build); } - private String generateBuild(KotlinDslGradleBuildWriter writer, GradleBuild build) { + private String write(KotlinDslGradleBuildWriter writer, GradleBuild build) { StringWriter out = new StringWriter(); writer.writeTo(new IndentingWriter(out, new SimpleIndentStrategy("\t")), build); return out.toString().replace("\r\n", "\n");