mirror of
https://gitee.com/dcren/initializr.git
synced 2025-04-05 17:38:06 +08:00
Introduce CodeBlock
This commit introduces a way to build more complex statement, including multi statements and nested method invocations. CodeBlock is heavily inspired from Square's JavaPoet project. A CodeBlock is an immutable piece of code that provide the imports that are needed and can emit code to an IndentingWriter. This commit also migrates the use of expressions in Java, Kotlin, and Groovy to the newly introduced CodeBlock. Those are deprecated in favor of CodeBlock. Closes gh-1043
This commit is contained in:
parent
be0d541d4d
commit
8acbad503a
initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code
groovy
java
kotlin
initializr-generator/src
main/java/io/spring/initializr/generator/language
CodeBlock.java
groovy
GroovyExpression.javaGroovyExpressionStatement.javaGroovyMethodDeclaration.javaGroovyMethodInvocation.javaGroovyReturnStatement.javaGroovySourceCodeWriter.javaGroovyStatement.java
java
JavaExpression.javaJavaExpressionStatement.javaJavaMethodDeclaration.javaJavaMethodInvocation.javaJavaReturnStatement.javaJavaSourceCodeWriter.javaJavaStatement.java
kotlin
test/java/io/spring/initializr/generator/language
@ -23,11 +23,9 @@ import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
|
||||
import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
|
||||
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.groovy.GroovyExpressionStatement;
|
||||
import io.spring.initializr.generator.language.groovy.GroovyMethodDeclaration;
|
||||
import io.spring.initializr.generator.language.groovy.GroovyMethodInvocation;
|
||||
import io.spring.initializr.generator.language.groovy.GroovyReturnStatement;
|
||||
import io.spring.initializr.generator.language.groovy.GroovyTypeDeclaration;
|
||||
import io.spring.initializr.generator.packaging.war.WarPackaging;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
@ -58,14 +56,16 @@ class GroovyProjectGenerationDefaultContributorsConfiguration {
|
||||
.modifiers(Modifier.PUBLIC | Modifier.STATIC)
|
||||
.returning("void")
|
||||
.parameters(new Parameter("java.lang.String[]", "args"))
|
||||
.body(new GroovyExpressionStatement(new GroovyMethodInvocation("org.springframework.boot.SpringApplication",
|
||||
"run", typeDeclaration.getName(), "args"))));
|
||||
.body(CodeBlock.ofStatement("$T.run($L, args)", "org.springframework.boot.SpringApplication",
|
||||
typeDeclaration.getName())));
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestApplicationTypeCustomizer<GroovyTypeDeclaration> junitJupiterTestMethodContributor() {
|
||||
return (typeDeclaration) -> {
|
||||
GroovyMethodDeclaration method = GroovyMethodDeclaration.method("contextLoads").returning("void").body();
|
||||
GroovyMethodDeclaration method = GroovyMethodDeclaration.method("contextLoads")
|
||||
.returning("void")
|
||||
.body(CodeBlock.of(""));
|
||||
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
|
||||
typeDeclaration.addMethodDeclaration(method);
|
||||
};
|
||||
@ -92,8 +92,7 @@ class GroovyProjectGenerationDefaultContributorsConfiguration {
|
||||
.returning("org.springframework.boot.builder.SpringApplicationBuilder")
|
||||
.parameters(
|
||||
new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application"))
|
||||
.body(new GroovyReturnStatement(
|
||||
new GroovyMethodInvocation("application", "sources", description.getApplicationName())));
|
||||
.body(CodeBlock.ofStatement("application.sources($L)", description.getApplicationName()));
|
||||
configure.annotate(Annotation.name("java.lang.Override"));
|
||||
typeDeclaration.addMethodDeclaration(configure);
|
||||
};
|
||||
|
@ -20,11 +20,9 @@ import java.lang.reflect.Modifier;
|
||||
|
||||
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.java.JavaExpressionStatement;
|
||||
import io.spring.initializr.generator.language.java.JavaMethodDeclaration;
|
||||
import io.spring.initializr.generator.language.java.JavaMethodInvocation;
|
||||
import io.spring.initializr.generator.language.java.JavaReturnStatement;
|
||||
import io.spring.initializr.generator.language.java.JavaTypeDeclaration;
|
||||
import io.spring.initializr.generator.packaging.war.WarPackaging;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
@ -52,15 +50,17 @@ class JavaProjectGenerationDefaultContributorsConfiguration {
|
||||
.modifiers(Modifier.PUBLIC | Modifier.STATIC)
|
||||
.returning("void")
|
||||
.parameters(new Parameter("java.lang.String[]", "args"))
|
||||
.body(new JavaExpressionStatement(new JavaMethodInvocation("org.springframework.boot.SpringApplication",
|
||||
"run", typeDeclaration.getName() + ".class", "args"))));
|
||||
.body(CodeBlock.ofStatement("$T.run($L.class, args)", "org.springframework.boot.SpringApplication",
|
||||
typeDeclaration.getName())));
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
TestApplicationTypeCustomizer<JavaTypeDeclaration> junitJupiterTestMethodContributor() {
|
||||
return (typeDeclaration) -> {
|
||||
JavaMethodDeclaration method = JavaMethodDeclaration.method("contextLoads").returning("void").body();
|
||||
JavaMethodDeclaration method = JavaMethodDeclaration.method("contextLoads")
|
||||
.returning("void")
|
||||
.body(CodeBlock.of(""));
|
||||
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
|
||||
typeDeclaration.addMethodDeclaration(method);
|
||||
};
|
||||
@ -83,8 +83,8 @@ class JavaProjectGenerationDefaultContributorsConfiguration {
|
||||
.returning("org.springframework.boot.builder.SpringApplicationBuilder")
|
||||
.parameters(
|
||||
new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application"))
|
||||
.body(new JavaReturnStatement(new JavaMethodInvocation("application", "sources",
|
||||
description.getApplicationName() + ".class")));
|
||||
.body(CodeBlock.ofStatement("return application.sources($L.class)",
|
||||
description.getApplicationName()));
|
||||
configure.annotate(Annotation.name("java.lang.Override"));
|
||||
typeDeclaration.addMethodDeclaration(configure);
|
||||
};
|
||||
|
@ -23,14 +23,11 @@ import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
|
||||
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
|
||||
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinCompilationUnit;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinExpressionStatement;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinFunctionDeclaration;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinFunctionInvocation;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinModifier;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinReifiedFunctionInvocation;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinReturnStatement;
|
||||
import io.spring.initializr.generator.language.kotlin.KotlinTypeDeclaration;
|
||||
import io.spring.initializr.generator.packaging.war.WarPackaging;
|
||||
import io.spring.initializr.generator.project.ProjectDescription;
|
||||
@ -56,7 +53,8 @@ class KotlinProjectGenerationDefaultContributorsConfiguration {
|
||||
@Bean
|
||||
TestApplicationTypeCustomizer<KotlinTypeDeclaration> junitJupiterTestMethodContributor() {
|
||||
return (typeDeclaration) -> {
|
||||
KotlinFunctionDeclaration function = KotlinFunctionDeclaration.function("contextLoads").body();
|
||||
KotlinFunctionDeclaration function = KotlinFunctionDeclaration.function("contextLoads")
|
||||
.body(CodeBlock.of(""));
|
||||
function.annotate(Annotation.name("org.junit.jupiter.api.Test"));
|
||||
typeDeclaration.addFunctionDeclaration(function);
|
||||
};
|
||||
@ -96,12 +94,10 @@ class KotlinProjectGenerationDefaultContributorsConfiguration {
|
||||
@Bean
|
||||
MainCompilationUnitCustomizer<KotlinTypeDeclaration, KotlinCompilationUnit> mainFunctionContributor(
|
||||
ProjectDescription description) {
|
||||
return (compilationUnit) -> compilationUnit.addTopLevelFunction(
|
||||
KotlinFunctionDeclaration.function("main")
|
||||
.parameters(new Parameter("Array<String>", "args"))
|
||||
.body(new KotlinExpressionStatement(
|
||||
new KotlinReifiedFunctionInvocation("org.springframework.boot.runApplication",
|
||||
description.getApplicationName(), "*args"))));
|
||||
return (compilationUnit) -> compilationUnit.addTopLevelFunction(KotlinFunctionDeclaration.function("main")
|
||||
.parameters(new Parameter("Array<String>", "args"))
|
||||
.body(CodeBlock.ofStatement("$T<$L>(*args)", "org.springframework.boot.runApplication",
|
||||
description.getApplicationName())));
|
||||
}
|
||||
|
||||
}
|
||||
@ -122,8 +118,8 @@ class KotlinProjectGenerationDefaultContributorsConfiguration {
|
||||
.returning("org.springframework.boot.builder.SpringApplicationBuilder")
|
||||
.parameters(
|
||||
new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application"))
|
||||
.body(new KotlinReturnStatement(new KotlinFunctionInvocation("application", "sources",
|
||||
description.getApplicationName() + "::class.java")));
|
||||
.body(CodeBlock.ofStatement("return application.sources($L::class.java)",
|
||||
description.getApplicationName()));
|
||||
typeDeclaration.addFunctionDeclaration(configure);
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.language;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriter;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A fragment of code, potentially containing declarations, or statements. CodeBlocks are
|
||||
* not validated.
|
||||
* <p>
|
||||
* Code blocks support placeholders identified by {@code $}. The following placeholders
|
||||
* are supported:
|
||||
* <ul>
|
||||
* <li>{@code $L} emits a literal value. Arguments for literals may be plain String,
|
||||
* primitives, or any type where the {@code toString()} representation can be used.
|
||||
* <li>{@code $S} escapes the value as a string, wraps it with double quotes, and emits
|
||||
* that. Emit {@code "null"} if the value is {@code null}. Does not handle multi-line
|
||||
* strings.
|
||||
* <li>{@code $T} emits a type reference. Arguments for types may be plain
|
||||
* {@linkplain Class classes}, fully qualified class names, and fully qualified
|
||||
* functions.</li>
|
||||
* <li>{@code $$} emits a dollar sign.
|
||||
* <li>{@code $]} ends a statement and emits the configured
|
||||
* {@linkplain FormattingOptions#statementSeparator() statement separator}.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Code blocks can be {@linkplain #write(IndentingWriter, FormattingOptions) rendered}
|
||||
* using an {@link IndentingWriter} and {@link FormattingOptions}.
|
||||
* <p>
|
||||
* This class is heavily inspired by JavaPoet.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public final class CodeBlock {
|
||||
|
||||
/**
|
||||
* Standard {@link FormattingOptions} for Java.
|
||||
*/
|
||||
public static final FormattingOptions JAVA_FORMATTING_OPTIONS = new JavaFormattingOptions();
|
||||
|
||||
private final List<String> parts;
|
||||
|
||||
private final List<Object> args;
|
||||
|
||||
private final List<String> imports;
|
||||
|
||||
private CodeBlock(Builder builder) {
|
||||
this.parts = List.copyOf(builder.parts);
|
||||
this.args = List.copyOf(builder.args);
|
||||
this.imports = List.copyOf(builder.imports);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the imports this instance contributes.
|
||||
* @return the imports.
|
||||
*/
|
||||
public List<String> getImports() {
|
||||
return this.imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write this instance using the specified writer.
|
||||
* @param writer the writer to use
|
||||
* @param options the formatting options to use
|
||||
*/
|
||||
public void write(IndentingWriter writer, FormattingOptions options) {
|
||||
int argIndex = 0;
|
||||
for (String part : this.parts) {
|
||||
switch (part) {
|
||||
case "$L" -> writer.print(String.valueOf(this.args.get(argIndex++)));
|
||||
case "$S" -> {
|
||||
String value = (String) this.args.get(argIndex++);
|
||||
String valueToEmit = (value != null) ? quote(value) : "null";
|
||||
writer.print(valueToEmit);
|
||||
}
|
||||
case "$T" -> {
|
||||
String className = (String) this.args.get(argIndex++);
|
||||
writer.print(className);
|
||||
}
|
||||
case "$]" -> writer.println(options.statementSeparator());
|
||||
case "$$" -> writer.print("$");
|
||||
default -> writer.print(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String quote(String value) {
|
||||
StringBuilder result = new StringBuilder(value.length() + 2);
|
||||
result.append('"');
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '\'') {
|
||||
result.append("'");
|
||||
continue;
|
||||
}
|
||||
if (c == '\"') {
|
||||
result.append("\\\"");
|
||||
continue;
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
result.append('"');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a code block using the specified code and optional arguments. To create a
|
||||
* single statement, consider {@link #ofStatement(String, Object...)} instead.
|
||||
* @param format the code
|
||||
* @param args the arguments, if any
|
||||
* @return a new instance
|
||||
* @see #builder()
|
||||
*/
|
||||
public static CodeBlock of(String format, Object... args) {
|
||||
return new Builder().add(format, args).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a code block with a single statement using the specified code and optional
|
||||
* arguments.
|
||||
* @param format the statement
|
||||
* @param args the arguments, if any
|
||||
* @return a new instance
|
||||
* @see #builder()
|
||||
*/
|
||||
public static CodeBlock ofStatement(String format, Object... args) {
|
||||
return new Builder().addStatement(format, args).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new builder.
|
||||
* @return a code block builder
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private final List<String> parts = new ArrayList<>();
|
||||
|
||||
private final List<Object> args = new ArrayList<>();
|
||||
|
||||
private final List<String> imports = new ArrayList<>();
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified {@link CodeBlock}, without any extra line or statement
|
||||
* separator.
|
||||
* @param codeBlock the code to add
|
||||
* @return this for method chaining
|
||||
*/
|
||||
public Builder add(CodeBlock codeBlock) {
|
||||
this.parts.addAll(codeBlock.parts);
|
||||
this.args.addAll(codeBlock.args);
|
||||
this.imports.addAll(codeBlock.imports);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add more code using the specified code and optional arguments.
|
||||
* @param format the code
|
||||
* @param args the arguments, if any
|
||||
* @return this for method chaining
|
||||
*/
|
||||
public Builder add(String format, Object... args) {
|
||||
int relativeParameterCount = 0;
|
||||
|
||||
for (int p = 0; p < format.length();) {
|
||||
if (format.charAt(p) != '$') {
|
||||
int nextP = format.indexOf('$', p + 1);
|
||||
nextP = (nextP != -1) ? nextP : format.length();
|
||||
this.parts.add(format.substring(p, nextP));
|
||||
p = nextP;
|
||||
continue;
|
||||
}
|
||||
p++; // placeholder
|
||||
if (p >= format.length()) {
|
||||
throw new IllegalArgumentException("Should not end with '$': '%s'".formatted(format));
|
||||
}
|
||||
char placeHolderType = format.charAt(p++);
|
||||
if (!isNoArgPlaceholder(placeHolderType)) {
|
||||
int index = relativeParameterCount;
|
||||
relativeParameterCount++;
|
||||
if (index >= args.length) {
|
||||
throw new IllegalArgumentException("Argument mismatch for '%s', expected at least %s %s, got %s"
|
||||
.formatted(format, relativeParameterCount,
|
||||
(relativeParameterCount > 1) ? "arguments" : "argument", args.length));
|
||||
}
|
||||
addArgument(format, placeHolderType, args[index]);
|
||||
}
|
||||
this.parts.add("$" + placeHolderType);
|
||||
}
|
||||
if (relativeParameterCount != args.length) {
|
||||
throw new IllegalArgumentException(
|
||||
"Argument mismatch for '%s', expected %s %s, got %s".formatted(format, relativeParameterCount,
|
||||
(relativeParameterCount > 1) ? "arguments" : "argument", args.length));
|
||||
}
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
private boolean isNoArgPlaceholder(char c) {
|
||||
return c == '$' || c == ']';
|
||||
}
|
||||
|
||||
private void addArgument(String format, char c, Object arg) {
|
||||
switch (c) {
|
||||
case 'L' -> this.args.add(arg);
|
||||
case 'S' -> this.args.add(argToString(arg));
|
||||
case 'T' -> this.args.add(argToType(arg));
|
||||
default -> throw new IllegalArgumentException(
|
||||
String.format("Unsupported placeholder '$%s' for '%s'", c, format));
|
||||
}
|
||||
}
|
||||
|
||||
private String argToString(Object o) {
|
||||
return (o != null) ? String.valueOf(o) : null;
|
||||
}
|
||||
|
||||
private String argToType(Object arg) {
|
||||
if (arg instanceof Class type) {
|
||||
this.imports.add(type.getName());
|
||||
return type.getSimpleName();
|
||||
}
|
||||
if (arg instanceof String className) {
|
||||
this.imports.add(className);
|
||||
return ClassUtils.getShortName(className);
|
||||
}
|
||||
throw new IllegalArgumentException("Failed to extract type from '%s'".formatted(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified {@link CodeBlock} as a statement.
|
||||
* @param codeBlock the code to add
|
||||
* @return this for method chaining
|
||||
*/
|
||||
public Builder addStatement(CodeBlock codeBlock) {
|
||||
add(codeBlock);
|
||||
this.parts.add("$]");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add more code using the specified code and optional arguments and indicate that
|
||||
* this statement is finished.
|
||||
* @param format the code
|
||||
* @param args the arguments, if any
|
||||
* @return this for method chaining
|
||||
*/
|
||||
public Builder addStatement(String format, Object... args) {
|
||||
add(format, args);
|
||||
this.parts.add("$]");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link CodeBlock} with the current state of this builder.
|
||||
* @return a {@link CodeBlock}
|
||||
*/
|
||||
public CodeBlock build() {
|
||||
return new CodeBlock(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Strategy interface to customize formatting of generated code block.
|
||||
*/
|
||||
public interface FormattingOptions {
|
||||
|
||||
/**
|
||||
* Return the separator to use to end a statement.
|
||||
* @return the statement separator
|
||||
*/
|
||||
String statementSeparator();
|
||||
|
||||
}
|
||||
|
||||
private static class JavaFormattingOptions implements FormattingOptions {
|
||||
|
||||
@Override
|
||||
public String statementSeparator() {
|
||||
return ";";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.groovy;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A Groovy expression.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class GroovyExpression {
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.groovy;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement that contains a single expression.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class GroovyExpressionStatement extends GroovyStatement {
|
||||
|
||||
private final GroovyExpression expression;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -24,6 +24,7 @@ import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
|
||||
/**
|
||||
@ -43,15 +44,26 @@ public final class GroovyMethodDeclaration implements Annotatable {
|
||||
|
||||
private final List<Parameter> parameters;
|
||||
|
||||
private final CodeBlock code;
|
||||
|
||||
private final List<GroovyStatement> statements;
|
||||
|
||||
private GroovyMethodDeclaration(String name, String returnType, int modifiers, List<Parameter> parameters,
|
||||
List<GroovyStatement> statements) {
|
||||
this.name = name;
|
||||
this.returnType = returnType;
|
||||
this.modifiers = modifiers;
|
||||
this.parameters = parameters;
|
||||
this.statements = statements;
|
||||
private GroovyMethodDeclaration(Builder builder, CodeBlock code) {
|
||||
this.name = builder.name;
|
||||
this.returnType = builder.returnType;
|
||||
this.modifiers = builder.modifiers;
|
||||
this.parameters = List.copyOf(builder.parameters);
|
||||
this.code = code;
|
||||
this.statements = Collections.emptyList();
|
||||
}
|
||||
|
||||
private GroovyMethodDeclaration(Builder builder, List<GroovyStatement> statements) {
|
||||
this.name = builder.name;
|
||||
this.returnType = builder.returnType;
|
||||
this.modifiers = builder.modifiers;
|
||||
this.parameters = List.copyOf(builder.parameters);
|
||||
this.code = CodeBlock.of("");
|
||||
this.statements = List.copyOf(statements);
|
||||
}
|
||||
|
||||
public static Builder method(String name) {
|
||||
@ -74,6 +86,11 @@ public final class GroovyMethodDeclaration implements Annotatable {
|
||||
return this.modifiers;
|
||||
}
|
||||
|
||||
CodeBlock getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public List<GroovyStatement> getStatements() {
|
||||
return this.statements;
|
||||
}
|
||||
@ -120,9 +137,13 @@ public final class GroovyMethodDeclaration implements Annotatable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public GroovyMethodDeclaration body(CodeBlock code) {
|
||||
return new GroovyMethodDeclaration(this, code);
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public GroovyMethodDeclaration body(GroovyStatement... statements) {
|
||||
return new GroovyMethodDeclaration(this.name, this.returnType, this.modifiers, this.parameters,
|
||||
Arrays.asList(statements));
|
||||
return new GroovyMethodDeclaration(this, Arrays.asList(statements));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -19,11 +19,15 @@ package io.spring.initializr.generator.language.groovy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* An invocation of a method.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class GroovyMethodInvocation extends GroovyExpression {
|
||||
|
||||
private final String target;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.groovy;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A return statement.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class GroovyReturnStatement extends GroovyStatement {
|
||||
|
||||
private final GroovyExpression expression;
|
||||
|
@ -38,6 +38,7 @@ import io.spring.initializr.generator.io.IndentingWriter;
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock.FormattingOptions;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceCode;
|
||||
import io.spring.initializr.generator.language.SourceCodeWriter;
|
||||
@ -51,6 +52,8 @@ import io.spring.initializr.generator.language.SourceStructure;
|
||||
*/
|
||||
public class GroovySourceCodeWriter implements SourceCodeWriter<GroovySourceCode> {
|
||||
|
||||
private static final FormattingOptions FORMATTING_OPTIONS = new GroovyFormattingOptions();
|
||||
|
||||
private static final Map<Predicate<Integer>, String> TYPE_MODIFIERS;
|
||||
|
||||
private static final Map<Predicate<Integer>, String> FIELD_MODIFIERS;
|
||||
@ -208,21 +211,27 @@ public class GroovySourceCodeWriter implements SourceCodeWriter<GroovySourceCode
|
||||
}
|
||||
writer.println(") {");
|
||||
writer.indented(() -> {
|
||||
List<GroovyStatement> statements = methodDeclaration.getStatements();
|
||||
for (GroovyStatement statement : statements) {
|
||||
if (statement instanceof GroovyExpressionStatement) {
|
||||
writeExpression(writer, ((GroovyExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof GroovyReturnStatement) {
|
||||
writeExpression(writer, ((GroovyReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println();
|
||||
}
|
||||
methodDeclaration.getCode().write(writer, FORMATTING_OPTIONS);
|
||||
writeStatements(writer, methodDeclaration);
|
||||
});
|
||||
writer.println("}");
|
||||
writer.println();
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void writeStatements(IndentingWriter writer, GroovyMethodDeclaration methodDeclaration) {
|
||||
List<GroovyStatement> statements = methodDeclaration.getStatements();
|
||||
for (GroovyStatement statement : statements) {
|
||||
if (statement instanceof GroovyExpressionStatement) {
|
||||
writeExpression(writer, ((GroovyExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof GroovyReturnStatement) {
|
||||
writeExpression(writer, ((GroovyReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeModifiers(IndentingWriter writer, Map<Predicate<Integer>, String> availableModifiers,
|
||||
int declaredModifiers) {
|
||||
String modifiers = availableModifiers.entrySet()
|
||||
@ -267,21 +276,27 @@ public class GroovySourceCodeWriter implements SourceCodeWriter<GroovySourceCode
|
||||
imports.addAll(getRequiredImports(methodDeclaration.getAnnotations(), this::determineImports));
|
||||
imports.addAll(getRequiredImports(methodDeclaration.getParameters(),
|
||||
(parameter) -> Collections.singletonList(parameter.getType())));
|
||||
imports.addAll(getRequiredImports(
|
||||
methodDeclaration.getStatements()
|
||||
.stream()
|
||||
.filter(GroovyExpressionStatement.class::isInstance)
|
||||
.map(GroovyExpressionStatement.class::cast)
|
||||
.map(GroovyExpressionStatement::getExpression)
|
||||
.filter(GroovyMethodInvocation.class::isInstance)
|
||||
.map(GroovyMethodInvocation.class::cast),
|
||||
(methodInvocation) -> Collections.singleton(methodInvocation.getTarget())));
|
||||
imports.addAll(methodDeclaration.getCode().getImports());
|
||||
determineImportsFromStatements(imports, methodDeclaration);
|
||||
}
|
||||
}
|
||||
Collections.sort(imports);
|
||||
return new LinkedHashSet<>(imports);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void determineImportsFromStatements(List<String> imports, GroovyMethodDeclaration methodDeclaration) {
|
||||
imports.addAll(getRequiredImports(
|
||||
methodDeclaration.getStatements()
|
||||
.stream()
|
||||
.filter(GroovyExpressionStatement.class::isInstance)
|
||||
.map(GroovyExpressionStatement.class::cast)
|
||||
.map(GroovyExpressionStatement::getExpression)
|
||||
.filter(GroovyMethodInvocation.class::isInstance)
|
||||
.map(GroovyMethodInvocation.class::cast),
|
||||
(methodInvocation) -> Collections.singleton(methodInvocation.getTarget())));
|
||||
}
|
||||
|
||||
private Collection<String> determineImports(Annotation annotation) {
|
||||
List<String> imports = new ArrayList<>();
|
||||
imports.add(annotation.getName());
|
||||
@ -325,4 +340,13 @@ public class GroovySourceCodeWriter implements SourceCodeWriter<GroovySourceCode
|
||||
return !"java.lang".equals(packageName);
|
||||
}
|
||||
|
||||
static class GroovyFormattingOptions implements FormattingOptions {
|
||||
|
||||
@Override
|
||||
public String statementSeparator() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.groovy;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement in Groovy.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class GroovyStatement {
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.java;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A Java expression.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class JavaExpression {
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.java;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement that contains a single expression.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class JavaExpressionStatement extends JavaStatement {
|
||||
|
||||
private final JavaExpression expression;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -23,6 +23,7 @@ import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
|
||||
/**
|
||||
@ -42,14 +43,26 @@ public final class JavaMethodDeclaration implements Annotatable {
|
||||
|
||||
private final List<Parameter> parameters;
|
||||
|
||||
private final CodeBlock code;
|
||||
|
||||
private final List<JavaStatement> statements;
|
||||
|
||||
private JavaMethodDeclaration(Builder builder, CodeBlock code) {
|
||||
this.name = builder.name;
|
||||
this.returnType = builder.returnType;
|
||||
this.modifiers = builder.modifiers;
|
||||
this.parameters = List.copyOf(builder.parameters);
|
||||
this.code = code;
|
||||
this.statements = Collections.emptyList();
|
||||
}
|
||||
|
||||
private JavaMethodDeclaration(String name, String returnType, int modifiers, List<Parameter> parameters,
|
||||
List<JavaStatement> statements) {
|
||||
this.name = name;
|
||||
this.returnType = returnType;
|
||||
this.modifiers = modifiers;
|
||||
this.parameters = parameters;
|
||||
this.code = CodeBlock.of((""));
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
@ -73,6 +86,11 @@ public final class JavaMethodDeclaration implements Annotatable {
|
||||
return this.modifiers;
|
||||
}
|
||||
|
||||
CodeBlock getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public List<JavaStatement> getStatements() {
|
||||
return this.statements;
|
||||
}
|
||||
@ -119,6 +137,11 @@ public final class JavaMethodDeclaration implements Annotatable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public JavaMethodDeclaration body(CodeBlock code) {
|
||||
return new JavaMethodDeclaration(this, code);
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public JavaMethodDeclaration body(JavaStatement... statements) {
|
||||
return new JavaMethodDeclaration(this.name, this.returnType, this.modifiers, this.parameters,
|
||||
Arrays.asList(statements));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -19,11 +19,15 @@ package io.spring.initializr.generator.language.java;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* An invocation of a method.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class JavaMethodInvocation extends JavaExpression {
|
||||
|
||||
private final String target;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.java;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A return statement.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class JavaReturnStatement extends JavaStatement {
|
||||
|
||||
private final JavaExpression expression;
|
||||
|
@ -38,6 +38,7 @@ import io.spring.initializr.generator.io.IndentingWriter;
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceCode;
|
||||
import io.spring.initializr.generator.language.SourceCodeWriter;
|
||||
@ -210,22 +211,28 @@ public class JavaSourceCodeWriter implements SourceCodeWriter<JavaSourceCode> {
|
||||
}
|
||||
writer.println(") {");
|
||||
writer.indented(() -> {
|
||||
List<JavaStatement> statements = methodDeclaration.getStatements();
|
||||
for (JavaStatement statement : statements) {
|
||||
if (statement instanceof JavaExpressionStatement) {
|
||||
writeExpression(writer, ((JavaExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof JavaReturnStatement) {
|
||||
writer.print("return ");
|
||||
writeExpression(writer, ((JavaReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println(";");
|
||||
}
|
||||
methodDeclaration.getCode().write(writer, CodeBlock.JAVA_FORMATTING_OPTIONS);
|
||||
writeJavaStatements(writer, methodDeclaration);
|
||||
});
|
||||
writer.println("}");
|
||||
writer.println();
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void writeJavaStatements(IndentingWriter writer, JavaMethodDeclaration methodDeclaration) {
|
||||
List<JavaStatement> statements = methodDeclaration.getStatements();
|
||||
for (JavaStatement statement : statements) {
|
||||
if (statement instanceof JavaExpressionStatement) {
|
||||
writeExpression(writer, ((JavaExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof JavaReturnStatement) {
|
||||
writer.print("return ");
|
||||
writeExpression(writer, ((JavaReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println(";");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeModifiers(IndentingWriter writer, Map<Predicate<Integer>, String> availableModifiers,
|
||||
int declaredModifiers) {
|
||||
String modifiers = availableModifiers.entrySet()
|
||||
@ -270,21 +277,27 @@ public class JavaSourceCodeWriter implements SourceCodeWriter<JavaSourceCode> {
|
||||
imports.addAll(getRequiredImports(methodDeclaration.getAnnotations(), this::determineImports));
|
||||
imports.addAll(getRequiredImports(methodDeclaration.getParameters(),
|
||||
(parameter) -> Collections.singletonList(parameter.getType())));
|
||||
imports.addAll(getRequiredImports(
|
||||
methodDeclaration.getStatements()
|
||||
.stream()
|
||||
.filter(JavaExpressionStatement.class::isInstance)
|
||||
.map(JavaExpressionStatement.class::cast)
|
||||
.map(JavaExpressionStatement::getExpression)
|
||||
.filter(JavaMethodInvocation.class::isInstance)
|
||||
.map(JavaMethodInvocation.class::cast),
|
||||
(methodInvocation) -> Collections.singleton(methodInvocation.getTarget())));
|
||||
determineImportsFromStatements(imports, methodDeclaration);
|
||||
imports.addAll(methodDeclaration.getCode().getImports());
|
||||
}
|
||||
}
|
||||
Collections.sort(imports);
|
||||
return new LinkedHashSet<>(imports);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void determineImportsFromStatements(List<String> imports, JavaMethodDeclaration methodDeclaration) {
|
||||
imports.addAll(getRequiredImports(
|
||||
methodDeclaration.getStatements()
|
||||
.stream()
|
||||
.filter(JavaExpressionStatement.class::isInstance)
|
||||
.map(JavaExpressionStatement.class::cast)
|
||||
.map(JavaExpressionStatement::getExpression)
|
||||
.filter(JavaMethodInvocation.class::isInstance)
|
||||
.map(JavaMethodInvocation.class::cast),
|
||||
(methodInvocation) -> Collections.singleton(methodInvocation.getTarget())));
|
||||
}
|
||||
|
||||
private Collection<String> determineImports(Annotation annotation) {
|
||||
List<String> imports = new ArrayList<>();
|
||||
imports.add(annotation.getName());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.java;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement in Java.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class JavaStatement {
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.kotlin;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A Kotlin expression.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinExpression {
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.kotlin;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement that contains a single expression.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinExpressionStatement extends KotlinStatement {
|
||||
|
||||
private final KotlinExpression expression;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -23,6 +23,7 @@ import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
|
||||
/**
|
||||
@ -42,15 +43,26 @@ public final class KotlinFunctionDeclaration implements Annotatable {
|
||||
|
||||
private final List<Parameter> parameters;
|
||||
|
||||
private final CodeBlock code;
|
||||
|
||||
private final List<KotlinStatement> statements;
|
||||
|
||||
private KotlinFunctionDeclaration(String name, String returnType, List<KotlinModifier> modifiers,
|
||||
List<Parameter> parameters, List<KotlinStatement> statements) {
|
||||
this.name = name;
|
||||
this.returnType = returnType;
|
||||
this.modifiers = modifiers;
|
||||
this.parameters = parameters;
|
||||
this.statements = statements;
|
||||
private KotlinFunctionDeclaration(Builder builder, CodeBlock code) {
|
||||
this.name = builder.name;
|
||||
this.returnType = builder.returnType;
|
||||
this.modifiers = builder.modifiers;
|
||||
this.parameters = List.copyOf(builder.parameters);
|
||||
this.code = code;
|
||||
this.statements = Collections.emptyList();
|
||||
}
|
||||
|
||||
private KotlinFunctionDeclaration(Builder builder, List<KotlinStatement> statements) {
|
||||
this.name = builder.name;
|
||||
this.returnType = builder.returnType;
|
||||
this.modifiers = builder.modifiers;
|
||||
this.parameters = List.copyOf(builder.parameters);
|
||||
this.code = CodeBlock.of("");
|
||||
this.statements = List.copyOf(statements);
|
||||
}
|
||||
|
||||
public static Builder function(String name) {
|
||||
@ -73,6 +85,11 @@ public final class KotlinFunctionDeclaration implements Annotatable {
|
||||
return this.modifiers;
|
||||
}
|
||||
|
||||
CodeBlock getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public List<KotlinStatement> getStatements() {
|
||||
return this.statements;
|
||||
}
|
||||
@ -119,9 +136,13 @@ public final class KotlinFunctionDeclaration implements Annotatable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public KotlinFunctionDeclaration body(CodeBlock code) {
|
||||
return new KotlinFunctionDeclaration(this, code);
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public KotlinFunctionDeclaration body(KotlinStatement... statements) {
|
||||
return new KotlinFunctionDeclaration(this.name, this.returnType, this.modifiers, this.parameters,
|
||||
Arrays.asList(statements));
|
||||
return new KotlinFunctionDeclaration(this, Arrays.asList(statements));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -19,11 +19,15 @@ package io.spring.initializr.generator.language.kotlin;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* An invocation of a function.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinFunctionInvocation extends KotlinExpression {
|
||||
|
||||
private final String target;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -24,6 +24,7 @@ import java.util.function.Consumer;
|
||||
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* Declaration of a property written in Kotlin.
|
||||
@ -197,6 +198,8 @@ public final class KotlinPropertyDeclaration implements Annotatable {
|
||||
|
||||
private final List<Annotation> annotations = new ArrayList<>();
|
||||
|
||||
private CodeBlock code;
|
||||
|
||||
private KotlinExpressionStatement body;
|
||||
|
||||
private final T parent;
|
||||
@ -213,11 +216,17 @@ public final class KotlinPropertyDeclaration implements Annotatable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public AccessorBuilder<?> withBody(KotlinExpressionStatement expressionStatement) {
|
||||
this.body = expressionStatement;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccessorBuilder<?> withBody(CodeBlock code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public T buildAccessor() {
|
||||
this.accessorFunction.accept(new Accessor(this));
|
||||
return this.parent;
|
||||
@ -229,17 +238,25 @@ public final class KotlinPropertyDeclaration implements Annotatable {
|
||||
|
||||
private final List<Annotation> annotations = new ArrayList<>();
|
||||
|
||||
private final CodeBlock code;
|
||||
|
||||
private final KotlinExpressionStatement body;
|
||||
|
||||
Accessor(AccessorBuilder<?> builder) {
|
||||
this.annotations.addAll(builder.annotations);
|
||||
this.code = builder.code;
|
||||
this.body = builder.body;
|
||||
}
|
||||
|
||||
boolean isEmptyBody() {
|
||||
return this.body == null;
|
||||
return (this.body == null && this.code == null);
|
||||
}
|
||||
|
||||
CodeBlock getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
KotlinExpressionStatement getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -19,11 +19,15 @@ package io.spring.initializr.generator.language.kotlin;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* Invocation of a function with a reified type parameter.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinReifiedFunctionInvocation extends KotlinExpression {
|
||||
|
||||
private final String name;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.kotlin;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A return statement.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinReturnStatement extends KotlinStatement {
|
||||
|
||||
private final KotlinExpression expression;
|
||||
|
@ -34,6 +34,7 @@ import io.spring.initializr.generator.io.IndentingWriter;
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotatable;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock.FormattingOptions;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceCode;
|
||||
import io.spring.initializr.generator.language.SourceCodeWriter;
|
||||
@ -47,6 +48,8 @@ import io.spring.initializr.generator.language.SourceStructure;
|
||||
*/
|
||||
public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode> {
|
||||
|
||||
private static final FormattingOptions FORMATTING_OPTIONS = new KotlinFormattingOptions();
|
||||
|
||||
private final IndentingWriterFactory indentingWriterFactory;
|
||||
|
||||
public KotlinSourceCodeWriter(IndentingWriterFactory indentingWriterFactory) {
|
||||
@ -157,7 +160,12 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode
|
||||
writer.print(accessorName);
|
||||
if (!accessor.isEmptyBody()) {
|
||||
writer.print("() = ");
|
||||
writeExpression(writer, accessor.getBody().getExpression());
|
||||
if (accessor.getCode() != null) {
|
||||
accessor.getCode().write(writer, FORMATTING_OPTIONS);
|
||||
}
|
||||
else if (accessor.getBody() != null) {
|
||||
writeExpression(writer, accessor.getBody().getExpression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,22 +186,28 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode
|
||||
writer.print(": " + getUnqualifiedName(functionDeclaration.getReturnType()));
|
||||
}
|
||||
writer.println(" {");
|
||||
List<KotlinStatement> statements = functionDeclaration.getStatements();
|
||||
writer.indented(() -> {
|
||||
for (KotlinStatement statement : statements) {
|
||||
if (statement instanceof KotlinExpressionStatement) {
|
||||
writeExpression(writer, ((KotlinExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof KotlinReturnStatement) {
|
||||
writer.print("return ");
|
||||
writeExpression(writer, ((KotlinReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println("");
|
||||
}
|
||||
functionDeclaration.getCode().write(writer, FORMATTING_OPTIONS);
|
||||
writeStatements(writer, functionDeclaration);
|
||||
});
|
||||
writer.println("}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void writeStatements(IndentingWriter writer, KotlinFunctionDeclaration functionDeclaration) {
|
||||
List<KotlinStatement> statements = functionDeclaration.getStatements();
|
||||
for (KotlinStatement statement : statements) {
|
||||
if (statement instanceof KotlinExpressionStatement) {
|
||||
writeExpression(writer, ((KotlinExpressionStatement) statement).getExpression());
|
||||
}
|
||||
else if (statement instanceof KotlinReturnStatement) {
|
||||
writer.print("return ");
|
||||
writeExpression(writer, ((KotlinReturnStatement) statement).getExpression());
|
||||
}
|
||||
writer.println("");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAnnotations(IndentingWriter writer, Annotatable annotatable) {
|
||||
for (Annotation annotation : annotatable.getAnnotations()) {
|
||||
writeAnnotation(writer, annotation, true);
|
||||
@ -316,6 +330,7 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode
|
||||
imports.addAll(getRequiredImports(functionDeclaration.getAnnotations(), this::determineImports));
|
||||
imports.addAll(getRequiredImports(functionDeclaration.getParameters(),
|
||||
(parameter) -> Collections.singleton(parameter.getType())));
|
||||
imports.addAll(functionDeclaration.getCode().getImports());
|
||||
imports.addAll(getRequiredImports(
|
||||
getKotlinExpressions(functionDeclaration).filter(KotlinFunctionInvocation.class::isInstance)
|
||||
.map(KotlinFunctionInvocation.class::cast),
|
||||
@ -344,6 +359,7 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode
|
||||
return imports;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private Stream<KotlinExpression> getKotlinExpressions(KotlinFunctionDeclaration functionDeclaration) {
|
||||
return functionDeclaration.getStatements()
|
||||
.stream()
|
||||
@ -378,4 +394,13 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter<KotlinSourceCode
|
||||
return !"java.lang".equals(packageName);
|
||||
}
|
||||
|
||||
static class KotlinFormattingOptions implements FormattingOptions {
|
||||
|
||||
@Override
|
||||
public String statementSeparator() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@ -16,11 +16,15 @@
|
||||
|
||||
package io.spring.initializr.generator.language.kotlin;
|
||||
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
|
||||
/**
|
||||
* A statement in Kotlin.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @deprecated since 0.20.0 in favor of {@link CodeBlock}
|
||||
*/
|
||||
@Deprecated(since = "0.20.0", forRemoval = true)
|
||||
public class KotlinStatement {
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.language;
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriter;
|
||||
import io.spring.initializr.generator.io.SimpleIndentStrategy;
|
||||
import io.spring.initializr.generator.language.CodeBlock.FormattingOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link CodeBlock}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class CodeBlockTests {
|
||||
|
||||
@Test
|
||||
void codeBlockWithPlaceholderAndTooFewArguments() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CodeBlock.of("$T.doStuff()"))
|
||||
.withMessage("Argument mismatch for '$T.doStuff()', expected at least 1 argument, got 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithPlaceholderAndTooManyArguments() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CodeBlock.of("$T.doStuff()", String.class, Integer.class))
|
||||
.withMessage("Argument mismatch for '$T.doStuff()', expected 1 argument, got 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithInvalidPlaceholder() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CodeBlock.of("$X.doStuff()", 123))
|
||||
.withMessage("Unsupported placeholder '$X' for '$X.doStuff()'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithTrailingDollarSign() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CodeBlock.of("doStuff()$"))
|
||||
.withMessage("Should not end with '$': 'doStuff()$'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithStringPlaceholder() {
|
||||
CodeBlock code = CodeBlock.of("return myUtil.truncate($S)", "value");
|
||||
assertThat(writeJava(code)).isEqualTo("return myUtil.truncate(\"value\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithStringPlaceholderAndDoubleQuote() {
|
||||
CodeBlock code = CodeBlock.of("return myUtil.truncate($S)", "va\"lue");
|
||||
assertThat(writeJava(code)).isEqualTo("return myUtil.truncate(\"va\\\"lue\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithStringPlaceholderAndEscapedSingleQuote() {
|
||||
CodeBlock code = CodeBlock.of("return myUtil.truncate($S)", "va\'lue");
|
||||
assertThat(writeJava(code)).isEqualTo("return myUtil.truncate(\"va'lue\")");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithLiteralPlaceholder() {
|
||||
CodeBlock code = CodeBlock.of("return $L.truncate(myString)", "myUtil");
|
||||
assertThat(writeJava(code)).isEqualTo("return myUtil.truncate(myString)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithDollarSignPlaceholder() {
|
||||
CodeBlock code = CodeBlock.of("// $$ allowed, that's $$$L.", 25);
|
||||
assertThat(writeJava(code)).isEqualTo("// $ allowed, that's $25.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithEndOfStatementPlaceholderInvokeConfiguredFormattingOptions() {
|
||||
FormattingOptions options = mock(FormattingOptions.class);
|
||||
given(options.statementSeparator()).willReturn(";");
|
||||
CodeBlock code = CodeBlock.of("invoke(param)$]");
|
||||
assertThat(write(code, options)).isEqualToNormalizingNewlines("""
|
||||
invoke(param);
|
||||
""");
|
||||
verify(options).statementSeparator();
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithTypePlaceholderAndClassAddsImport() {
|
||||
CodeBlock code = CodeBlock.of("return $T.truncate(myString)", StringUtils.class);
|
||||
assertThat(writeJava(code)).isEqualTo("return StringUtils.truncate(myString)");
|
||||
assertThat(code.getImports()).containsExactly(StringUtils.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithTypePlaceholderAndClassNameAddsImport() {
|
||||
CodeBlock code = CodeBlock.of("return $T.truncate(myString)", "com.example.StringUtils");
|
||||
assertThat(writeJava(code)).isEqualTo("return StringUtils.truncate(myString)");
|
||||
assertThat(code.getImports()).containsExactly("com.example.StringUtils");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithTypePlaceholderAndNonResolvableType() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> CodeBlock.of("return $T.truncate(myString)", true))
|
||||
.withMessageContaining("Failed to extract type from 'true'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockDoesNotAddNewLine() {
|
||||
CodeBlock code = CodeBlock.of("(123, 456)");
|
||||
assertThat(writeJava(code)).isEqualTo("(123, 456)");
|
||||
assertThat(code.getImports()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlocksCanBeAdded() {
|
||||
CodeBlock code = CodeBlock.builder().add("(123").add(CodeBlock.of(", 456)")).build();
|
||||
assertThat(writeJava(code)).isEqualTo("(123, 456)");
|
||||
assertThat(code.getImports()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithSingleStatement() {
|
||||
CodeBlock code = CodeBlock.ofStatement("myInstance.sayHello(123)");
|
||||
assertThat(writeJava(code)).isEqualToNormalizingNewlines("""
|
||||
myInstance.sayHello(123);
|
||||
""");
|
||||
assertThat(code.getImports()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void codeBlockWithMultipleStatements() {
|
||||
CodeBlock code = CodeBlock.builder()
|
||||
.addStatement("myInstance.sayHello(123)")
|
||||
.addStatement(CodeBlock.of("myInstance.sayHello(456)"))
|
||||
.build();
|
||||
assertThat(writeJava(code)).isEqualToNormalizingNewlines("""
|
||||
myInstance.sayHello(123);
|
||||
myInstance.sayHello(456);
|
||||
""");
|
||||
assertThat(code.getImports()).isEmpty();
|
||||
}
|
||||
|
||||
private String writeJava(CodeBlock code) {
|
||||
return write(code, CodeBlock.JAVA_FORMATTING_OPTIONS);
|
||||
}
|
||||
|
||||
private String write(CodeBlock code, FormattingOptions options) {
|
||||
StringWriter out = new StringWriter();
|
||||
IndentingWriter writer = new IndentingWriter(out, new SimpleIndentStrategy("\t"));
|
||||
code.write(writer, options);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,7 @@ import java.util.UUID;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Language;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceStructure;
|
||||
@ -108,6 +109,22 @@ class GroovySourceCodeWriterTests {
|
||||
|
||||
@Test
|
||||
void method() throws IOException {
|
||||
GroovySourceCode sourceCode = new GroovySourceCode();
|
||||
GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
test.addMethodDeclaration(GroovyMethodDeclaration.method("trim")
|
||||
.returning("java.lang.String")
|
||||
.parameters(new Parameter("java.lang.String", "value"))
|
||||
.body(CodeBlock.ofStatement("value.trim()")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.groovy");
|
||||
assertThat(lines).containsExactly("package com.example", "", "class Test {", "",
|
||||
" String trim(String value) {", " value.trim()", " }", "", "}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
@SuppressWarnings("removal")
|
||||
void methodWithStatements() throws IOException {
|
||||
GroovySourceCode sourceCode = new GroovySourceCode();
|
||||
GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
@ -130,8 +147,7 @@ class GroovySourceCodeWriterTests {
|
||||
.modifiers(Modifier.PUBLIC | Modifier.STATIC)
|
||||
.returning("void")
|
||||
.parameters(new Parameter("java.lang.String[]", "args"))
|
||||
.body(new GroovyExpressionStatement(
|
||||
new GroovyMethodInvocation("org.springframework.boot.SpringApplication", "run", "Test", "args"))));
|
||||
.body(CodeBlock.ofStatement("$T.run($L, args)", "org.springframework.boot.SpringApplication", "Test")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.groovy");
|
||||
assertThat(lines).containsExactly("package com.example", "",
|
||||
"import org.springframework.boot.SpringApplication",
|
||||
@ -278,7 +294,7 @@ class GroovySourceCodeWriterTests {
|
||||
GroovyMethodDeclaration method = GroovyMethodDeclaration.method("something")
|
||||
.returning("void")
|
||||
.parameters()
|
||||
.body();
|
||||
.body(CodeBlock.of(""));
|
||||
method.annotate(Annotation.name("com.example.test.TestAnnotation"));
|
||||
test.addMethodDeclaration(method);
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.groovy");
|
||||
|
@ -29,6 +29,7 @@ import java.util.UUID;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Language;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceStructure;
|
||||
@ -107,6 +108,23 @@ class JavaSourceCodeWriterTests {
|
||||
|
||||
@Test
|
||||
void method() throws IOException {
|
||||
JavaSourceCode sourceCode = new JavaSourceCode();
|
||||
JavaCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
test.addMethodDeclaration(JavaMethodDeclaration.method("trim")
|
||||
.returning("java.lang.String")
|
||||
.modifiers(Modifier.PUBLIC)
|
||||
.parameters(new Parameter("java.lang.String", "value"))
|
||||
.body(CodeBlock.ofStatement("return value.trim()")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.java");
|
||||
assertThat(lines).containsExactly("package com.example;", "", "class Test {", "",
|
||||
" public String trim(String value) {", " return value.trim();", " }", "", "}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
@SuppressWarnings("removal")
|
||||
void methodWithStatements() throws IOException {
|
||||
JavaSourceCode sourceCode = new JavaSourceCode();
|
||||
JavaCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
@ -205,8 +223,8 @@ class JavaSourceCodeWriterTests {
|
||||
.modifiers(Modifier.PUBLIC | Modifier.STATIC)
|
||||
.returning("void")
|
||||
.parameters(new Parameter("java.lang.String[]", "args"))
|
||||
.body(new JavaExpressionStatement(new JavaMethodInvocation("org.springframework.boot.SpringApplication",
|
||||
"run", "Test.class", "args"))));
|
||||
.body(CodeBlock.ofStatement("$T.run($L.class, args)", "org.springframework.boot.SpringApplication",
|
||||
"Test")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.java");
|
||||
assertThat(lines).containsExactly("package com.example;", "",
|
||||
"import org.springframework.boot.SpringApplication;",
|
||||
@ -283,7 +301,10 @@ class JavaSourceCodeWriterTests {
|
||||
JavaSourceCode sourceCode = new JavaSourceCode();
|
||||
JavaCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
JavaMethodDeclaration method = JavaMethodDeclaration.method("something").returning("void").parameters().body();
|
||||
JavaMethodDeclaration method = JavaMethodDeclaration.method("something")
|
||||
.returning("void")
|
||||
.parameters()
|
||||
.body(CodeBlock.of(""));
|
||||
method.annotate(Annotation.name("com.example.test.TestAnnotation"));
|
||||
test.addMethodDeclaration(method);
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.java");
|
||||
|
@ -28,6 +28,7 @@ import java.util.UUID;
|
||||
|
||||
import io.spring.initializr.generator.io.IndentingWriterFactory;
|
||||
import io.spring.initializr.generator.language.Annotation;
|
||||
import io.spring.initializr.generator.language.CodeBlock;
|
||||
import io.spring.initializr.generator.language.Language;
|
||||
import io.spring.initializr.generator.language.Parameter;
|
||||
import io.spring.initializr.generator.language.SourceStructure;
|
||||
@ -107,6 +108,22 @@ class KotlinSourceCodeWriterTests {
|
||||
|
||||
@Test
|
||||
void function() throws IOException {
|
||||
KotlinSourceCode sourceCode = new KotlinSourceCode();
|
||||
KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
test.addFunctionDeclaration(KotlinFunctionDeclaration.function("reverse")
|
||||
.returning("java.lang.String")
|
||||
.parameters(new Parameter("java.lang.String", "echo"))
|
||||
.body(CodeBlock.ofStatement("return echo.reversed()")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.kt");
|
||||
assertThat(lines).containsExactly("package com.example", "", "class Test {", "",
|
||||
" fun reverse(echo: String): String {", " return echo.reversed()", " }", "", "}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
@SuppressWarnings("removal")
|
||||
void functionWithStatements() throws IOException {
|
||||
KotlinSourceCode sourceCode = new KotlinSourceCode();
|
||||
KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
@ -127,7 +144,7 @@ class KotlinSourceCodeWriterTests {
|
||||
test.addFunctionDeclaration(KotlinFunctionDeclaration.function("toString")
|
||||
.modifiers(KotlinModifier.OVERRIDE, KotlinModifier.PUBLIC, KotlinModifier.OPEN)
|
||||
.returning("java.lang.String")
|
||||
.body(new KotlinReturnStatement(new KotlinFunctionInvocation("super", "toString"))));
|
||||
.body(CodeBlock.ofStatement("return super.toString()")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.kt");
|
||||
assertThat(lines).containsExactly("package com.example", "", "class Test {", "",
|
||||
" open override fun toString(): String {", " return super.toString()", " }", "", "}");
|
||||
@ -159,6 +176,27 @@ class KotlinSourceCodeWriterTests {
|
||||
|
||||
@Test
|
||||
void valGetterProperty() throws IOException {
|
||||
KotlinSourceCode sourceCode = new KotlinSourceCode();
|
||||
KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
test.addPropertyDeclaration(
|
||||
KotlinPropertyDeclaration.val("testProp").returning("java.lang.String").value("\"This is a TEST\""));
|
||||
test.addPropertyDeclaration(KotlinPropertyDeclaration.val("withGetter")
|
||||
.returning("java.lang.String")
|
||||
.getter()
|
||||
.withBody(CodeBlock.of("testProp.toLowerCase()"))
|
||||
.buildAccessor()
|
||||
.emptyValue());
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.kt");
|
||||
assertThat(lines).containsExactly("package com.example", "", "class Test {", "",
|
||||
" val testProp: String = \"This is a TEST\"", "", " val withGetter: String",
|
||||
" get() = testProp.toLowerCase()", "", "}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
@SuppressWarnings("removal")
|
||||
void valGetterPropertyWithStatement() throws IOException {
|
||||
KotlinSourceCode sourceCode = new KotlinSourceCode();
|
||||
KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
@ -265,8 +303,7 @@ class KotlinSourceCodeWriterTests {
|
||||
test.annotate(Annotation.name("org.springframework.boot.autoconfigure.SpringBootApplication"));
|
||||
compilationUnit.addTopLevelFunction(KotlinFunctionDeclaration.function("main")
|
||||
.parameters(new Parameter("Array<String>", "args"))
|
||||
.body(new KotlinExpressionStatement(
|
||||
new KotlinReifiedFunctionInvocation("org.springframework.boot.runApplication", "Test", "*args"))));
|
||||
.body(CodeBlock.ofStatement("$T<$L>(*args)", "org.springframework.boot.runApplication", "Test")));
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.kt");
|
||||
assertThat(lines).containsExactly("package com.example", "",
|
||||
"import org.springframework.boot.autoconfigure.SpringBootApplication",
|
||||
@ -339,7 +376,7 @@ class KotlinSourceCodeWriterTests {
|
||||
KotlinSourceCode sourceCode = new KotlinSourceCode();
|
||||
KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");
|
||||
KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test");
|
||||
KotlinFunctionDeclaration function = KotlinFunctionDeclaration.function("something").body();
|
||||
KotlinFunctionDeclaration function = KotlinFunctionDeclaration.function("something").body(CodeBlock.of(""));
|
||||
function.annotate(Annotation.name("com.example.test.TestAnnotation"));
|
||||
test.addFunctionDeclaration(function);
|
||||
List<String> lines = writeSingleType(sourceCode, "com/example/Test.kt");
|
||||
|
Loading…
Reference in New Issue
Block a user