From 1d354c21362bb0a4e7bfcc87798d2c632c0ac2e5 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 10 Nov 2022 17:30:02 +0100 Subject: [PATCH] Hacking See gh-1079 --- .../buildsystem/gradle/GradleBuild.java | 11 +++ .../buildsystem/gradle/GradleBuildWriter.java | 18 ++++- .../buildsystem/gradle/GradleSnippet.java | 46 ++++++++++++ .../gradle/GradleSnippetContainer.java | 74 +++++++++++++++++++ .../GroovyDslGradleBuildWriterTests.java | 62 ++++++++++++++++ 5 files changed, 208 insertions(+), 3 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 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..2b1c7a1123 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 @@ -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..a6e16ba57b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippet.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * @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; + } + + 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..e18702fb0b --- /dev/null +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/buildsystem/gradle/GradleSnippetContainer.java @@ -0,0 +1,74 @@ +/* + * 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; + +/** + * @author Stephane Nicoll + */ +public class GradleSnippetContainer { + + private final List snippets = new ArrayList<>(); + + /** + * Specify if this container is empty. + * @return {@code true} if no task 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. + */ + public void add(Set importedTypes, Consumer writer) { + this.snippets.add(new GradleSnippet(importedTypes, writer)); + } + + /** + * Register a {@code snippet} with no import. + */ + public void add(Consumer writer) { + add(Collections.emptySet(), writer); + } + +} 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 6726b3ecd2..c527f7822e 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 @@ -18,6 +18,7 @@ import java.io.StringWriter; import java.util.Comparator; +import java.util.Set; import io.spring.initializr.generator.buildsystem.BillOfMaterials; import io.spring.initializr.generator.buildsystem.Dependency; @@ -556,6 +557,67 @@ void gradleBuildWithCustomVersion() { assertThat(write(build)).contains("version = '1.2.4.RELEASE'"); } + @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"); + } + private String write(GradleBuild build) { return write(new GroovyDslGradleBuildWriter(), build); }