diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java index 646b3f3a..b7ceea3b 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java @@ -27,7 +27,7 @@ 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.KotlinMethodInvocation; +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; @@ -96,7 +96,7 @@ class KotlinProjectGenerationDefaultContributorsConfiguration { return (compilationUnit) -> compilationUnit.addTopLevelFunction( KotlinFunctionDeclaration.function("main").parameters(new Parameter("Array", "args")) .body(new KotlinExpressionStatement( - new KotlinMethodInvocation("org.springframework.boot.SpringApplication", "run", + new KotlinFunctionInvocation("org.springframework.boot.SpringApplication", "run", projectDescription.getApplicationName() + "::class.java", "*args")))); } @@ -143,7 +143,7 @@ class KotlinProjectGenerationDefaultContributorsConfiguration { .returning("org.springframework.boot.builder.SpringApplicationBuilder") .parameters(new Parameter("org.springframework.boot.builder.SpringApplicationBuilder", "application")) - .body(new KotlinReturnStatement(new KotlinMethodInvocation("application", "sources", + .body(new KotlinReturnStatement(new KotlinFunctionInvocation("application", "sources", projectDescription.getApplicationName() + "::class.java"))); typeDeclaration.addFunctionDeclaration(configure); }; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpression.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpression.java index 033a39fc..3a0913a0 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpression.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpression.java @@ -20,8 +20,7 @@ package io.spring.initializr.generator.language.groovy; * A Groovy expression. * * @author Stephane Nicoll - * @author Matt Berteaux */ -public interface GroovyExpression { +public class GroovyExpression { } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpressionStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpressionStatement.java index 837b9add..efcfa11e 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpressionStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyExpressionStatement.java @@ -21,7 +21,7 @@ package io.spring.initializr.generator.language.groovy; * * @author Stephane Nicoll */ -public class GroovyExpressionStatement implements GroovyStatement { +public class GroovyExpressionStatement extends GroovyStatement { private final GroovyExpression expression; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyFieldDeclaration.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyFieldDeclaration.java index bfb86dac..d089e55e 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyFieldDeclaration.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyFieldDeclaration.java @@ -24,13 +24,13 @@ import io.spring.initializr.generator.language.Annotatable; import io.spring.initializr.generator.language.Annotation; /** - * Declaration, and potential initialization, of a field in Groovy. + * Declaration of a field written in Groovy. * * @author Matt Berteaux */ public final class GroovyFieldDeclaration implements Annotatable { - private final List annotations; + private final List annotations = new ArrayList<>(); private final int modifiers; @@ -40,12 +40,14 @@ public final class GroovyFieldDeclaration implements Annotatable { private final Object value; + private final boolean initialized; + private GroovyFieldDeclaration(Builder builder) { this.modifiers = builder.modifiers; this.name = builder.name; this.returnType = builder.returnType; this.value = builder.value; - this.annotations = builder.annotations; + this.initialized = builder.initialized; } public static Builder field(String name) { @@ -78,9 +80,11 @@ public final class GroovyFieldDeclaration implements Annotatable { return this.value; } - public static final class Builder { + public boolean isInitialized() { + return this.initialized; + } - private final List annotations = new ArrayList<>(); + public static final class Builder { private final String name; @@ -88,7 +92,9 @@ public final class GroovyFieldDeclaration implements Annotatable { private int modifiers; - private Object value = InitializedStatus.NOT_INITIALIZED; + private Object value; + + private boolean initialized; private Builder(String name) { this.name = name; @@ -99,13 +105,9 @@ public final class GroovyFieldDeclaration implements Annotatable { return this; } - public Builder value(GroovyExpression value) { + public Builder value(Object value) { this.value = value; - return this; - } - - public Builder withAnnotation(Annotation annotation) { - this.annotations.add(annotation); + this.initialized = true; return this; } @@ -116,14 +118,4 @@ public final class GroovyFieldDeclaration implements Annotatable { } - /** - * Track if the value has been set or not. Using this because initializing a field to - * null should be possible. - */ - enum InitializedStatus { - - NOT_INITIALIZED; - - } - } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyMethodInvocation.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyMethodInvocation.java index 9a7e9e4d..25454cdb 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyMethodInvocation.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyMethodInvocation.java @@ -23,9 +23,8 @@ import java.util.List; * An invocation of a method. * * @author Stephane Nicoll - * @author Matt Berteaux */ -public class GroovyMethodInvocation implements GroovyExpression, GroovyStatement { +public class GroovyMethodInvocation extends GroovyExpression { private final String target; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitive.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitive.java deleted file mode 100644 index 30ceb2e3..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitive.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.groovy; - -/** - * A primitive in the Groovy language. - * - * @author Matt Berteaux - */ -public interface GroovyPrimitive extends GroovyExpression { - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitives.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitives.java deleted file mode 100644 index 54a51c2b..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyPrimitives.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.groovy; - -import java.util.function.Supplier; - -import io.spring.initializr.generator.language.java.JavaPrimitives; - -/** - * Primitives for the Groovy language. Are just wrappers around the - * {@link JavaPrimitives}. - * - * @author Matt Berteaux - */ -public final class GroovyPrimitives { - - private GroovyPrimitives() { - // hide public constructor - } - - public static GroovyPrimitive byteValue(Byte value) { - return new GroovyByte(value); - } - - public static GroovyPrimitive shortValue(Short value) { - return new GroovyShort(value); - } - - public static GroovyPrimitive integerValue(Integer value) { - return new GroovyInteger(value); - } - - public static GroovyPrimitive doubleValue(Double value) { - return new GroovyDouble(value); - } - - public static GroovyPrimitive longValue(Long value) { - return new GroovyLong(value); - } - - public static GroovyPrimitive charValue(String charString) { - return new GroovyChar(charString); - } - - public static GroovyPrimitive booleanValue(Boolean value) { - return new GroovyBoolean(value); - } - - private static String valueOrNull(Object value, Supplier nonNullSupplier) { - if (value == null) { - return "null"; - } - return nonNullSupplier.get(); - } - - public static final class GroovyByte implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Byte"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "byte"; - - protected final Byte value; - - public GroovyByte(Byte value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Byte.toString(this.value)); - } - - } - - public static final class GroovyShort implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Short"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "short"; - - protected final Short value; - - private GroovyShort(Short value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Short.toString(this.value)); - } - - } - - public static final class GroovyInteger implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Integer"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "int"; - - protected final Integer value; - - private GroovyInteger(Integer value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Integer.toString(this.value)); - } - - } - - public static final class GroovyDouble implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Double"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "double"; - - protected final Double value; - - private GroovyDouble(Double value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Double.toString(this.value)); - } - - } - - public static final class GroovyFloat implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Float"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "float"; - - protected final Float value; - - private GroovyFloat(Float value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "f"); - } - - } - - public static final class GroovyLong implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Long"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "long"; - - protected final Long value; - - private GroovyLong(Long value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "L"); - } - - } - - public static final class GroovyChar implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Character"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "char"; - - protected final String value; - - private GroovyChar(String charString) { - this.value = charString; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value); - } - - } - - public static final class GroovyBoolean implements GroovyPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Boolean"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "boolean"; - - protected final Boolean value; - - private GroovyBoolean(Boolean value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Boolean.toString(this.value)); - } - - } - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyReturnStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyReturnStatement.java index 64f3673d..deee18d5 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyReturnStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovyReturnStatement.java @@ -20,12 +20,17 @@ package io.spring.initializr.generator.language.groovy; * A return statement. * * @author Stephane Nicoll - * @author Matt Berteaux */ -public class GroovyReturnStatement extends GroovyExpressionStatement { +public class GroovyReturnStatement extends GroovyStatement { + + private final GroovyExpression expression; public GroovyReturnStatement(GroovyExpression expression) { - super(expression); + this.expression = expression; + } + + public GroovyExpression getExpression() { + return this.expression; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriter.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriter.java index 186f5c14..7512467f 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriter.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriter.java @@ -28,7 +28,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; @@ -53,10 +52,10 @@ public class GroovySourceCodeWriter implements SourceCodeWriter, String> TYPE_MODIFIERS; - private static final Map, String> METHOD_MODIFIERS; - private static final Map, String> FIELD_MODIFIERS; + private static final Map, String> METHOD_MODIFIERS; + static { Map, String> typeModifiers = new LinkedHashMap<>(); typeModifiers.put(Modifier::isProtected, "protected"); @@ -66,11 +65,6 @@ public class GroovySourceCodeWriter implements SourceCodeWriter, String> methodModifiers = new LinkedHashMap<>(typeModifiers); - methodModifiers.put(Modifier::isSynchronized, "synchronized"); - methodModifiers.put(Modifier::isNative, "native"); - METHOD_MODIFIERS = methodModifiers; - Map, String> fieldModifiers = new LinkedHashMap<>(); fieldModifiers.put(Modifier::isPublic, "public"); fieldModifiers.put(Modifier::isProtected, "protected"); @@ -80,6 +74,10 @@ public class GroovySourceCodeWriter implements SourceCodeWriter, String> methodModifiers = new LinkedHashMap<>(typeModifiers); + methodModifiers.put(Modifier::isSynchronized, "synchronized"); + methodModifiers.put(Modifier::isNative, "native"); + METHOD_MODIFIERS = methodModifiers; } private final IndentingWriterFactory indentingWriterFactory; @@ -90,7 +88,7 @@ public class GroovySourceCodeWriter implements SourceCodeWriter writeAnnotation(writer, annotation)); + } + + private void writeAnnotation(IndentingWriter writer, Annotation annotation) { + writer.print("@" + getUnqualifiedName(annotation.getName())); + List attributes = annotation.getAttributes(); + if (!attributes.isEmpty()) { + writer.print("("); + if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { + writer.print(formatAnnotationAttribute(attributes.get(0))); + } + else { + writer.print(attributes.stream() + .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) + .collect(Collectors.joining(", "))); + } + writer.print(")"); } - writeFieldModifiers(writer, fieldDeclaration); + writer.println(); + } + + private String formatAnnotationAttribute(Annotation.Attribute attribute) { + List values = attribute.getValues(); + if (attribute.getType().equals(Class.class)) { + return formatValues(values, this::getUnqualifiedName); + } + if (Enum.class.isAssignableFrom(attribute.getType())) { + return formatValues(values, (value) -> { + String enumValue = value.substring(value.lastIndexOf(".") + 1); + String enumClass = value.substring(0, value.lastIndexOf(".")); + return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); + }); + } + if (attribute.getType().equals(String.class)) { + return formatValues(values, (value) -> String.format("\"%s\"", value)); + } + return formatValues(values, (value) -> String.format("%s", value)); + } + + private String formatValues(List values, Function formatter) { + String result = values.stream().map(formatter).collect(Collectors.joining(", ")); + return (values.size() > 1) ? "{ " + result + " }" : result; + } + + private void writeFieldDeclaration(IndentingWriter writer, GroovyFieldDeclaration fieldDeclaration) { + writeAnnotations(writer, fieldDeclaration); + writeModifiers(writer, FIELD_MODIFIERS, fieldDeclaration.getModifiers()); writer.print(getUnqualifiedName(fieldDeclaration.getReturnType())); writer.print(" "); writer.print(fieldDeclaration.getName()); - if (!Objects.equals(GroovyFieldDeclaration.InitializedStatus.NOT_INITIALIZED, fieldDeclaration.getValue())) { + if (fieldDeclaration.isInitialized()) { writer.print(" = "); - writeFieldValue(writer, fieldDeclaration.getValue(), fieldDeclaration.getReturnType()); + writer.print(String.valueOf(fieldDeclaration.getValue())); } writer.println(); writer.println(); } - private void writeFieldValue(IndentingWriter writer, Object value, String returnType) { - quote(writer, value, returnType); - writer.print(String.valueOf(value)); - quote(writer, value, returnType); - } - - private void quote(IndentingWriter writer, Object value, String returnType) { - if (value instanceof Character || "char".equals(returnType) || "java.lang.Character".equals(returnType)) { - writer.print("\'"); - } - else if (value instanceof CharSequence) { - writer.print("\""); - } - } - private void writeMethodDeclaration(IndentingWriter writer, GroovyMethodDeclaration methodDeclaration) { writeAnnotations(writer, methodDeclaration); writeModifiers(writer, METHOD_MODIFIERS, methodDeclaration.getModifiers()); @@ -200,10 +226,6 @@ public class GroovySourceCodeWriter implements SourceCodeWriter, String> availableModifiers, int declaredModifiers) { String modifiers = availableModifiers.entrySet().stream() @@ -215,10 +237,6 @@ public class GroovySourceCodeWriter implements SourceCodeWriter(imports); } - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable) { - writeAnnotations(writer, annotatable, true); - } - - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable, boolean newLine) { - for (Annotation annotation : annotatable.getAnnotations()) { - writeAnnotation(writer, annotation, newLine); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation, boolean newLine) { - writer.print("@" + getUnqualifiedName(annotation.getName())); - List attributes = annotation.getAttributes(); - if (!attributes.isEmpty()) { - writer.print("("); - if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { - writer.print(formatAnnotationAttribute(attributes.get(0))); - } - else { - writer.print(attributes.stream() - .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) - .collect(Collectors.joining(", "))); - } - writer.print(")"); - } - if (newLine) { - writer.println(); - } - else { - writer.print(" "); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation) { - writeAnnotation(writer, annotation, true); - } - - protected String formatAnnotationAttribute(Annotation.Attribute attribute) { - List values = attribute.getValues(); - if (attribute.getType().equals(Class.class)) { - return formatValues(values, (value) -> String.format(annotationFormatString(), getUnqualifiedName(value))); - } - if (Enum.class.isAssignableFrom(attribute.getType())) { - return formatValues(values, (value) -> { - String enumValue = value.substring(value.lastIndexOf(".") + 1); - String enumClass = value.substring(0, value.lastIndexOf(".")); - return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); - }); - } - if (attribute.getType().equals(String.class)) { - return formatValues(values, (value) -> String.format("\"%s\"", value)); - } - return formatValues(values, (value) -> String.format("%s", value)); - } - - private String formatValues(List values, Function formatter) { - String result = values.stream().map(formatter).collect(Collectors.joining(", ")); - return (values.size() > 1) ? formatAnnotationArray(result) : result; - } - - private String formatAnnotationArray(String values) { - return "{ " + values + " }"; - } - - private String getUnqualifiedName(String name) { - if (!name.contains(".")) { - return name; - } - return name.substring(name.lastIndexOf(".") + 1); - } - - private boolean requiresImport(String name) { - if (name == null || !name.contains(".")) { - return false; - } - String packageName = name.substring(0, name.lastIndexOf('.')); - return !"java.lang".equals(packageName); - } - private Collection determineImports(Annotation annotation) { List imports = new ArrayList<>(); imports.add(annotation.getName()); @@ -367,8 +312,19 @@ public class GroovySourceCodeWriter implements SourceCodeWriter methodDeclarations = new ArrayList<>(); - private final List fieldDeclarations = new ArrayList<>(); + private final List methodDeclarations = new ArrayList<>(); + GroovyTypeDeclaration(String name) { super(name); } @@ -46,14 +46,6 @@ public class GroovyTypeDeclaration extends TypeDeclaration { return this.modifiers; } - public void addMethodDeclaration(GroovyMethodDeclaration methodDeclaration) { - this.methodDeclarations.add(methodDeclaration); - } - - public List getMethodDeclarations() { - return this.methodDeclarations; - } - public void addFieldDeclaration(GroovyFieldDeclaration fieldDeclaration) { this.fieldDeclarations.add(fieldDeclaration); } @@ -62,4 +54,12 @@ public class GroovyTypeDeclaration extends TypeDeclaration { return this.fieldDeclarations; } + public void addMethodDeclaration(GroovyMethodDeclaration methodDeclaration) { + this.methodDeclarations.add(methodDeclaration); + } + + public List getMethodDeclarations() { + return this.methodDeclarations; + } + } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpression.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpression.java index 7527dbc4..b967f93d 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpression.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpression.java @@ -20,8 +20,7 @@ package io.spring.initializr.generator.language.java; * A Java expression. * * @author Andy Wilkinson - * @author Matt Berteaux */ -public interface JavaExpression { +public class JavaExpression { } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpressionStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpressionStatement.java index 94c00dc3..2faff959 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpressionStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaExpressionStatement.java @@ -20,9 +20,8 @@ package io.spring.initializr.generator.language.java; * A statement that contains a single expression. * * @author Andy Wilkinson - * @author Matt Berteaux */ -public class JavaExpressionStatement implements JavaStatement { +public class JavaExpressionStatement extends JavaStatement { private final JavaExpression expression; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaFieldDeclaration.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaFieldDeclaration.java index a7eb9257..0cda1ab0 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaFieldDeclaration.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaFieldDeclaration.java @@ -16,7 +16,6 @@ package io.spring.initializr.generator.language.java; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,7 +24,7 @@ import io.spring.initializr.generator.language.Annotatable; import io.spring.initializr.generator.language.Annotation; /** - * Declaration, and potential initialization, of a field in Java. + * Declaration of a field written in Java. * * @author Matt Berteaux */ @@ -41,33 +40,20 @@ public final class JavaFieldDeclaration implements Annotatable { private final Object value; - private JavaFieldDeclaration(int modifiers, String name, String returnType, Object value) { - this.modifiers = modifiers; - this.name = name; - this.returnType = returnType; - this.value = value; + private final boolean initialized; + + private JavaFieldDeclaration(Builder builder) { + this.modifiers = builder.modifiers; + this.name = builder.name; + this.returnType = builder.returnType; + this.value = builder.value; + this.initialized = builder.initialized; } public static Builder field(String name) { return new Builder(name); } - String getName() { - return this.name; - } - - String getReturnType() { - return this.returnType; - } - - int getModifiers() { - return this.modifiers; - } - - Object getValue() { - return this.value; - } - @Override public void annotate(Annotation annotation) { this.annotations.add(annotation); @@ -78,6 +64,26 @@ public final class JavaFieldDeclaration implements Annotatable { return Collections.unmodifiableList(this.annotations); } + public int getModifiers() { + return this.modifiers; + } + + public String getName() { + return this.name; + } + + public String getReturnType() { + return this.returnType; + } + + public Object getValue() { + return this.value; + } + + public boolean isInitialized() { + return this.initialized; + } + /** * Builder for creating a {@link JavaFieldDeclaration}. */ @@ -85,43 +91,34 @@ public final class JavaFieldDeclaration implements Annotatable { private final String name; - private int modifiers = Modifier.PUBLIC; + private String returnType; - private Object value = InitializedStatus.NOT_INITIALIZED; + private int modifiers; + + private Object value; + + private boolean initialized; private Builder(String name) { this.name = name; } - public Builder packagePrivate() { - this.modifiers = 0; - return this; - } - public Builder modifiers(int modifiers) { this.modifiers = modifiers; return this; } - public Builder value(JavaExpression value) { + public Builder value(Object value) { this.value = value; + this.initialized = true; return this; } public JavaFieldDeclaration returning(String returnType) { - return new JavaFieldDeclaration(this.modifiers, this.name, returnType, this.value); + this.returnType = returnType; + return new JavaFieldDeclaration(this); } } - /** - * Track if the value has been set or not. Using this because initializing a field to - * null should be possible. - */ - enum InitializedStatus { - - NOT_INITIALIZED; - - } - } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaMethodInvocation.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaMethodInvocation.java index b61694e2..a33ef186 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaMethodInvocation.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaMethodInvocation.java @@ -24,7 +24,7 @@ import java.util.List; * * @author Andy Wilkinson */ -public class JavaMethodInvocation implements JavaExpression, JavaStatement { +public class JavaMethodInvocation extends JavaExpression { private final String target; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitive.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitive.java deleted file mode 100644 index a9632ccb..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitive.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.java; - -/** - * A primitive for the Java language. - * - * @author Matt Berteaux - */ -public interface JavaPrimitive extends JavaExpression { - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitives.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitives.java deleted file mode 100644 index 168c2de1..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaPrimitives.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.java; - -import java.util.function.Supplier; - -/** - * Primitives for the java language. - * - * @author Matt Berteaux - */ -public final class JavaPrimitives { - - private JavaPrimitives() { - // hide public constructor - } - - public static JavaPrimitive byteValue(Byte value) { - return new JavaByte(value); - } - - public static JavaPrimitive shortValue(Short value) { - return new JavaShort(value); - } - - public static JavaPrimitive integerValue(Integer value) { - return new JavaInteger(value); - } - - public static JavaPrimitive longValue(Long value) { - return new JavaLong(value); - } - - public static JavaPrimitive doubleValue(Double value) { - return new JavaDouble(value); - } - - public static JavaPrimitive floatValue(Float value) { - return new JavaFloat(value); - } - - public static JavaPrimitive charValue(String charValue) { - return new JavaChar(charValue); - } - - public static JavaPrimitive booleanValue(Boolean value) { - return new JavaBoolean(value); - } - - private static String valueOrNull(Object value, Supplier nonNullSupplier) { - if (value == null) { - return "null"; - } - return nonNullSupplier.get(); - } - - public static final class JavaByte implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Byte"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "byte"; - - protected final Byte value; - - private JavaByte(Byte value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Byte.toString(this.value)); - } - - } - - public static final class JavaShort implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Short"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "short"; - - protected final Short value; - - private JavaShort(Short value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Short.toString(this.value)); - } - - } - - public static final class JavaInteger implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Integer"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "int"; - - protected final Integer value; - - private JavaInteger(Integer value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Integer.toString(this.value)); - } - - } - - public static final class JavaLong implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Long"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "long"; - - protected final Long value; - - private JavaLong(Long value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "L"); - } - - } - - public static final class JavaDouble implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Double"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "double"; - - protected final Double value; - - private JavaDouble(Double value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Double.toString(this.value)); - } - - } - - public static final class JavaFloat implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Float"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "float"; - - protected final Float value; - - private JavaFloat(Float value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "f"); - } - - } - - public static final class JavaChar implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Character"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "char"; - - protected final String value; - - private JavaChar(String charString) { - this.value = charString; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value); - } - - } - - public static final class JavaBoolean implements JavaPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "java.lang.Boolean"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "boolean"; - - protected final Boolean value; - - private JavaBoolean(Boolean value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Boolean.toString(this.value)); - } - - } - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaReturnStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaReturnStatement.java index 05f3e68e..07b81304 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaReturnStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaReturnStatement.java @@ -20,12 +20,17 @@ package io.spring.initializr.generator.language.java; * A return statement. * * @author Andy Wilkinson - * @author Matt Berteaux */ -public class JavaReturnStatement extends JavaExpressionStatement { +public class JavaReturnStatement extends JavaStatement { + + private final JavaExpression expression; public JavaReturnStatement(JavaExpression expression) { - super(expression); + this.expression = expression; + } + + public JavaExpression getExpression() { + return this.expression; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriter.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriter.java index f49d50af..38fc1467 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriter.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriter.java @@ -28,7 +28,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; @@ -53,10 +52,10 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { private static final Map, String> TYPE_MODIFIERS; - private static final Map, String> METHOD_MODIFIERS; - private static final Map, String> FIELD_MODIFIERS; + private static final Map, String> METHOD_MODIFIERS; + static { Map, String> typeModifiers = new LinkedHashMap<>(); typeModifiers.put(Modifier::isPublic, "public"); @@ -67,11 +66,6 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { typeModifiers.put(Modifier::isFinal, "final"); typeModifiers.put(Modifier::isStrict, "strictfp"); TYPE_MODIFIERS = typeModifiers; - Map, String> methodModifiers = new LinkedHashMap<>(typeModifiers); - methodModifiers.put(Modifier::isSynchronized, "synchronized"); - methodModifiers.put(Modifier::isNative, "native"); - METHOD_MODIFIERS = methodModifiers; - Map, String> fieldModifiers = new LinkedHashMap<>(); fieldModifiers.put(Modifier::isPublic, "public"); fieldModifiers.put(Modifier::isProtected, "protected"); @@ -81,6 +75,10 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { fieldModifiers.put(Modifier::isTransient, "transient"); fieldModifiers.put(Modifier::isVolatile, "volatile"); FIELD_MODIFIERS = fieldModifiers; + Map, String> methodModifiers = new LinkedHashMap<>(typeModifiers); + methodModifiers.put(Modifier::isSynchronized, "synchronized"); + methodModifiers.put(Modifier::isNative, "native"); + METHOD_MODIFIERS = methodModifiers; } private final IndentingWriterFactory indentingWriterFactory; @@ -91,7 +89,7 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { @Override public void writeTo(Path directory, JavaSourceCode sourceCode) throws IOException { - if (!directory.toFile().exists()) { + if (!Files.exists(directory)) { Files.createDirectories(directory); } for (JavaCompilationUnit compilationUnit : sourceCode.getCompilationUnits()) { @@ -143,37 +141,63 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { } } - private void writeFieldDeclaration(IndentingWriter writer, JavaFieldDeclaration fieldDeclaration) { - writeAnnotations(writer, fieldDeclaration); - writeFieldModifiers(writer, fieldDeclaration); - writer.print(getUnqualifiedName(fieldDeclaration.getReturnType())); - writer.print(" "); - writer.print(fieldDeclaration.getName()); - if (!Objects.equals(JavaFieldDeclaration.InitializedStatus.NOT_INITIALIZED, fieldDeclaration.getValue())) { - writer.print(" = "); - writeFieldValue(writer, fieldDeclaration.getValue(), fieldDeclaration.getReturnType()); + private void writeAnnotations(IndentingWriter writer, Annotatable annotatable) { + annotatable.getAnnotations().forEach((annotation) -> writeAnnotation(writer, annotation)); + } + + private void writeAnnotation(IndentingWriter writer, Annotation annotation) { + writer.print("@" + getUnqualifiedName(annotation.getName())); + List attributes = annotation.getAttributes(); + if (!attributes.isEmpty()) { + writer.print("("); + if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { + writer.print(formatAnnotationAttribute(attributes.get(0))); + } + else { + writer.print(attributes.stream() + .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) + .collect(Collectors.joining(", "))); + } + writer.print(")"); } - writer.println(";"); writer.println(); } - private void writeFieldValue(IndentingWriter writer, Object value, String returnType) { - quote(writer, value, returnType); - writer.print(String.valueOf(value)); - quote(writer, value, returnType); + private String formatAnnotationAttribute(Annotation.Attribute attribute) { + List values = attribute.getValues(); + if (attribute.getType().equals(Class.class)) { + return formatValues(values, (value) -> String.format("%s.class", getUnqualifiedName(value))); + } + if (Enum.class.isAssignableFrom(attribute.getType())) { + return formatValues(values, (value) -> { + String enumValue = value.substring(value.lastIndexOf(".") + 1); + String enumClass = value.substring(0, value.lastIndexOf(".")); + return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); + }); + } + if (attribute.getType().equals(String.class)) { + return formatValues(values, (value) -> String.format("\"%s\"", value)); + } + return formatValues(values, (value) -> String.format("%s", value)); } - private void quote(IndentingWriter writer, Object value, String returnType) { - if (value instanceof Character || "char".equals(returnType) || "java.lang.Character".equals(returnType)) { - writer.print("\'"); - } - else if (value instanceof CharSequence) { - writer.print("\""); - } + private String formatValues(List values, Function formatter) { + String result = values.stream().map(formatter).collect(Collectors.joining(", ")); + return (values.size() > 1) ? "{ " + result + " }" : result; } - private void writeFieldModifiers(IndentingWriter writer, JavaFieldDeclaration fieldDeclaration) { + private void writeFieldDeclaration(IndentingWriter writer, JavaFieldDeclaration fieldDeclaration) { + writeAnnotations(writer, fieldDeclaration); writeModifiers(writer, FIELD_MODIFIERS, fieldDeclaration.getModifiers()); + writer.print(getUnqualifiedName(fieldDeclaration.getReturnType())); + writer.print(" "); + writer.print(fieldDeclaration.getName()); + if (fieldDeclaration.isInitialized()) { + writer.print(" = "); + writer.print(String.valueOf(fieldDeclaration.getValue())); + } + writer.println(";"); + writer.println(); } private void writeMethodDeclaration(IndentingWriter writer, JavaMethodDeclaration methodDeclaration) { @@ -190,13 +214,13 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { writer.indented(() -> { List statements = methodDeclaration.getStatements(); for (JavaStatement statement : statements) { - if (statement instanceof JavaReturnStatement) { + if (statement instanceof JavaExpressionStatement) { + writeExpression(writer, ((JavaExpressionStatement) statement).getExpression()); + } + else if (statement instanceof JavaReturnStatement) { writer.print("return "); writeExpression(writer, ((JavaReturnStatement) statement).getExpression()); } - else if (statement instanceof JavaExpressionStatement) { - writeExpression(writer, ((JavaExpressionStatement) statement).getExpression()); - } writer.println(";"); } }); @@ -204,10 +228,6 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { writer.println(); } - private void writeMethodModifiers(IndentingWriter writer, JavaMethodDeclaration methodDeclaration) { - writeModifiers(writer, METHOD_MODIFIERS, methodDeclaration.getModifiers()); - } - private void writeModifiers(IndentingWriter writer, Map, String> availableModifiers, int declaredModifiers) { String modifiers = availableModifiers.entrySet().stream() @@ -294,6 +314,13 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { .collect(Collectors.toList()); } + private String getUnqualifiedName(String name) { + if (!name.contains(".")) { + return name; + } + return name.substring(name.lastIndexOf(".") + 1); + } + private boolean requiresImport(String name) { if (name == null || !name.contains(".")) { return false; @@ -302,79 +329,4 @@ public class JavaSourceCodeWriter implements SourceCodeWriter { return !"java.lang".equals(packageName); } - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable) { - writeAnnotations(writer, annotatable, true); - } - - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable, boolean newLine) { - for (Annotation annotation : annotatable.getAnnotations()) { - writeAnnotation(writer, annotation, newLine); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation, boolean newLine) { - writer.print("@" + getUnqualifiedName(annotation.getName())); - List attributes = annotation.getAttributes(); - if (!attributes.isEmpty()) { - writer.print("("); - if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { - writer.print(formatAnnotationAttribute(attributes.get(0))); - } - else { - writer.print(attributes.stream() - .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) - .collect(Collectors.joining(", "))); - } - writer.print(")"); - } - if (newLine) { - writer.println(); - } - else { - writer.print(" "); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation) { - writeAnnotation(writer, annotation, true); - } - - private String formatAnnotationAttribute(Annotation.Attribute attribute) { - List values = attribute.getValues(); - if (attribute.getType().equals(Class.class)) { - return formatValues(values, (value) -> String.format(annotationFormatString(), getUnqualifiedName(value))); - } - if (Enum.class.isAssignableFrom(attribute.getType())) { - return formatValues(values, (value) -> { - String enumValue = value.substring(value.lastIndexOf(".") + 1); - String enumClass = value.substring(0, value.lastIndexOf(".")); - return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); - }); - } - if (attribute.getType().equals(String.class)) { - return formatValues(values, (value) -> String.format("\"%s\"", value)); - } - return formatValues(values, (value) -> String.format("%s", value)); - } - - private String formatValues(List values, Function formatter) { - String result = values.stream().map(formatter).collect(Collectors.joining(", ")); - return (values.size() > 1) ? formatAnnotationArray(result) : result; - } - - private String formatAnnotationArray(String values) { - return "{ " + values + " }"; - } - - private String getUnqualifiedName(String name) { - if (!name.contains(".")) { - return name; - } - return name.substring(name.lastIndexOf(".") + 1); - } - - private String annotationFormatString() { - return "%s.class"; - } - } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaStatement.java index 6e9b0212..3474213a 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaStatement.java @@ -20,8 +20,7 @@ package io.spring.initializr.generator.language.java; * A statement in Java. * * @author Andy Wilkinson - * @author Matt Berteaux */ -public interface JavaStatement { +public class JavaStatement { } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaString.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaString.java deleted file mode 100644 index b3be9e8f..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaString.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.java; - -/** - * A String type in the Java language. - * - * @author Matt Berteaux - */ -public final class JavaString implements JavaExpression { - - /** - * The class name of this type. - */ - public static final String CLASS_NAME = "java.lang.String"; - - private final String value; - - private JavaString(String value) { - this.value = value; - } - - public String getValue() { - return this.value; - } - - @Override - public String toString() { - return "\"" + this.value + "\""; - } - - public static JavaString stringValue(String value) { - return new JavaString(value); - } - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaTypeDeclaration.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaTypeDeclaration.java index 168f80ed..b4089753 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaTypeDeclaration.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/java/JavaTypeDeclaration.java @@ -31,10 +31,10 @@ public class JavaTypeDeclaration extends TypeDeclaration { private int modifiers; - private final List methodDeclarations = new ArrayList<>(); - private final List fieldDeclarations = new ArrayList<>(); + private final List methodDeclarations = new ArrayList<>(); + JavaTypeDeclaration(String name) { super(name); } @@ -47,14 +47,6 @@ public class JavaTypeDeclaration extends TypeDeclaration { return this.modifiers; } - public void addMethodDeclaration(JavaMethodDeclaration methodDeclaration) { - this.methodDeclarations.add(methodDeclaration); - } - - public List getMethodDeclarations() { - return this.methodDeclarations; - } - public void addFieldDeclaration(JavaFieldDeclaration fieldDeclaration) { this.fieldDeclarations.add(fieldDeclaration); } @@ -63,4 +55,12 @@ public class JavaTypeDeclaration extends TypeDeclaration { return this.fieldDeclarations; } + public void addMethodDeclaration(JavaMethodDeclaration methodDeclaration) { + this.methodDeclarations.add(methodDeclaration); + } + + public List getMethodDeclarations() { + return this.methodDeclarations; + } + } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpression.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpression.java index 83d80a09..ce7e8b09 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpression.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpression.java @@ -21,6 +21,6 @@ package io.spring.initializr.generator.language.kotlin; * * @author Stephane Nicoll */ -public interface KotlinExpression { +public class KotlinExpression { } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpressionStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpressionStatement.java index 66a99bac..4b53dbf5 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpressionStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinExpressionStatement.java @@ -21,7 +21,7 @@ package io.spring.initializr.generator.language.kotlin; * * @author Stephane Nicoll */ -public class KotlinExpressionStatement implements KotlinStatement { +public class KotlinExpressionStatement extends KotlinStatement { private final KotlinExpression expression; diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinFunctionInvocation.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinFunctionInvocation.java index 245803c2..ee5e9119 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinFunctionInvocation.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinFunctionInvocation.java @@ -16,6 +16,7 @@ package io.spring.initializr.generator.language.kotlin; +import java.util.Arrays; import java.util.List; /** @@ -23,15 +24,22 @@ import java.util.List; * * @author Stephane Nicoll */ -public class KotlinFunctionInvocation implements KotlinExpression { +public class KotlinFunctionInvocation extends KotlinExpression { + + private final String target; private final String name; private final List arguments; - public KotlinFunctionInvocation(String name, List arguments) { + public KotlinFunctionInvocation(String target, String name, String... arguments) { + this.target = target; this.name = name; - this.arguments = arguments; + this.arguments = Arrays.asList(arguments); + } + + public String getTarget() { + return this.target; } public String getName() { diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinMethodInvocation.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinMethodInvocation.java deleted file mode 100644 index 4161a051..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinMethodInvocation.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.kotlin; - -import java.util.Arrays; -import java.util.List; - -/** - * A method invocation in Kotlin. - * - * @author Matt Berteaux - */ -public class KotlinMethodInvocation implements KotlinExpression { - - private final String target; - - private final String name; - - private final List arguments; - - public KotlinMethodInvocation(String target, String name, String... arguments) { - this.target = target; - this.name = name; - this.arguments = Arrays.asList(arguments); - } - - public String getTarget() { - return this.target; - } - - public String getName() { - return this.name; - } - - public List getArguments() { - return this.arguments; - } - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinModifier.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinModifier.java index 68fc123b..c35d8dc2 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinModifier.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinModifier.java @@ -56,6 +56,11 @@ public enum KotlinModifier { /** * Override a member. */ - OVERRIDE + OVERRIDE, + + /** + * Declare a late-initialized property. + */ + LATEINIT } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitive.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitive.java deleted file mode 100644 index fe9793b9..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitive.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.kotlin; - -/** - * A primitive for the Kotlin language. - * - * @author Matt Berteaux - */ -public interface KotlinPrimitive extends KotlinExpression { - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitives.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitives.java deleted file mode 100644 index 93ace804..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPrimitives.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.kotlin; - -import java.util.function.Supplier; - -/** - * Kotlin primitives. - * - * @author Matt Berteaux - */ -public final class KotlinPrimitives { - - private KotlinPrimitives() { - // hide public constructor - } - - public static KotlinPrimitive byteValue(Byte value) { - return new KotlinByte(value); - } - - public static KotlinPrimitive shortValue(Short value) { - return new KotlinShort(value); - } - - public static KotlinPrimitive integerValue(Integer value) { - return new KotlinInt(value); - } - - public static KotlinPrimitive doubleValue(Double value) { - return new KotlinDouble(value); - } - - public static KotlinPrimitive longValue(Long value) { - return new KotlinLong(value); - } - - public static KotlinPrimitive floatValue(Float value) { - return new KotlinFloat(value); - } - - public static KotlinPrimitive charValue(String charString) { - return new KotlinChar(charString); - } - - public static KotlinPrimitive booleanValue(Boolean value) { - return new KotlinBoolean(value); - } - - private static String valueOrNull(Object value, Supplier nonNullSupplier) { - if (value == null) { - return "null"; - } - return nonNullSupplier.get(); - } - - public static final class KotlinByte implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_TYPE_CLASS = "kotlin.Byte"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Byte"; - - protected final Byte value; - - private KotlinByte(Byte value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Byte.toString(this.value)); - } - - } - - public static final class KotlinShort implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Short"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Short"; - - protected final Short value; - - private KotlinShort(Short value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Short.toString(this.value)); - } - - } - - public static final class KotlinInt implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Int"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Int"; - - protected final Integer value; - - private KotlinInt(Integer value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Integer.toString(this.value)); - } - - } - - public static final class KotlinDouble implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Double"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Double"; - - protected final Double value; - - private KotlinDouble(Double value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Double.toString(this.value)); - } - - } - - public static final class KotlinLong implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Long"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Long"; - - protected final Long value; - - private KotlinLong(Long value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "L"); - } - - } - - public static final class KotlinFloat implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Float"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Float"; - - protected final Float value; - - private KotlinFloat(Float value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value + "f"); - } - - } - - public static final class KotlinBoolean implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Boolean"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Boolean"; - - protected final Boolean value; - - private KotlinBoolean(Boolean value) { - this.value = value; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> Boolean.toString(this.value)); - } - - } - - public static final class KotlinChar implements KotlinPrimitive { - - /** - * The class name of the boxed type. - */ - public static final String BOXED_CLASS_NAME = "kotlin.Char"; - - /** - * The name of the unboxed type. - */ - public static final String TYPE = "kotlin.Char"; - - protected final String value; - - private KotlinChar(String charString) { - this.value = charString; - } - - @Override - public String toString() { - return valueOrNull(this.value, () -> this.value); - } - - } - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyDeclaration.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyDeclaration.java index 019fbcd5..3c90bc58 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyDeclaration.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyDeclaration.java @@ -17,6 +17,7 @@ package io.spring.initializr.generator.language.kotlin; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.function.Consumer; @@ -25,7 +26,7 @@ import io.spring.initializr.generator.language.Annotatable; import io.spring.initializr.generator.language.Annotation; /** - * Declaration of a property in Kotlin. + * Declaration of a property written in Kotlin. * * @author Matt Berteaux */ @@ -39,15 +40,18 @@ public final class KotlinPropertyDeclaration implements Annotatable { private final String returnType; + private final List modifiers; + private final KotlinExpressionStatement valueExpression; private final Accessor getter; private final Accessor setter; - private KotlinPropertyDeclaration(Builder builder) { + private KotlinPropertyDeclaration(Builder builder) { this.name = builder.name; this.returnType = builder.returnType; + this.modifiers = new ArrayList<>(builder.modifiers); this.isVal = builder.isVal; this.valueExpression = builder.initializerStatement; this.getter = builder.getter; @@ -74,6 +78,10 @@ public final class KotlinPropertyDeclaration implements Annotatable { return this.returnType; } + public List getModifiers() { + return this.modifiers; + } + KotlinExpressionStatement getValueExpression() { return this.valueExpression; } @@ -86,14 +94,6 @@ public final class KotlinPropertyDeclaration implements Annotatable { return this.setter; } - public boolean hasGetter() { - return getGetter() != null; - } - - public boolean hasSetter() { - return getSetter() != null; - } - @Override public void annotate(Annotation annotation) { this.annotations.add(annotation); @@ -117,6 +117,8 @@ public final class KotlinPropertyDeclaration implements Annotatable { private String returnType; + private List modifiers = new ArrayList<>(); + private KotlinExpressionStatement initializerStatement; private Accessor getter; @@ -145,12 +147,17 @@ public final class KotlinPropertyDeclaration implements Annotatable { return self(); } + public T modifiers(KotlinModifier... modifiers) { + this.modifiers = Arrays.asList(modifiers); + return self(); + } + public KotlinPropertyDeclaration emptyValue() { return new KotlinPropertyDeclaration(this); } - public KotlinPropertyDeclaration value(KotlinExpression expression) { - this.initializerStatement = new KotlinExpressionStatement(expression); + public KotlinPropertyDeclaration value(Object value) { + this.initializerStatement = new KotlinExpressionStatement(new SimpleValueExpression(value)); return new KotlinPropertyDeclaration(this); } @@ -192,8 +199,6 @@ public final class KotlinPropertyDeclaration implements Annotatable { private KotlinExpressionStatement body; - private boolean isPrivate = false; - private final T parent; private final Consumer accessorFunction; @@ -203,17 +208,12 @@ public final class KotlinPropertyDeclaration implements Annotatable { this.accessorFunction = accessorFunction; } - public AccessorBuilder isPrivate() { - this.isPrivate = true; - return this; - } - - public AccessorBuilder withAnnotation(Annotation annotation) { + public AccessorBuilder withAnnotation(Annotation annotation) { this.annotations.add(annotation); return this; } - public AccessorBuilder withBody(KotlinExpressionStatement expressionStatement) { + public AccessorBuilder withBody(KotlinExpressionStatement expressionStatement) { this.body = expressionStatement; return this; } @@ -231,17 +231,9 @@ public final class KotlinPropertyDeclaration implements Annotatable { private final KotlinExpressionStatement body; - private final boolean isPrivate; - - @SuppressWarnings("unchecked") - Accessor(AccessorBuilder builder) { + Accessor(AccessorBuilder builder) { this.annotations.addAll(builder.annotations); this.body = builder.body; - this.isPrivate = builder.isPrivate; - } - - boolean isPrivate() { - return this.isPrivate; } boolean isEmptyBody() { @@ -264,4 +256,19 @@ public final class KotlinPropertyDeclaration implements Annotatable { } + private static class SimpleValueExpression extends KotlinExpression { + + private final Object value; + + SimpleValueExpression(Object value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(this.value); + } + + } + } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyModifier.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyModifier.java deleted file mode 100644 index 56d25545..00000000 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinPropertyModifier.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * 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.kotlin; - -/** - * Modifiers that can modify a Kotlin property. - * - * @author Matt Berteaux - */ -public enum KotlinPropertyModifier { - - /** - * Represents a private property. - */ - PRIVATE, - - /** - * Represents a lateinit property. - */ - LATE_INIT - -} diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReifiedFunctionInvocation.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReifiedFunctionInvocation.java index e1eca06a..df6f16ec 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReifiedFunctionInvocation.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReifiedFunctionInvocation.java @@ -17,23 +17,37 @@ package io.spring.initializr.generator.language.kotlin; import java.util.Arrays; +import java.util.List; /** * Invocation of a function with a reified type parameter. * * @author Stephane Nicoll */ -public class KotlinReifiedFunctionInvocation extends KotlinFunctionInvocation implements KotlinExpression { +public class KotlinReifiedFunctionInvocation extends KotlinExpression { + + private final String name; private final String targetClass; + private final List arguments; + public KotlinReifiedFunctionInvocation(String name, String targetClass, String... arguments) { - super(name, Arrays.asList(arguments)); + this.name = name; this.targetClass = targetClass; + this.arguments = Arrays.asList(arguments); + } + + public String getName() { + return this.name; } public String getTargetClass() { return this.targetClass; } + public List getArguments() { + return this.arguments; + } + } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReturnStatement.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReturnStatement.java index 1efc6011..764bbd35 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReturnStatement.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinReturnStatement.java @@ -20,12 +20,17 @@ package io.spring.initializr.generator.language.kotlin; * A return statement. * * @author Andy Wilkinson - * @author Matt Berteaux */ -public class KotlinReturnStatement extends KotlinExpressionStatement { +public class KotlinReturnStatement extends KotlinStatement { + + private final KotlinExpression expression; public KotlinReturnStatement(KotlinExpression expression) { - super(expression); + this.expression = expression; + } + + public KotlinExpression getExpression() { + return this.expression; } } diff --git a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriter.java b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriter.java index cb243603..6ffeb362 100644 --- a/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriter.java +++ b/initializr-generator/src/main/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriter.java @@ -54,7 +54,7 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter writeAccessor(writer, "set", propertyDeclaration.getSetter())); } @@ -155,9 +156,6 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter attributes = annotation.getAttributes(); + if (!attributes.isEmpty()) { + writer.print("("); + if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { + writer.print(formatAnnotationAttribute(attributes.get(0))); + } + else { + writer.print(attributes.stream() + .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) + .collect(Collectors.joining(", "))); + } + writer.print(")"); + } + if (newLine) { + writer.println(); + } + else { + writer.print(" "); + } + } + + private String formatAnnotationAttribute(Annotation.Attribute attribute) { + List values = attribute.getValues(); + if (attribute.getType().equals(Class.class)) { + return formatValues(values, (value) -> String.format("%s::class", getUnqualifiedName(value))); + } + if (Enum.class.isAssignableFrom(attribute.getType())) { + return formatValues(values, (value) -> { + String enumValue = value.substring(value.lastIndexOf(".") + 1); + String enumClass = value.substring(0, value.lastIndexOf(".")); + return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); + }); + } + if (attribute.getType().equals(String.class)) { + return formatValues(values, (value) -> String.format("\"%s\"", value)); + } + return formatValues(values, (value) -> String.format("%s", value)); + } + + private String formatValues(List values, Function formatter) { + String result = values.stream().map(formatter).collect(Collectors.joining(", ")); + return (values.size() > 1) ? "[" + result + "]" : result; + } + private void writeModifiers(IndentingWriter writer, List declaredModifiers) { String modifiers = declaredModifiers.stream().filter((entry) -> !entry.equals(KotlinModifier.PUBLIC)).sorted() .map((entry) -> entry.toString().toLowerCase(Locale.ENGLISH)).collect(Collectors.joining(" ")); @@ -208,25 +258,18 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter Collections.singleton(parameter.getType()))); imports.addAll(getRequiredImports( - getKotlinExpressions(functionDeclaration).filter(KotlinMethodInvocation.class::isInstance) - .map(KotlinMethodInvocation.class::cast), + getKotlinExpressions(functionDeclaration).filter(KotlinFunctionInvocation.class::isInstance) + .map(KotlinFunctionInvocation.class::cast), (invocation) -> Collections.singleton(invocation.getTarget()))); imports.addAll(getRequiredImports( getKotlinExpressions(functionDeclaration).filter(KotlinReifiedFunctionInvocation.class::isInstance) @@ -292,78 +335,6 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter getKotlinExpressions(KotlinFunctionDeclaration functionDeclaration) { - return functionDeclaration.getStatements().stream().filter(KotlinExpressionStatement.class::isInstance) - .map(KotlinExpressionStatement.class::cast).map(KotlinExpressionStatement::getExpression); - } - - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable) { - writeAnnotations(writer, annotatable, true); - } - - private void writeAnnotations(IndentingWriter writer, Annotatable annotatable, boolean newLine) { - for (Annotation annotation : annotatable.getAnnotations()) { - writeAnnotation(writer, annotation, newLine); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation, boolean newLine) { - writer.print("@" + getUnqualifiedName(annotation.getName())); - List attributes = annotation.getAttributes(); - if (!attributes.isEmpty()) { - writer.print("("); - if (attributes.size() == 1 && attributes.get(0).getName().equals("value")) { - writer.print(formatAnnotationAttribute(attributes.get(0))); - } - else { - writer.print(attributes.stream() - .map((attribute) -> attribute.getName() + " = " + formatAnnotationAttribute(attribute)) - .collect(Collectors.joining(", "))); - } - writer.print(")"); - } - if (newLine) { - writer.println(); - } - else { - writer.print(" "); - } - } - - private void writeAnnotation(IndentingWriter writer, Annotation annotation) { - writeAnnotation(writer, annotation, true); - } - - private String formatAnnotationAttribute(Annotation.Attribute attribute) { - List values = attribute.getValues(); - if (attribute.getType().equals(Class.class)) { - return formatValues(values, (value) -> String.format(annotationFormatString(), getUnqualifiedName(value))); - } - if (Enum.class.isAssignableFrom(attribute.getType())) { - return formatValues(values, (value) -> { - String enumValue = value.substring(value.lastIndexOf(".") + 1); - String enumClass = value.substring(0, value.lastIndexOf(".")); - return String.format("%s.%s", getUnqualifiedName(enumClass), enumValue); - }); - } - if (attribute.getType().equals(String.class)) { - return formatValues(values, (value) -> String.format("\"%s\"", value)); - } - return formatValues(values, (value) -> String.format("%s", value)); - } - - private String formatValues(List values, Function formatter) { - String result = values.stream().map(formatter).collect(Collectors.joining(", ")); - return (values.size() > 1) ? formatAnnotationArray(result) : result; - } - - private String getUnqualifiedName(String name) { - if (!name.contains(".")) { - return name; - } - return name.substring(name.lastIndexOf(".") + 1); - } - private Collection determineImports(Annotation annotation) { List imports = new ArrayList<>(); imports.add(annotation.getName()); @@ -379,6 +350,11 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter getKotlinExpressions(KotlinFunctionDeclaration functionDeclaration) { + return functionDeclaration.getStatements().stream().filter(KotlinExpressionStatement.class::isInstance) + .map(KotlinExpressionStatement.class::cast).map(KotlinExpressionStatement::getExpression); + } + private List getRequiredImports(List candidates, Function> mapping) { return getRequiredImports(candidates.stream(), mapping); } @@ -388,20 +364,19 @@ public class KotlinSourceCodeWriter implements SourceCodeWriter modifiers = new ArrayList<>(); - private final List functionDeclarations = new ArrayList<>(); - private final List propertyDeclarations = new ArrayList<>(); + private final List functionDeclarations = new ArrayList<>(); + KotlinTypeDeclaration(String name) { super(name); } @@ -47,14 +47,6 @@ public class KotlinTypeDeclaration extends TypeDeclaration { return this.modifiers; } - public void addFunctionDeclaration(KotlinFunctionDeclaration methodDeclaration) { - this.functionDeclarations.add(methodDeclaration); - } - - public List getFunctionDeclarations() { - return this.functionDeclarations; - } - public void addPropertyDeclaration(KotlinPropertyDeclaration propertyDeclaration) { this.propertyDeclarations.add(propertyDeclaration); } @@ -63,4 +55,12 @@ public class KotlinTypeDeclaration extends TypeDeclaration { return this.propertyDeclarations; } + public void addFunctionDeclaration(KotlinFunctionDeclaration methodDeclaration) { + this.functionDeclarations.add(methodDeclaration); + } + + public List getFunctionDeclarations() { + return this.functionDeclarations; + } + } diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriterTests.java index 58b5dba7..f2673092 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriterTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/language/groovy/GroovySourceCodeWriterTests.java @@ -26,7 +26,6 @@ import java.util.List; import io.spring.initializr.generator.io.IndentingWriterFactory; import io.spring.initializr.generator.language.Annotation; import io.spring.initializr.generator.language.Parameter; -import io.spring.initializr.generator.language.java.JavaPrimitives; import io.spring.initializr.generator.test.io.TextTestUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -37,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link GroovySourceCodeWriter}. * * @author Stephane Nicoll + * @author Matt Berteaux */ class GroovySourceCodeWriterTests { @@ -120,7 +120,7 @@ class GroovySourceCodeWriterTests { GroovySourceCode sourceCode = new GroovySourceCode(); GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testString").returning(GroovyString.CLASS_NAME)); + test.addFieldDeclaration(GroovyFieldDeclaration.field("testString").returning("java.lang.String")); List lines = writeSingleType(sourceCode, "com/example/Test.groovy"); assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " String testString", "", "}"); @@ -131,18 +131,18 @@ class GroovySourceCodeWriterTests { GroovySourceCode sourceCode = new GroovySourceCode(); GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testInteger").value(GroovyPrimitives.integerValue(42)) - .returning(GroovyPrimitives.GroovyInteger.BOXED_CLASS_NAME)); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testDouble").modifiers(Modifier.PRIVATE) - .value(GroovyPrimitives.doubleValue(1986d)).returning(JavaPrimitives.JavaDouble.TYPE)); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testLong").value(GroovyPrimitives.longValue(1986L)) - .returning(GroovyPrimitives.GroovyLong.TYPE)); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testNullBoolean") - .value(GroovyPrimitives.booleanValue(null)).returning(GroovyPrimitives.GroovyBoolean.BOXED_CLASS_NAME)); + test.addFieldDeclaration(GroovyFieldDeclaration.field("testNoInit").returning("boolean")); + test.addFieldDeclaration( + GroovyFieldDeclaration.field("testInteger").value("42").returning("java.lang.Integer")); + test.addFieldDeclaration(GroovyFieldDeclaration.field("testDouble").modifiers(Modifier.PRIVATE).value("1986.0") + .returning("double")); + test.addFieldDeclaration(GroovyFieldDeclaration.field("testLong").value("1986L").returning("long")); + test.addFieldDeclaration( + GroovyFieldDeclaration.field("testNullBoolean").value(null).returning("java.lang.Boolean")); List lines = writeSingleType(sourceCode, "com/example/Test.groovy"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " Integer testInteger = 42", - "", " private double testDouble = 1986.0", "", " long testLong = 1986L", "", - " Boolean testNullBoolean = null", "", "}"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " boolean testNoInit", "", + " Integer testInteger = 42", "", " private double testDouble = 1986.0", "", + " long testLong = 1986L", "", " Boolean testNullBoolean = null", "", "}"); } @Test @@ -150,24 +150,37 @@ class GroovySourceCodeWriterTests { GroovySourceCode sourceCode = new GroovySourceCode(); GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE) - .returning(GroovyString.CLASS_NAME)); + test.addFieldDeclaration( + GroovyFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE).returning("java.lang.String")); List lines = writeSingleType(sourceCode, "com/example/Test.groovy"); assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " private String testString", "", "}"); } + @Test + void fieldImport() throws IOException { + GroovySourceCode sourceCode = new GroovySourceCode(); + GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addFieldDeclaration( + GroovyFieldDeclaration.field("testString").modifiers(Modifier.PUBLIC).returning("com.example.One")); + List lines = writeSingleType(sourceCode, "com/example/Test.groovy"); + assertThat(lines).containsExactly("package com.example", "", "import com.example.One", "", "class Test {", "", + " public One testString", "", "}"); + } + @Test void fieldAnnotation() throws IOException { GroovySourceCode sourceCode = new GroovySourceCode(); GroovyCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); GroovyTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addFieldDeclaration(GroovyFieldDeclaration.field("testString") - .withAnnotation(Annotation.name("org.springframework.beans.factory.annotation.Autowired")) - .returning(GroovyString.CLASS_NAME)); + GroovyFieldDeclaration field = GroovyFieldDeclaration.field("testString").returning("java.lang.String"); + field.annotate(Annotation.name("org.springframework.beans.factory.annotation.Autowired")); + test.addFieldDeclaration(field); List lines = writeSingleType(sourceCode, "com/example/Test.groovy"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " @Autowired", - " String testString", "", "}"); + assertThat(lines).containsExactly("package com.example", "", + "import org.springframework.beans.factory.annotation.Autowired", "", "class Test {", "", + " @Autowired", " String testString", "", "}"); } @Test diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriterTests.java index 26cdc55d..8dd0095d 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriterTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/language/java/JavaSourceCodeWriterTests.java @@ -89,7 +89,7 @@ class JavaSourceCodeWriterTests { 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(JavaString.CLASS_NAME, "value")) + .modifiers(Modifier.PUBLIC).parameters(new Parameter("java.lang.String", "value")) .body(new JavaReturnStatement(new JavaMethodInvocation("value", "trim")))); List lines = writeSingleType(sourceCode, "com/example/Test.java"); assertThat(lines).containsExactly("package com.example;", "", "class Test {", "", @@ -103,12 +103,24 @@ class JavaSourceCodeWriterTests { JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); test.modifiers(Modifier.PUBLIC); test.addFieldDeclaration( - JavaFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE).returning(JavaString.CLASS_NAME)); + JavaFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE).returning("java.lang.String")); List lines = writeSingleType(sourceCode, "com/example/Test.java"); assertThat(lines).containsExactly("package com.example;", "", "public class Test {", "", " private String testString;", "", "}"); } + @Test + void fieldImport() throws IOException { + JavaSourceCode sourceCode = new JavaSourceCode(); + JavaCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addFieldDeclaration( + JavaFieldDeclaration.field("testString").modifiers(Modifier.PUBLIC).returning("com.example.One")); + List lines = writeSingleType(sourceCode, "com/example/Test.java"); + assertThat(lines).containsExactly("package com.example;", "", "import com.example.One;", "", "class Test {", "", + " public One testString;", "", "}"); + } + @Test void fieldAnnotation() throws IOException { JavaSourceCode sourceCode = new JavaSourceCode(); @@ -116,7 +128,7 @@ class JavaSourceCodeWriterTests { JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); test.modifiers(Modifier.PUBLIC); JavaFieldDeclaration field = JavaFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE) - .returning(JavaString.CLASS_NAME); + .returning("java.lang.String"); field.annotate(Annotation.name("org.springframework.beans.factory.annotation.Autowired")); test.addFieldDeclaration(field); List lines = writeSingleType(sourceCode, "com/example/Test.java"); @@ -132,19 +144,18 @@ class JavaSourceCodeWriterTests { JavaTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); test.modifiers(Modifier.PUBLIC); test.addFieldDeclaration(JavaFieldDeclaration.field("testString").modifiers(Modifier.PRIVATE) - .value(JavaString.stringValue("Test String")).returning(JavaString.CLASS_NAME)); + .value("\"Test String\"").returning("java.lang.String")); test.addFieldDeclaration(JavaFieldDeclaration.field("testChar").modifiers(Modifier.PRIVATE | Modifier.TRANSIENT) - .value(JavaPrimitives.charValue("\\u03a9")).returning(JavaPrimitives.JavaChar.TYPE)); + .value("'\\u03a9'").returning("char")); test.addFieldDeclaration(JavaFieldDeclaration.field("testInt").modifiers(Modifier.PRIVATE | Modifier.FINAL) - .value(JavaPrimitives.integerValue(1337)).returning(JavaPrimitives.JavaInteger.TYPE)); - test.addFieldDeclaration(JavaFieldDeclaration.field("testDouble").modifiers(Modifier.PRIVATE) - .value(JavaPrimitives.doubleValue(3.14)).returning(JavaPrimitives.JavaDouble.BOXED_CLASS_NAME)); - test.addFieldDeclaration(JavaFieldDeclaration.field("testLong").modifiers(Modifier.PRIVATE) - .value(JavaPrimitives.longValue(1986L)).returning(JavaPrimitives.JavaLong.BOXED_CLASS_NAME)); - test.addFieldDeclaration(JavaFieldDeclaration.field("testFloat").value(JavaPrimitives.floatValue(99.999f)) - .returning(JavaPrimitives.JavaFloat.TYPE)); - test.addFieldDeclaration(JavaFieldDeclaration.field("testBool").packagePrivate() - .value(JavaPrimitives.booleanValue(true)).returning(JavaPrimitives.JavaBoolean.TYPE)); + .value(1337).returning("int")); + test.addFieldDeclaration( + JavaFieldDeclaration.field("testDouble").modifiers(Modifier.PRIVATE).value("3.14").returning("Double")); + test.addFieldDeclaration( + JavaFieldDeclaration.field("testLong").modifiers(Modifier.PRIVATE).value("1986L").returning("Long")); + test.addFieldDeclaration( + JavaFieldDeclaration.field("testFloat").modifiers(Modifier.PUBLIC).value("99.999f").returning("float")); + test.addFieldDeclaration(JavaFieldDeclaration.field("testBool").value("true").returning("boolean")); List lines = writeSingleType(sourceCode, "com/example/Test.java"); assertThat(lines).containsExactly("package com.example;", "", "public class Test {", "", " private String testString = \"Test String\";", "", diff --git a/initializr-generator/src/test/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriterTests.java b/initializr-generator/src/test/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriterTests.java index cd3b64d9..5ff7e213 100644 --- a/initializr-generator/src/test/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriterTests.java +++ b/initializr-generator/src/test/java/io/spring/initializr/generator/language/kotlin/KotlinSourceCodeWriterTests.java @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link KotlinSourceCodeWriter}. * * @author Stephane Nicoll + * @author Matt Berteaux */ class KotlinSourceCodeWriterTests { @@ -89,7 +90,7 @@ class KotlinSourceCodeWriterTests { KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); test.addFunctionDeclaration(KotlinFunctionDeclaration.function("reverse").returning("java.lang.String") .parameters(new Parameter("java.lang.String", "echo")) - .body(new KotlinReturnStatement(new KotlinMethodInvocation("echo", "reversed")))); + .body(new KotlinReturnStatement(new KotlinFunctionInvocation("echo", "reversed")))); List lines = writeSingleType(sourceCode, "com/example/Test.kt"); assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " fun reverse(echo: String): String {", " return echo.reversed()", " }", "", "}"); @@ -103,12 +104,127 @@ class KotlinSourceCodeWriterTests { test.addFunctionDeclaration(KotlinFunctionDeclaration.function("toString") .modifiers(KotlinModifier.OVERRIDE, KotlinModifier.PUBLIC, KotlinModifier.OPEN) .returning("java.lang.String") - .body(new KotlinReturnStatement(new KotlinMethodInvocation("super", "toString")))); + .body(new KotlinReturnStatement(new KotlinFunctionInvocation("super", "toString")))); List lines = writeSingleType(sourceCode, "com/example/Test.kt"); assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " open override fun toString(): String {", " return super.toString()", " }", "", "}"); } + @Test + void valProperty() 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").emptyValue()); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " val testProp: String", "", + "}"); + } + + @Test + void valPropertyImport() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration( + KotlinPropertyDeclaration.val("testProp").returning("com.example.One").emptyValue()); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "import com.example.One", "", "class Test {", "", + " val testProp: One", "", "}"); + } + + @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(new KotlinExpressionStatement(new KotlinFunctionInvocation("testProp", "toLowerCase"))) + .buildAccessor().emptyValue()); + List 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 + void varProperty() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration( + KotlinPropertyDeclaration.var("testProp").returning("java.lang.String").value("\"This is a test\"")); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", + " var testProp: String = \"This is a test\"", "", "}"); + } + + @Test + void varSetterProperty() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning("java.lang.String").setter() + .buildAccessor().value("\"This is a test\"")); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", + " var testProp: String = \"This is a test\"", " set", "", "}"); + } + + @Test + void varAnnotateSetterProperty() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning("java.lang.String").setter() + .withAnnotation(Annotation.name("org.springframework.beans.factory.annotation.Autowired")) + .buildAccessor().value("\"This is a test\"")); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", + " var testProp: String = \"This is a test\"", " @Autowired set", "", "}"); + } + + @Test + void varProperties() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning("Int").value(42)); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testDouble").returning("Double").value("1986.0")); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testFloat").value("99.999f")); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testLong").returning("Long").value("1986L")); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " var testProp: Int = 42", + "", " var testDouble: Double = 1986.0", "", " var testFloat = 99.999f", "", + " var testLong: Long = 1986L", "", "}"); + } + + @Test + void varEmptyProperty() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning("Int").empty()); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " var testProp: Int", "", + "}"); + } + + @Test + void varLateinitProperty() throws IOException { + KotlinSourceCode sourceCode = new KotlinSourceCode(); + KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); + KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); + test.addPropertyDeclaration( + KotlinPropertyDeclaration.var("testProp").modifiers(KotlinModifier.LATEINIT).returning("Int").empty()); + List lines = writeSingleType(sourceCode, "com/example/Test.kt"); + assertThat(lines).containsExactly("package com.example", "", "class Test {", "", + " lateinit var testProp: Int", "", "}"); + } + @Test void springBootApplication() throws IOException { KotlinSourceCode sourceCode = new KotlinSourceCode(); @@ -178,102 +294,6 @@ class KotlinSourceCodeWriterTests { "@TestApplication(target = One::class, unit = ChronoUnit.NANOS)", "class Test"); } - @Test - void valProperty() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration( - KotlinPropertyDeclaration.val("testProp").returning(KotlinString.CLASS_NAME).emptyValue()); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " val testProp: String", "", - "}"); - } - - @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(KotlinString.CLASS_NAME) - .value(KotlinString.stringValue("This is a TEST"))); - test.addPropertyDeclaration(KotlinPropertyDeclaration.val("withGetter").returning(KotlinString.CLASS_NAME) - .getter().withBody(new KotlinExpressionStatement(new KotlinMethodInvocation("testProp", "toLowerCase"))) - .buildAccessor().emptyValue()); - List 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 - void varProperty() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning(KotlinString.CLASS_NAME) - .value(KotlinString.stringValue("This is a test"))); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", - " var testProp: String = \"This is a test\"", "", "}"); - } - - @Test - void varPrivateSetterProperty() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning(KotlinString.CLASS_NAME) - .setter().isPrivate().buildAccessor().value(KotlinString.stringValue("This is a test"))); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", - " var testProp: String = \"This is a test\"", " private set", "", "}"); - } - - @Test - void varAnnotateSetterProperty() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp").returning(KotlinString.CLASS_NAME) - .setter().withAnnotation(Annotation.name("org.springframework.beans.factory.annotation.Autowired")) - .buildAccessor().value(KotlinString.stringValue("This is a test"))); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", - " var testProp: String = \"This is a test\"", " @Autowired set", "", "}"); - } - - @Test - void varProperties() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp") - .returning(KotlinPrimitives.KotlinInt.BOXED_CLASS_NAME).value(KotlinPrimitives.integerValue(42))); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testDouble") - .returning(KotlinPrimitives.KotlinDouble.BOXED_CLASS_NAME).value(KotlinPrimitives.doubleValue(1986d))); - test.addPropertyDeclaration( - KotlinPropertyDeclaration.var("testFloat").value(KotlinPrimitives.floatValue(99.999f))); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testLong") - .returning(KotlinPrimitives.KotlinLong.BOXED_CLASS_NAME).value(KotlinPrimitives.longValue(1986L))); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " var testProp: Int = 42", - "", " var testDouble: Double = 1986.0", "", " var testFloat = 99.999f", "", - " var testLong: Long = 1986L", "", "}"); - } - - @Test - void varEmptyProperty() throws IOException { - KotlinSourceCode sourceCode = new KotlinSourceCode(); - KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test"); - KotlinTypeDeclaration test = compilationUnit.createTypeDeclaration("Test"); - test.addPropertyDeclaration(KotlinPropertyDeclaration.var("testProp") - .returning(KotlinPrimitives.KotlinInt.BOXED_CLASS_NAME).empty()); - List lines = writeSingleType(sourceCode, "com/example/Test.kt"); - assertThat(lines).containsExactly("package com.example", "", "class Test {", "", " var testProp: Int", "", - "}"); - } - private List writeClassAnnotation(Annotation annotation) throws IOException { KotlinSourceCode sourceCode = new KotlinSourceCode(); KotlinCompilationUnit compilationUnit = sourceCode.createCompilationUnit("com.example", "Test");