diff --git a/.editorconfig b/.editorconfig index 42f4202..db22c58 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,3 +12,6 @@ ij_continuation_indent_size = 4 ij_java_class_count_to_use_import_on_demand = 999 ij_java_names_count_to_use_import_on_demand = 20 ij_java_imports_layout = *,|,javax.**,java.**,|,$* + +[*.yaml] +indent_size = 2 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a328262..683293c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,17 +34,50 @@ jobs: - uses: actions/cache@v4 with: path: ~/.m2/repository - key: build_and_test_maven + key: build_maven - name: Build - run: ./mvnw compile -e - - name: Test - run: ./mvnw test -e - - uses: actions/upload-artifact@v4 + run: ./mvnw install -e + - name: Upload generated sources + uses: actions/upload-artifact@v4 with: name: generated-sources path: | - it/target/generated-sources/* + it/java17/target/generated-sources if-no-files-found: error + - name: Upload jars + uses: actions/upload-artifact@v4 + with: + name: jars + path: | + ~/.m2/repository/org/sharedtype + if-no-files-found: error + - name: Remove jars from cache + run: rm -rf ~/.m2/repository/org/sharedtype + + jdk_compatibility_test: + needs: [build_and_test] + runs-on: ubuntu-latest + strategy: + matrix: + java: [ 8, 11 ] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: ${{ matrix.java }} + - uses: actions/download-artifact@v4 + with: + name: jars + path: ~/.m2/repository/org/sharedtype +# - name: Display downloaded artifact +# run: ls -lhR ~/.m2/repository/org/sharedtype + - uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: build_maven + - name: Test + run: ./mvnw verify -pl it/java8 -e client_test: needs: [build_and_test] @@ -57,9 +90,9 @@ jobs: - uses: actions/download-artifact@v4 with: name: generated-sources - path: it/target/generated-sources/ + path: it/java17/target/generated-sources - name: Display downloaded artifact - run: ls -lhR it/target/generated-sources + run: ls -lhR it/java17/target/generated-sources - name: Test Typescript working-directory: client-test/typescript run: | @@ -67,7 +100,7 @@ jobs: npm run test clean-artifact: - needs: [ client_test ] + needs: [ jdk_compatibility_test, client_test ] runs-on: ubuntu-latest if: always() steps: diff --git a/README.md b/README.md index 057cbb7..97f9caa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![CI](https://github.com/cuzfrog/sharedtype/actions/workflows/ci.yaml/badge.svg)](https://github.com/cuzfrog/sharedtype/actions/workflows/ci.yaml) # SharedType - Sharing Java Types made easy +* Client Java version >= 8. * Only client source dependency is `@SharedType`. * SharedType annotation processor jar is <100KB, only 2 small dependencies: jsr305 annotations and mustache. * Parsing takes milliseconds. See [Performance](doc/Performance.md). diff --git a/annotation/src/main/java/module-info.java b/annotation/src/main/java/module-info.java deleted file mode 100644 index fac4726..0000000 --- a/annotation/src/main/java/module-info.java +++ /dev/null @@ -1,3 +0,0 @@ -module org.sharedtype.annotation { - exports org.sharedtype.annotation; -} diff --git a/annotation/src/main/java/org/sharedtype/annotation/SharedType.java b/annotation/src/main/java/org/sharedtype/annotation/SharedType.java index fc48c81..11e7aa8 100644 --- a/annotation/src/main/java/org/sharedtype/annotation/SharedType.java +++ b/annotation/src/main/java/org/sharedtype/annotation/SharedType.java @@ -58,7 +58,7 @@ * unless the field or accessor is also ignored. *

*/ - @Target({ElementType.METHOD, ElementType.FIELD, ElementType.RECORD_COMPONENT, ElementType.TYPE}) + @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) @interface Ignore { } @@ -107,7 +107,7 @@ * */ @Target({ElementType.FIELD, ElementType.PARAMETER}) - @Retention(RetentionPolicy.SOURCE) + @Retention(RetentionPolicy.CLASS) @interface EnumValue { } @@ -115,17 +115,17 @@ enum ComponentType { /** * Represents: * */ FIELDS, /** - * Represents: + * Represents 0 argument non-static methods: * */ ACCESSORS, diff --git a/client-test/typescript/src/index.d.ts b/client-test/typescript/src/index.d.ts index c8f446e..3f4aa85 100644 --- a/client-test/typescript/src/index.d.ts +++ b/client-test/typescript/src/index.d.ts @@ -1 +1 @@ -export type * from "../../../it/target/generated-sources/types.d.ts"; +export type * from "../../../it/java17/target/generated-sources/types.d.ts"; diff --git a/client-test/typescript/tests/enum-union.ts b/client-test/typescript/tests/enum-union.ts index 09b6b2a..5e0e22c 100644 --- a/client-test/typescript/tests/enum-union.ts +++ b/client-test/typescript/tests/enum-union.ts @@ -1,9 +1,53 @@ -import type { EnumGalaxy, EnumSize, EnumTShirt } from "../src/index.js"; +import type {DependencyClassA, DependencyClassB, DependencyClassC, EnumGalaxy, EnumSize, EnumTShirt, JavaRecord} from "../src/index.js"; export const list1: EnumGalaxy[] = ["Andromeda", "MilkyWay", "Triangulum"]; export const record1: Record = { - S: 1, - M: 2, - L: 3, + S: 1, + M: 2, + L: 3, } export const size1: EnumSize = 1; + +export const dependencyClassC: DependencyClassC = {} as DependencyClassC; + +export const dependencyClassB: DependencyClassB = { + c: dependencyClassC +} + +export const dependencyClassA: DependencyClassA = { + a: 0, + b: dependencyClassB +}; +dependencyClassC.a = dependencyClassA + +export const obj: Omit, "aVoid" | "genericMap"> = { + boxedBoolean: false, + boxedByte: 0, + boxedChar: "", + boxedDouble: 0, + boxedFloat: 0, + boxedInt: 0, + boxedIntArray: [], + boxedLong: 0, + boxedShort: 0, + containerStringList: [], + containerStringListCollection: [], + cyclicDependency: dependencyClassA, + duplicateAccessor: "", + enumGalaxy: "MilkyWay", + enumSize: 3, + genericList: [], + genericListSet: [], + genericSet: [], + intArray: [], + object: undefined, + primitiveBoolean: false, + primitiveByte: 0, + primitiveChar: "", + primitiveDouble: 0, + primitiveFloat: 0, + primitiveInt: 0, + primitiveLong: 0, + primitiveShort: 0, + string: "", +}; diff --git a/doc/Development.md b/doc/Development.md index 9117134..c8c8ed3 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -1,7 +1,9 @@ # Development Guide ## Setup -Setup Java env vars (>= Java17 for development): +Linux is recommended. If you use Windows, you can use WSL with a remotely connected IDE. Windows 11 supports GUI app inside WSL. + +Setup Java env vars (>= Java17 for development), configure `JAVA17_HOME` to point to your Java installation: ```bash . setenv ``` @@ -10,8 +12,6 @@ Optionally mount tmpfs to save your disk by: ./mount-tmpfs.sh ``` -If you encounter compilation problems with your IDE, delegate compilation to maven. - ## Style check ```bash ./mvnw editorconfig:check @@ -24,11 +24,32 @@ Debug annotation processor by run maven build: ``` Then attach your debugger on it. -## Run Integration test +## Run test +If you encounter compilation problems with your IDE, delegate compilation to maven. +Before run test in IDE/individual module, run `./mvnw clean install -DskipTests` to build dependency classes. + +#### E.g. run integration test locally: ```bash -./mvnw clean install -DskipTests -q && ./mvnw test -pl it +./mvnw clean install -DskipTests -q && ./mvnw test -pl it/java17 -pl it/java8 ``` +#### Run local verification with all java tests +```bash +./mvnw verify +``` + +#### Verify JDK8 compatibility locally +Setup `JAVA8_HOME` to point to your Java8 installation. +```bash +. setenv 8 +./mvnw verify -pl it/java8 +``` + +#### Run client tests locally +Client tests are run in target languages in respective dir inside `./client-test`. They do basic type checking. +* Typescript. `. setenv && npm i && npm run test` + + ## Coding Style Guide -1. since annotation processing is one shot execution, JIT is not likely to optimize the code. So please try to avoid long calling stacks like Stream chains. -2. no dependencies without strong justification. +1. since annotation processing is one shot execution, JIT is not likely to optimize the code. So prefer plain loop than long calling stacks like Stream chains. +2. no adding dependencies without strong justification. diff --git a/doc/Usage.md b/doc/Usage.md index d3d2035..96dc42f 100644 --- a/doc/Usage.md +++ b/doc/Usage.md @@ -81,3 +81,8 @@ See [Default Properties](../processor/src/main/resources/sharedtype-default.prop #### Per annotation options See Javadoc on [@SharedType](../annotation/src/main/java/org/sharedtype/annotation/SharedType.java) for details. + +### Limitations +* Current design only retain `@SharedType` on source level. That means they are not visible if it is in a dependency jar during its dependent's compilation. +You have to execute the annotation processing on the same classpath with source code. +For multiple module builds, a workaround is to execute on every module. diff --git a/internal/src/main/java/org/sharedtype/domain/ArrayTypeInfo.java b/internal/src/main/java/org/sharedtype/domain/ArrayTypeInfo.java index cd9e68c..04d9190 100644 --- a/internal/src/main/java/org/sharedtype/domain/ArrayTypeInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/ArrayTypeInfo.java @@ -1,6 +1,17 @@ package org.sharedtype.domain; -public record ArrayTypeInfo(TypeInfo component) implements TypeInfo { +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@EqualsAndHashCode +public final class ArrayTypeInfo implements TypeInfo { + private final TypeInfo component; + + public TypeInfo component() { + return component; + } + @Override public boolean resolved() { return component.resolved(); diff --git a/internal/src/main/java/org/sharedtype/domain/ClassDef.java b/internal/src/main/java/org/sharedtype/domain/ClassDef.java index a8269f5..b1b216b 100644 --- a/internal/src/main/java/org/sharedtype/domain/ClassDef.java +++ b/internal/src/main/java/org/sharedtype/domain/ClassDef.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * Represents info captured from an interface, class, or record. @@ -68,21 +69,21 @@ public boolean resolved() { @Override public String toString() { - var rows = new ArrayList(components.size()+2); + List rows = new ArrayList<>(components.size()+2); rows.add(String.format("%s%s%s {", simpleName, typeVariablesToString(), supertypesToString())); - rows.addAll(components.stream().map(f -> String.format(" %s", f)).toList()); + rows.addAll(components.stream().map(f -> String.format(" %s", f)).collect(Collectors.toList())); rows.add("}"); return String.join(System.lineSeparator(), rows); } private String typeVariablesToString() { - return typeVariables.isEmpty() ? "" : "<" + String.join(",", typeVariables.stream().map(TypeVariableInfo::toString).toList()) + ">"; + return typeVariables.isEmpty() ? "" : "<" + String.join(",", typeVariables.stream().map(TypeVariableInfo::toString).collect(Collectors.toList())) + ">"; } private String supertypesToString() { if (supertypes.isEmpty()) { return ""; } - return " extends " + String.join(" & ", supertypes.stream().map(t -> t + (t.resolved() ? "" : "?")).toList()); + return " extends " + String.join(" & ", supertypes.stream().map(t -> t + (t.resolved() ? "" : "?")).collect(Collectors.toList())); } } diff --git a/internal/src/main/java/org/sharedtype/domain/ComponentInfo.java b/internal/src/main/java/org/sharedtype/domain/ComponentInfo.java index 8690cfd..bd6e7cf 100644 --- a/internal/src/main/java/org/sharedtype/domain/ComponentInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/ComponentInfo.java @@ -2,6 +2,6 @@ import java.io.Serializable; -public sealed interface ComponentInfo extends Serializable permits EnumValueInfo, FieldComponentInfo { +public interface ComponentInfo extends Serializable { boolean resolved(); } diff --git a/internal/src/main/java/org/sharedtype/domain/ConcreteTypeInfo.java b/internal/src/main/java/org/sharedtype/domain/ConcreteTypeInfo.java index 50da329..bdcc0e2 100644 --- a/internal/src/main/java/org/sharedtype/domain/ConcreteTypeInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/ConcreteTypeInfo.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; @EqualsAndHashCode(of = "qualifiedName") @Builder @@ -49,7 +50,7 @@ public List typeArgs() { public String toString() { return String.format("%s%s%s", qualifiedName, - typeArgs.isEmpty() ? "" : "<" + String.join(",", typeArgs.stream().map(TypeInfo::toString).toList()) + ">", + typeArgs.isEmpty() ? "" : "<" + typeArgs.stream().map(TypeInfo::toString).collect(Collectors.joining(",")) + ">", resolved ? "" : "?" ); } diff --git a/internal/src/main/java/org/sharedtype/domain/ConstantInfo.java b/internal/src/main/java/org/sharedtype/domain/ConstantInfo.java index ba5c8cf..4071902 100644 --- a/internal/src/main/java/org/sharedtype/domain/ConstantInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/ConstantInfo.java @@ -1,5 +1,5 @@ package org.sharedtype.domain; -public record ConstantInfo() { +public final class ConstantInfo { } diff --git a/internal/src/main/java/org/sharedtype/domain/Constants.java b/internal/src/main/java/org/sharedtype/domain/Constants.java index 7ac2848..be9b4c4 100644 --- a/internal/src/main/java/org/sharedtype/domain/Constants.java +++ b/internal/src/main/java/org/sharedtype/domain/Constants.java @@ -3,6 +3,7 @@ import org.sharedtype.annotation.SharedType; import javax.lang.model.type.TypeKind; +import java.util.HashMap; import java.util.Map; public final class Constants { @@ -33,34 +34,36 @@ public final class Constants { public static final ConcreteTypeInfo OPTIONAL_TYPE_INFO = ConcreteTypeInfo.ofPredefined("java.util.Optional", "Optional"); public static final ConcreteTypeInfo MAP_TYPE_INFO = ConcreteTypeInfo.ofPredefined("java.util.Map", "Map"); - public static final Map PRIMITIVES = Map.of( - TypeKind.BOOLEAN, BOOLEAN_TYPE_INFO, - TypeKind.BYTE, BYTE_TYPE_INFO, - TypeKind.CHAR, CHAR_TYPE_INFO, - TypeKind.DOUBLE, DOUBLE_TYPE_INFO, - TypeKind.FLOAT, FLOAT_TYPE_INFO, - TypeKind.INT, INT_TYPE_INFO, - TypeKind.LONG, LONG_TYPE_INFO, - TypeKind.SHORT, SHORT_TYPE_INFO - ); + public static final Map PRIMITIVES = new HashMap<>(8); + static { + PRIMITIVES.put(TypeKind.BOOLEAN, BOOLEAN_TYPE_INFO); + PRIMITIVES.put(TypeKind.BYTE, BYTE_TYPE_INFO); + PRIMITIVES.put(TypeKind.CHAR, CHAR_TYPE_INFO); + PRIMITIVES.put(TypeKind.DOUBLE, DOUBLE_TYPE_INFO); + PRIMITIVES.put(TypeKind.FLOAT, FLOAT_TYPE_INFO); + PRIMITIVES.put(TypeKind.INT, INT_TYPE_INFO); + PRIMITIVES.put(TypeKind.LONG, LONG_TYPE_INFO); + PRIMITIVES.put(TypeKind.SHORT, SHORT_TYPE_INFO); + } - public static final Map PREDEFINED_OBJECT_TYPES = Map.ofEntries( - Map.entry("java.lang.Boolean", BOXED_BOOLEAN_TYPE_INFO), - Map.entry("java.lang.Byte", BOXED_BYTE_TYPE_INFO), - Map.entry("java.lang.Character", BOXED_CHAR_TYPE_INFO), - Map.entry("java.lang.Double", BOXED_DOUBLE_TYPE_INFO), - Map.entry("java.lang.Float", BOXED_FLOAT_TYPE_INFO), - Map.entry("java.lang.Integer", BOXED_INT_TYPE_INFO), - Map.entry("java.lang.Long", BOXED_LONG_TYPE_INFO), - Map.entry("java.lang.Short", BOXED_SHORT_TYPE_INFO), - Map.entry("java.lang.String", STRING_TYPE_INFO), - Map.entry("java.lang.Void", VOID_TYPE_INFO), - Map.entry("java.lang.Object", OBJECT_TYPE_INFO), - Map.entry("java.lang.Class", CLASS_TYPE_INFO), - Map.entry("java.lang.Enum", ENUM_TYPE_INFO), - Map.entry("java.util.Optional", OPTIONAL_TYPE_INFO) -// Map.entry("java.util.Map", MAP_TYPE_INFO) // TODO: Map support - ); + public static final Map PREDEFINED_OBJECT_TYPES = new HashMap<>(16); + static { + PREDEFINED_OBJECT_TYPES.put("java.lang.Boolean", BOXED_BOOLEAN_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Byte", BOXED_BYTE_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Character", BOXED_CHAR_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Double", BOXED_DOUBLE_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Float", BOXED_FLOAT_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Integer", BOXED_INT_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Long", BOXED_LONG_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Short", BOXED_SHORT_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.String", STRING_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Void", VOID_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Object", OBJECT_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Class", CLASS_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.lang.Enum", ENUM_TYPE_INFO); + PREDEFINED_OBJECT_TYPES.put("java.util.Optional", OPTIONAL_TYPE_INFO); + // PREDEFINED_OBJECT_TYPES.put("java.util.Map", MAP_TYPE_INFO); // TODO: Map support + }; private Constants() { } diff --git a/internal/src/main/java/org/sharedtype/domain/EnumDef.java b/internal/src/main/java/org/sharedtype/domain/EnumDef.java index 686051b..a023142 100644 --- a/internal/src/main/java/org/sharedtype/domain/EnumDef.java +++ b/internal/src/main/java/org/sharedtype/domain/EnumDef.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; @EqualsAndHashCode(of = "qualifiedName") @Builder @@ -38,7 +39,7 @@ public boolean resolved() { public String toString() { return String.format("%s[%s]", qualifiedName, - enumValueInfos.isEmpty() ? "" : String.join(",", enumValueInfos.stream().map(EnumValueInfo::toString).toList()) + enumValueInfos.isEmpty() ? "" : String.join(",", enumValueInfos.stream().map(EnumValueInfo::toString).collect(Collectors.toList())) ); } } diff --git a/internal/src/main/java/org/sharedtype/domain/EnumInfo.java b/internal/src/main/java/org/sharedtype/domain/EnumInfo.java deleted file mode 100644 index ca9cf1e..0000000 --- a/internal/src/main/java/org/sharedtype/domain/EnumInfo.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.sharedtype.domain; - -public record EnumInfo() { - -} diff --git a/internal/src/main/java/org/sharedtype/domain/EnumValueInfo.java b/internal/src/main/java/org/sharedtype/domain/EnumValueInfo.java index fc3c786..922c89d 100644 --- a/internal/src/main/java/org/sharedtype/domain/EnumValueInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/EnumValueInfo.java @@ -1,6 +1,22 @@ package org.sharedtype.domain; -public record EnumValueInfo(TypeInfo type, Object value) implements ComponentInfo { +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; + +@EqualsAndHashCode +@RequiredArgsConstructor +public final class EnumValueInfo implements ComponentInfo { + private final TypeInfo type; + private final Object value; + + public TypeInfo type() { + return type; + } + + public Object value() { + return value; + } + @Override public boolean resolved() { return type.resolved(); diff --git a/internal/src/main/java/org/sharedtype/domain/FieldComponentInfo.java b/internal/src/main/java/org/sharedtype/domain/FieldComponentInfo.java index e9e5145..2bce2be 100644 --- a/internal/src/main/java/org/sharedtype/domain/FieldComponentInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/FieldComponentInfo.java @@ -6,12 +6,22 @@ import java.util.Set; @Builder -public record FieldComponentInfo( - String name, - Set modifiers, - boolean optional, - TypeInfo type -) implements ComponentInfo { +public final class FieldComponentInfo implements ComponentInfo { + private final String name; + private final Set modifiers; + private final boolean optional; + private final TypeInfo type; + + public String name() { + return name; + } + public boolean optional() { + return optional; + } + + public TypeInfo type() { + return type; + } @Override public boolean resolved() { diff --git a/internal/src/main/java/org/sharedtype/domain/TypeDef.java b/internal/src/main/java/org/sharedtype/domain/TypeDef.java index 4a89090..4b2215c 100644 --- a/internal/src/main/java/org/sharedtype/domain/TypeDef.java +++ b/internal/src/main/java/org/sharedtype/domain/TypeDef.java @@ -3,7 +3,7 @@ import java.io.Serializable; import java.util.List; -public sealed interface TypeDef extends Serializable permits ClassDef, EnumDef { +public interface TypeDef extends Serializable { String qualifiedName(); String simpleName(); diff --git a/internal/src/main/java/org/sharedtype/domain/TypeInfo.java b/internal/src/main/java/org/sharedtype/domain/TypeInfo.java index a437b6d..29243af 100644 --- a/internal/src/main/java/org/sharedtype/domain/TypeInfo.java +++ b/internal/src/main/java/org/sharedtype/domain/TypeInfo.java @@ -2,6 +2,6 @@ import java.io.Serializable; -public sealed interface TypeInfo extends Serializable permits ArrayTypeInfo, ConcreteTypeInfo, TypeVariableInfo { +public interface TypeInfo extends Serializable { boolean resolved(); } diff --git a/it/java17/pom.xml b/it/java17/pom.xml new file mode 100644 index 0000000..6ed5da8 --- /dev/null +++ b/it/java17/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + org.sharedtype + sharedtype-it-parent + 0.1-SNAPSHOT + ../pom.xml + + + sharedtype-it-java17 + SharedType Integration Test Java17 + + + 17 + 17 + + diff --git a/it/src/main/java/org/sharedtype/it/types/Container.java b/it/java17/src/main/java/org/sharedtype/it/types/Container.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/Container.java rename to it/java17/src/main/java/org/sharedtype/it/types/Container.java diff --git a/it/src/main/java/org/sharedtype/it/types/DependencyClassA.java b/it/java17/src/main/java/org/sharedtype/it/types/DependencyClassA.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/DependencyClassA.java rename to it/java17/src/main/java/org/sharedtype/it/types/DependencyClassA.java diff --git a/it/src/main/java/org/sharedtype/it/types/DependencyClassB.java b/it/java17/src/main/java/org/sharedtype/it/types/DependencyClassB.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/DependencyClassB.java rename to it/java17/src/main/java/org/sharedtype/it/types/DependencyClassB.java diff --git a/it/src/main/java/org/sharedtype/it/types/DependencyClassC.java b/it/java17/src/main/java/org/sharedtype/it/types/DependencyClassC.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/DependencyClassC.java rename to it/java17/src/main/java/org/sharedtype/it/types/DependencyClassC.java diff --git a/it/src/main/java/org/sharedtype/it/types/EnumGalaxy.java b/it/java17/src/main/java/org/sharedtype/it/types/EnumGalaxy.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/EnumGalaxy.java rename to it/java17/src/main/java/org/sharedtype/it/types/EnumGalaxy.java diff --git a/it/src/main/java/org/sharedtype/it/types/EnumSize.java b/it/java17/src/main/java/org/sharedtype/it/types/EnumSize.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/EnumSize.java rename to it/java17/src/main/java/org/sharedtype/it/types/EnumSize.java diff --git a/it/src/main/java/org/sharedtype/it/types/EnumTShirt.java b/it/java17/src/main/java/org/sharedtype/it/types/EnumTShirt.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/EnumTShirt.java rename to it/java17/src/main/java/org/sharedtype/it/types/EnumTShirt.java diff --git a/it/src/main/java/org/sharedtype/it/types/InterfaceA.java b/it/java17/src/main/java/org/sharedtype/it/types/InterfaceA.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/InterfaceA.java rename to it/java17/src/main/java/org/sharedtype/it/types/InterfaceA.java diff --git a/it/src/main/java/org/sharedtype/it/types/JavaRecord.java b/it/java17/src/main/java/org/sharedtype/it/types/JavaRecord.java similarity index 88% rename from it/src/main/java/org/sharedtype/it/types/JavaRecord.java rename to it/java17/src/main/java/org/sharedtype/it/types/JavaRecord.java index c5b7bd2..744fe7b 100644 --- a/it/src/main/java/org/sharedtype/it/types/JavaRecord.java +++ b/it/java17/src/main/java/org/sharedtype/it/types/JavaRecord.java @@ -45,14 +45,17 @@ public record JavaRecord( EnumGalaxy enumGalaxy, EnumSize enumSize, - String duplicateAccessor + String duplicateAccessor, + @SharedType.Ignore String explicitlyIgnored ) implements InterfaceA { + static final int STATIC_FIELD = 888; + @SharedType.Accessor String getDuplicateAccessor() { return duplicateAccessor; } - String getShouldNotBeIncluded() { + String shouldNotBeIncluded() { return null; } } diff --git a/it/src/main/java/org/sharedtype/it/types/SuperClassA.java b/it/java17/src/main/java/org/sharedtype/it/types/SuperClassA.java similarity index 100% rename from it/src/main/java/org/sharedtype/it/types/SuperClassA.java rename to it/java17/src/main/java/org/sharedtype/it/types/SuperClassA.java diff --git a/it/src/test/java/org/sharedtype/domain/EnumTShirtIntegrationTest.java b/it/java17/src/test/java/org/sharedtype/domain/EnumTShirtIntegrationTest.java similarity index 100% rename from it/src/test/java/org/sharedtype/domain/EnumTShirtIntegrationTest.java rename to it/java17/src/test/java/org/sharedtype/domain/EnumTShirtIntegrationTest.java diff --git a/it/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java b/it/java17/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java similarity index 84% rename from it/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java rename to it/java17/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java index 497ab9b..4e87d21 100644 --- a/it/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java +++ b/it/java17/src/test/java/org/sharedtype/domain/JavaRecordIntegrationTest.java @@ -28,17 +28,9 @@ void supertypes() { assertThat(supertypeInfo.qualifiedName()).isEqualTo("org.sharedtype.it.types.InterfaceA"); } - @Test - void duplicateAccessorField() { - var duplicateAccessorField = classDef.components().get(0); - assertThat(duplicateAccessorField.name()).isEqualTo("duplicateAccessor"); - var typeInfo = (ConcreteTypeInfo)duplicateAccessorField.type(); - assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.String"); - } - @Test void stringField() { - var stringField = classDef.components().get(1); + var stringField = classDef.components().get(0); assertThat(stringField.name()).isEqualTo("string"); var typeInfo = (ConcreteTypeInfo)stringField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.String"); @@ -46,7 +38,7 @@ void stringField() { @Test void primitiveByteField() { - var primitiveByteField = classDef.components().get(2); + var primitiveByteField = classDef.components().get(1); assertThat(primitiveByteField.name()).isEqualTo("primitiveByte"); var typeInfo = (ConcreteTypeInfo)primitiveByteField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("byte"); @@ -54,7 +46,7 @@ void primitiveByteField() { @Test void boxedByteField() { - var boxedByteField = classDef.components().get(3); + var boxedByteField = classDef.components().get(2); assertThat(boxedByteField.name()).isEqualTo("boxedByte"); var typeInfo = (ConcreteTypeInfo)boxedByteField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Byte"); @@ -62,7 +54,7 @@ void boxedByteField() { @Test void primitiveShortField() { - var primitiveShortField = classDef.components().get(4); + var primitiveShortField = classDef.components().get(3); assertThat(primitiveShortField.name()).isEqualTo("primitiveShort"); var typeInfo = (ConcreteTypeInfo)primitiveShortField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("short"); @@ -70,7 +62,7 @@ void primitiveShortField() { @Test void boxedShortField() { - var boxedShortField = classDef.components().get(5); + var boxedShortField = classDef.components().get(4); assertThat(boxedShortField.name()).isEqualTo("boxedShort"); var typeInfo = (ConcreteTypeInfo)boxedShortField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Short"); @@ -78,7 +70,7 @@ void boxedShortField() { @Test void primitiveIntField() { - var primitiveIntField = classDef.components().get(6); + var primitiveIntField = classDef.components().get(5); assertThat(primitiveIntField.name()).isEqualTo("primitiveInt"); var typeInfo = (ConcreteTypeInfo)primitiveIntField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("int"); @@ -86,7 +78,7 @@ void primitiveIntField() { @Test void boxedIntField() { - var boxedIntField = classDef.components().get(7); + var boxedIntField = classDef.components().get(6); assertThat(boxedIntField.name()).isEqualTo("boxedInt"); var typeInfo = (ConcreteTypeInfo)boxedIntField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Integer"); @@ -94,7 +86,7 @@ void boxedIntField() { @Test void primitiveLongField() { - var primitiveLongField = classDef.components().get(8); + var primitiveLongField = classDef.components().get(7); assertThat(primitiveLongField.name()).isEqualTo("primitiveLong"); var typeInfo = (ConcreteTypeInfo)primitiveLongField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("long"); @@ -102,7 +94,7 @@ void primitiveLongField() { @Test void boxedLongField() { - var boxedLongField = classDef.components().get(9); + var boxedLongField = classDef.components().get(8); assertThat(boxedLongField.name()).isEqualTo("boxedLong"); var typeInfo = (ConcreteTypeInfo)boxedLongField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Long"); @@ -110,7 +102,7 @@ void boxedLongField() { @Test void primitiveFloatField() { - var primitiveFloatField = classDef.components().get(10); + var primitiveFloatField = classDef.components().get(9); assertThat(primitiveFloatField.name()).isEqualTo("primitiveFloat"); var typeInfo = (ConcreteTypeInfo)primitiveFloatField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("float"); @@ -118,7 +110,7 @@ void primitiveFloatField() { @Test void boxedFloatField() { - var boxedFloatField = classDef.components().get(11); + var boxedFloatField = classDef.components().get(10); assertThat(boxedFloatField.name()).isEqualTo("boxedFloat"); var typeInfo = (ConcreteTypeInfo)boxedFloatField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Float"); @@ -126,7 +118,7 @@ void boxedFloatField() { @Test void primitiveDoubleField() { - var primitiveDoubleField = classDef.components().get(12); + var primitiveDoubleField = classDef.components().get(11); assertThat(primitiveDoubleField.name()).isEqualTo("primitiveDouble"); var typeInfo = (ConcreteTypeInfo)primitiveDoubleField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("double"); @@ -134,7 +126,7 @@ void primitiveDoubleField() { @Test void boxedDoubleField() { - var boxedDoubleField = classDef.components().get(13); + var boxedDoubleField = classDef.components().get(12); assertThat(boxedDoubleField.name()).isEqualTo("boxedDouble"); var typeInfo = (ConcreteTypeInfo)boxedDoubleField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Double"); @@ -142,7 +134,7 @@ void boxedDoubleField() { @Test void primitiveBooleanField() { - var primitiveBooleanField = classDef.components().get(14); + var primitiveBooleanField = classDef.components().get(13); assertThat(primitiveBooleanField.name()).isEqualTo("primitiveBoolean"); var typeInfo = (ConcreteTypeInfo)primitiveBooleanField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("boolean"); @@ -150,7 +142,7 @@ void primitiveBooleanField() { @Test void boxedBooleanField() { - var boxedBooleanField = classDef.components().get(15); + var boxedBooleanField = classDef.components().get(14); assertThat(boxedBooleanField.name()).isEqualTo("boxedBoolean"); var typeInfo = (ConcreteTypeInfo)boxedBooleanField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Boolean"); @@ -158,7 +150,7 @@ void boxedBooleanField() { @Test void primitiveCharField() { - var primitiveCharField = classDef.components().get(16); + var primitiveCharField = classDef.components().get(15); assertThat(primitiveCharField.name()).isEqualTo("primitiveChar"); var typeInfo = (ConcreteTypeInfo)primitiveCharField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("char"); @@ -166,7 +158,7 @@ void primitiveCharField() { @Test void boxedCharField() { - var boxedCharField = classDef.components().get(17); + var boxedCharField = classDef.components().get(16); assertThat(boxedCharField.name()).isEqualTo("boxedChar"); var typeInfo = (ConcreteTypeInfo)boxedCharField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Character"); @@ -174,7 +166,7 @@ void boxedCharField() { @Test void objectField() { - var objectField = classDef.components().get(18); + var objectField = classDef.components().get(17); assertThat(objectField.name()).isEqualTo("object"); var typeInfo = (ConcreteTypeInfo)objectField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Object"); @@ -182,7 +174,7 @@ void objectField() { @Test void aVoidField() { - var aVoidField = classDef.components().get(19); + var aVoidField = classDef.components().get(18); assertThat(aVoidField.name()).isEqualTo("aVoid"); var typeInfo = (ConcreteTypeInfo)aVoidField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.Void"); @@ -190,7 +182,7 @@ void aVoidField() { @Test void cyclicDependencyField() { - var cyclicDependencyField = classDef.components().get(20); + var cyclicDependencyField = classDef.components().get(19); assertThat(cyclicDependencyField.name()).isEqualTo("cyclicDependency"); var typeInfo = (ConcreteTypeInfo)cyclicDependencyField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("org.sharedtype.it.types.DependencyClassA"); @@ -198,7 +190,7 @@ void cyclicDependencyField() { @Test void containerStringListField() { - var containerStringListField = classDef.components().get(21); + var containerStringListField = classDef.components().get(20); assertThat(containerStringListField.name()).isEqualTo("containerStringList"); var arrayTypeInfo = (ArrayTypeInfo)containerStringListField.type(); var typeInfo = (ConcreteTypeInfo)arrayTypeInfo.component(); @@ -209,7 +201,7 @@ void containerStringListField() { @Test void containerStringListCollectionField() { - var containerStringListCollectionField = classDef.components().get(22); + var containerStringListCollectionField = classDef.components().get(21); assertThat(containerStringListCollectionField.name()).isEqualTo("containerStringListCollection"); var arrayTypeInfo = (ArrayTypeInfo)containerStringListCollectionField.type(); var nestedArrayTypeInfo = (ArrayTypeInfo)arrayTypeInfo.component(); @@ -221,7 +213,7 @@ void containerStringListCollectionField() { @Test void genericListField() { - var genericListField = classDef.components().get(23); + var genericListField = classDef.components().get(22); assertThat(genericListField.name()).isEqualTo("genericList"); var arrayTypeInfo = (ArrayTypeInfo)genericListField.type(); var typeInfo = (ConcreteTypeInfo)arrayTypeInfo.component(); @@ -230,7 +222,7 @@ void genericListField() { @Test void genericSetField() { - var genericSetField = classDef.components().get(24); + var genericSetField = classDef.components().get(23); assertThat(genericSetField.name()).isEqualTo("genericSet"); var arrayTypeInfo = (ArrayTypeInfo)genericSetField.type(); var typeInfo = (ConcreteTypeInfo)arrayTypeInfo.component(); @@ -239,7 +231,7 @@ void genericSetField() { @Test void genericListSetField() { - var genericListSetField = classDef.components().get(25); + var genericListSetField = classDef.components().get(24); assertThat(genericListSetField.name()).isEqualTo("genericListSet"); var arrayTypeInfo = (ArrayTypeInfo)genericListSetField.type(); var nestedArrayTypeInfo = (ArrayTypeInfo)arrayTypeInfo.component(); @@ -247,9 +239,14 @@ void genericListSetField() { assertThat(typeInfo.qualifiedName()).isEqualTo("T"); } + @Test + void genericMapField() { + // TODO + } + @Test void intArrayField() { - var integerArrayField = classDef.components().get(27); + var integerArrayField = classDef.components().get(26); assertThat(integerArrayField.name()).isEqualTo("intArray"); var arrayTypeInfo = (ArrayTypeInfo)integerArrayField.type(); var typeInfo = (ConcreteTypeInfo)arrayTypeInfo.component(); @@ -258,7 +255,7 @@ void intArrayField() { @Test void boxedIntArrayField() { - var boxedIntArrayField = classDef.components().get(28); + var boxedIntArrayField = classDef.components().get(27); assertThat(boxedIntArrayField.name()).isEqualTo("boxedIntArray"); var arrayTypeInfo = (ArrayTypeInfo)boxedIntArrayField.type(); var typeInfo = (ConcreteTypeInfo)arrayTypeInfo.component(); @@ -267,7 +264,7 @@ void boxedIntArrayField() { @Test void enumGalaxyField() { - var enumGalaxyField = classDef.components().get(29); + var enumGalaxyField = classDef.components().get(28); assertThat(enumGalaxyField.name()).isEqualTo("enumGalaxy"); var typeInfo = (ConcreteTypeInfo)enumGalaxyField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("org.sharedtype.it.types.EnumGalaxy"); @@ -275,12 +272,20 @@ void enumGalaxyField() { @Test void enumSizeField() { - var enumSizeField = classDef.components().get(30); + var enumSizeField = classDef.components().get(29); assertThat(enumSizeField.name()).isEqualTo("enumSize"); var typeInfo = (ConcreteTypeInfo)enumSizeField.type(); assertThat(typeInfo.qualifiedName()).isEqualTo("org.sharedtype.it.types.EnumSize"); } + @Test + void duplicateAccessorField() { + var duplicateAccessorField = classDef.components().get(30); + assertThat(duplicateAccessorField.name()).isEqualTo("duplicateAccessor"); + var typeInfo = (ConcreteTypeInfo)duplicateAccessorField.type(); + assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.String"); + } + @Test void fieldsSize() { assertThat(classDef.components().size()).isEqualTo(31); diff --git a/it/src/test/java/org/sharedtype/domain/TypeDefIntegrationTest.java b/it/java17/src/test/java/org/sharedtype/domain/TypeDefIntegrationTest.java similarity index 100% rename from it/src/test/java/org/sharedtype/domain/TypeDefIntegrationTest.java rename to it/java17/src/test/java/org/sharedtype/domain/TypeDefIntegrationTest.java diff --git a/it/java8/pom.xml b/it/java8/pom.xml new file mode 100644 index 0000000..8d716db --- /dev/null +++ b/it/java8/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + org.sharedtype + sharedtype-it-parent + 0.1-SNAPSHOT + ../pom.xml + + + sharedtype-it-java8 + SharedType Integration Test Java8 + + + 8 + 8 + + diff --git a/it/java8/setenv b/it/java8/setenv new file mode 100755 index 0000000..ba1628b --- /dev/null +++ b/it/java8/setenv @@ -0,0 +1,8 @@ +#!/bin/bash + +export JAVA_HOME=$JAVA8_HOME +export PATH=$JAVA_HOME/bin:$PATH + +java -version +alias mvnw="../../mvnw" +echo "alias mvnw is point to ../../mvnw" diff --git a/it/java8/src/main/java/org/sharedtype/it/types/EnumSize.java b/it/java8/src/main/java/org/sharedtype/it/types/EnumSize.java new file mode 100644 index 0000000..26d0b2a --- /dev/null +++ b/it/java8/src/main/java/org/sharedtype/it/types/EnumSize.java @@ -0,0 +1,12 @@ +package org.sharedtype.it.types; + +import lombok.RequiredArgsConstructor; +import org.sharedtype.annotation.SharedType; + +@RequiredArgsConstructor +public enum EnumSize { + SMALL(1), MEDIUM(2), LARGE(3); + + @SharedType.EnumValue + private final int size; +} diff --git a/it/java8/src/main/java/org/sharedtype/it/types/JavaClass.java b/it/java8/src/main/java/org/sharedtype/it/types/JavaClass.java new file mode 100644 index 0000000..0fca913 --- /dev/null +++ b/it/java8/src/main/java/org/sharedtype/it/types/JavaClass.java @@ -0,0 +1,9 @@ +package org.sharedtype.it.types; + +import org.sharedtype.annotation.SharedType; + +@SharedType +class JavaClass { + private String string; + private EnumSize size; +} diff --git a/it/java8/src/test/java/org/sharedtype/domain/EnumValueIntegrationTest.java b/it/java8/src/test/java/org/sharedtype/domain/EnumValueIntegrationTest.java new file mode 100644 index 0000000..39390a6 --- /dev/null +++ b/it/java8/src/test/java/org/sharedtype/domain/EnumValueIntegrationTest.java @@ -0,0 +1,28 @@ +package org.sharedtype.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sharedtype.domain.TypeDefDeserializer.deserializeTypeDef; + +final class EnumValueIntegrationTest { + @Test + void enumSize() { + EnumDef enumSize = (EnumDef) deserializeTypeDef("EnumSize.ser"); + assertThat(enumSize.simpleName()).isEqualTo("EnumSize"); + assertThat(enumSize.qualifiedName()).isEqualTo("org.sharedtype.it.types.EnumSize"); + assertThat(enumSize.components()).hasSize(3).allMatch(constant -> { + ConcreteTypeInfo typeInfo = (ConcreteTypeInfo)constant.type(); + return typeInfo.qualifiedName().equals("int"); + }); + + EnumValueInfo constant1 = enumSize.components().get(0); + assertThat(constant1.value()).isEqualTo(1); + + EnumValueInfo constant2 = enumSize.components().get(1); + assertThat(constant2.value()).isEqualTo(2); + + EnumValueInfo constant3 = enumSize.components().get(2); + assertThat(constant3.value()).isEqualTo(3); + } +} diff --git a/it/java8/src/test/java/org/sharedtype/domain/JavaClassIntegrationTest.java b/it/java8/src/test/java/org/sharedtype/domain/JavaClassIntegrationTest.java new file mode 100644 index 0000000..e6a4fc0 --- /dev/null +++ b/it/java8/src/test/java/org/sharedtype/domain/JavaClassIntegrationTest.java @@ -0,0 +1,28 @@ +package org.sharedtype.domain; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sharedtype.domain.TypeDefDeserializer.deserializeTypeDef; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +final class JavaClassIntegrationTest { + private final ClassDef classDef = (ClassDef)deserializeTypeDef("JavaClass.ser"); + + @Test + void parseFields() { + assertThat(classDef.components()).satisfiesExactly( + string -> { + assertThat(string.name()).isEqualTo("string"); + ConcreteTypeInfo typeInfo = (ConcreteTypeInfo)string.type(); + assertThat(typeInfo.qualifiedName()).isEqualTo("java.lang.String"); + }, + size -> { + assertThat(size.name()).isEqualTo("size"); + ConcreteTypeInfo typeInfo = (ConcreteTypeInfo)size.type(); + assertThat(typeInfo.qualifiedName()).isEqualTo("org.sharedtype.it.types.EnumSize"); + } + ); + } +} diff --git a/it/pom.xml b/it/pom.xml index dd8dcea..4df8226 100644 --- a/it/pom.xml +++ b/it/pom.xml @@ -9,8 +9,9 @@ ../pom.xml - sharedtype-it - SharedType Integration Test + sharedtype-it-parent + SharedType Integration Test Parent + pom @@ -31,7 +32,8 @@ ${project.groupId} - sharedtype-internal + sharedtype-it-shared + ${project.version} test diff --git a/it/shared/pom.xml b/it/shared/pom.xml new file mode 100644 index 0000000..d0f5bd7 --- /dev/null +++ b/it/shared/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + org.sharedtype + sharedtype-parent + 0.1-SNAPSHOT + ../../pom.xml + + + sharedtype-it-shared + SharedType Integration Test Shared + + + + ${project.groupId} + sharedtype-internal + + + diff --git a/it/src/test/java/org/sharedtype/domain/TypeDefDeserializer.java b/it/shared/src/main/java/org/sharedtype/domain/TypeDefDeserializer.java similarity index 54% rename from it/src/test/java/org/sharedtype/domain/TypeDefDeserializer.java rename to it/shared/src/main/java/org/sharedtype/domain/TypeDefDeserializer.java index 83dca5c..6304cc8 100644 --- a/it/src/test/java/org/sharedtype/domain/TypeDefDeserializer.java +++ b/it/shared/src/main/java/org/sharedtype/domain/TypeDefDeserializer.java @@ -1,12 +1,15 @@ package org.sharedtype.domain; import java.io.IOException; +import java.io.InputStream; import java.io.ObjectInputStream; +import static java.util.Objects.requireNonNull; + final class TypeDefDeserializer { static TypeDef deserializeTypeDef(String serFilename) { - try (var is = TypeDefDeserializer.class.getClassLoader().getResourceAsStream(serFilename); - var ois = new ObjectInputStream(is)) { + try (InputStream is = TypeDefDeserializer.class.getClassLoader().getResourceAsStream(serFilename); + ObjectInputStream ois = new ObjectInputStream(requireNonNull(is, "Cannot find " + serFilename))) { return (TypeDef) ois.readObject(); } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); diff --git a/mount-tmpfs.sh b/mount-tmpfs.sh index 339e44f..52b3910 100755 --- a/mount-tmpfs.sh +++ b/mount-tmpfs.sh @@ -16,7 +16,9 @@ function mountTmpfs() { echo "tmpfs mounted at $1 of size $2" } -mountTmpfs "$DIR/annotation/target" 128M -mountTmpfs "$DIR/processor/target" 256M -mountTmpfs "$DIR/it/target" 256M +mountTmpfs "$DIR/annotation/target" 32M +mountTmpfs "$DIR/processor/target" 64M +mountTmpfs "$DIR/it/shared/target" 32M +mountTmpfs "$DIR/it/java17/target" 64M +mountTmpfs "$DIR/it/java8/target" 64M mountTmpfs "$MAVEN_REPO_DIR" 64M diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100644 index 95ba6f5..0000000 --- a/mvnw.cmd +++ /dev/null @@ -1,205 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.2.0 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index aaf3914..eb4e420 100644 --- a/pom.xml +++ b/pom.xml @@ -35,12 +35,17 @@ internal processor it + it/shared + it/java8 + it/java17 UTF-8 - 17 - 17 + 8 + 8 + 17 + 17 5.10.2 1.18.34 1.1.1 diff --git a/processor/src/main/java/org/sharedtype/processor/AnnotationProcessorImpl.java b/processor/src/main/java/org/sharedtype/processor/AnnotationProcessorImpl.java index 0ff0495..908c686 100644 --- a/processor/src/main/java/org/sharedtype/processor/AnnotationProcessorImpl.java +++ b/processor/src/main/java/org/sharedtype/processor/AnnotationProcessorImpl.java @@ -16,20 +16,19 @@ import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedOptions; -import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.List; import java.util.Set; import static org.sharedtype.domain.Constants.ANNOTATION_QUALIFIED_NAME; import static org.sharedtype.processor.support.Preconditions.checkArgument; @SupportedAnnotationTypes("org.sharedtype.annotation.SharedType") -@SupportedSourceVersion(SourceVersion.RELEASE_17) @SupportedOptions({"sharedtype.propsFile"}) @AutoService(Processor.class) public final class AnnotationProcessorImpl extends AbstractProcessor { @@ -40,6 +39,11 @@ public final class AnnotationProcessorImpl extends AbstractProcessor { private TypeResolver resolver; private TypeWriter writer; + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); @@ -58,7 +62,7 @@ public boolean process(Set annotations, RoundEnvironment if (annotations.size() > 1) { throw new SharedTypeInternalError(String.format("Only '%s' is expected.", ANNOTATION_QUALIFIED_NAME)); } - var annotation = annotations.iterator().next(); + TypeElement annotation = annotations.iterator().next(); checkArgument(annotation.getQualifiedName().contentEquals(ANNOTATION_QUALIFIED_NAME), "Wrong anno: %s", annotation); doProcess(roundEnv.getElementsAnnotatedWith(annotation)); @@ -67,10 +71,11 @@ public boolean process(Set annotations, RoundEnvironment @VisibleForTesting void doProcess(Set elements) { - var discoveredDefs = new ArrayList(elements.size()); + List discoveredDefs = new ArrayList<>(elements.size()); for (Element element : elements) { - if (element instanceof TypeElement typeElement) { - var typeDef = parser.parse(typeElement); + if (element instanceof TypeElement) { + TypeElement typeElement = (TypeElement) element; + TypeDef typeDef = parser.parse(typeElement); if (typeDef != null) { discoveredDefs.add(typeDef); } else { @@ -80,7 +85,7 @@ void doProcess(Set elements) { throw new UnsupportedOperationException("Unsupported element: " + element); } } - var resolvedDefs = resolver.resolve(discoveredDefs); + List resolvedDefs = resolver.resolve(discoveredDefs); try { writer.write(resolvedDefs); } catch (IOException e) { diff --git a/processor/src/main/java/org/sharedtype/processor/context/Config.java b/processor/src/main/java/org/sharedtype/processor/context/Config.java index 6a3a994..44cd282 100644 --- a/processor/src/main/java/org/sharedtype/processor/context/Config.java +++ b/processor/src/main/java/org/sharedtype/processor/context/Config.java @@ -7,6 +7,7 @@ import javax.lang.model.element.TypeElement; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; import java.util.EnumSet; import java.util.Set; @@ -24,20 +25,19 @@ public final class Config { } @AnnoContainer - private record DummyDefault() {} + private static class DummyDefault {} public Config(TypeElement typeElement) { - var simpleName = typeElement.getSimpleName().toString(); - var annoFromType = typeElement.getAnnotation(SharedType.class); + String simpleName = typeElement.getSimpleName().toString(); + SharedType annoFromType = typeElement.getAnnotation(SharedType.class); this.anno = annoFromType == null ? DummyDefault.class.getAnnotation(AnnoContainer.class).anno() : annoFromType; this.name = anno.name().isEmpty() ? simpleName : anno.name(); this.qualifiedName = typeElement.getQualifiedName().toString(); - this.includedComponentTypes = EnumSet.copyOf(Set.of(anno.includes())); + this.includedComponentTypes = EnumSet.copyOf(Arrays.asList(anno.includes())); } public boolean isComponentIgnored(Element element) { - var ignored = element.getAnnotation(SharedType.Ignore.class); - return ignored != null; + return element.getAnnotation(SharedType.Ignore.class) != null; } public boolean includes(SharedType.ComponentType componentType) { diff --git a/processor/src/main/java/org/sharedtype/processor/context/Context.java b/processor/src/main/java/org/sharedtype/processor/context/Context.java index a03839c..f9593fd 100644 --- a/processor/src/main/java/org/sharedtype/processor/context/Context.java +++ b/processor/src/main/java/org/sharedtype/processor/context/Context.java @@ -36,7 +36,7 @@ public Context(ProcessingEnvironment processingEnv, Props props) { trees = Trees.instance(processingEnv); arraylikeTypes = props.getArraylikeTypeQualifiedNames().stream() .map(qualifiedName -> types.erasure(elements.getTypeElement(qualifiedName).asType())) - .collect(Collectors.toUnmodifiableSet()); + .collect(Collectors.toSet()); } // TODO: optimize by remove varargs diff --git a/processor/src/main/java/org/sharedtype/processor/context/PropsFactory.java b/processor/src/main/java/org/sharedtype/processor/context/PropsFactory.java index c5dd41a..dc739b9 100644 --- a/processor/src/main/java/org/sharedtype/processor/context/PropsFactory.java +++ b/processor/src/main/java/org/sharedtype/processor/context/PropsFactory.java @@ -18,10 +18,10 @@ public final class PropsFactory { private static final String DEFAULT_PROPERTIES_FILE = "sharedtype-default.properties"; public static Props loadProps(@Nullable Path userPropertiesFile) { - var classLoader = PropsFactory.class.getClassLoader(); + ClassLoader classLoader = PropsFactory.class.getClassLoader(); try (InputStream defaultPropsInputstream = classLoader.getResourceAsStream(DEFAULT_PROPERTIES_FILE); InputStream userPropsInputstream = userPropertiesFile == null || Files.notExists(userPropertiesFile) ? null : Files.newInputStream(userPropertiesFile)) { - var properties = new Properties(); + Properties properties = new Properties(); properties.load(defaultPropsInputstream); if (userPropsInputstream != null) { properties.load(userPropsInputstream); @@ -54,10 +54,10 @@ private static Set parseSet(String value) { @SuppressWarnings({"unchecked", "rawtypes"}) private static Set parseSet(String value, Class type) { - var arr = value.split(","); - var set = new LinkedHashSet(arr.length); + String[] arr = value.split(","); + Set set = new LinkedHashSet<>(arr.length); for (String s : arr) { - var trimmed = s.trim(); + String trimmed = s.trim(); if (!trimmed.isEmpty()) { if (type.equals(String.class)) { set.add((T) trimmed); diff --git a/processor/src/main/java/org/sharedtype/processor/context/TypeCache.java b/processor/src/main/java/org/sharedtype/processor/context/TypeCache.java index e71f2b8..bae30d8 100644 --- a/processor/src/main/java/org/sharedtype/processor/context/TypeCache.java +++ b/processor/src/main/java/org/sharedtype/processor/context/TypeCache.java @@ -18,25 +18,25 @@ public final class TypeCache { public void saveTypeDef(String qualifiedName, TypeDef typeDef) { typeByQualifiedName.compute(qualifiedName, (k, v) -> { - var c = v == null ? new Container() : v; + Container c = v == null ? new Container() : v; c.typeDef = typeDef; return c; }); } public void saveTypeInfo(String qualifiedName, TypeInfo typeInfo) { typeByQualifiedName.compute(qualifiedName, (k, v) -> { - var c = v == null ? new Container() : v; + Container c = v == null ? new Container() : v; c.typeInfo = typeInfo; return c; }); } public TypeDef getTypeDef(String qualifiedName) { - var container = typeByQualifiedName.get(qualifiedName); + Container container = typeByQualifiedName.get(qualifiedName); return container == null ? null : container.typeDef; } public TypeInfo getTypeInfo(String qualifiedName) { - var container = typeByQualifiedName.get(qualifiedName); + Container container = typeByQualifiedName.get(qualifiedName); return container == null ? null : container.typeInfo; } diff --git a/processor/src/main/java/org/sharedtype/processor/parser/ClassTypeDefParser.java b/processor/src/main/java/org/sharedtype/processor/parser/ClassTypeDefParser.java index dcb4e0b..3acde01 100644 --- a/processor/src/main/java/org/sharedtype/processor/parser/ClassTypeDefParser.java +++ b/processor/src/main/java/org/sharedtype/processor/parser/ClassTypeDefParser.java @@ -18,8 +18,8 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; -import javax.lang.model.element.RecordComponentElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; final class ClassTypeDefParser implements TypeDefParser { @@ -43,9 +44,9 @@ final class ClassTypeDefParser implements TypeDefParser { @Override public TypeDef parse(TypeElement typeElement) { - var config = new Config(typeElement); + Config config = new Config(typeElement); - var builder = ClassDef.builder().qualifiedName(config.getQualifiedName()).simpleName(config.getName()); + ClassDef.ClassDefBuilder builder = ClassDef.builder().qualifiedName(config.getQualifiedName()).simpleName(config.getName()); builder.typeVariables(parseTypeVariables(typeElement)); builder.components(parseComponents(typeElement, config)); builder.supertypes(parseSupertypes(typeElement)); @@ -54,22 +55,23 @@ public TypeDef parse(TypeElement typeElement) { } private List parseTypeVariables(TypeElement typeElement) { - var typeParameters = typeElement.getTypeParameters(); + List typeParameters = typeElement.getTypeParameters(); return typeParameters.stream() .map(typeParameterElement -> TypeVariableInfo.builder().name(typeParameterElement.getSimpleName().toString()).build()) - .toList(); // TODO: type bounds + .collect(Collectors.toList()); // TODO: type bounds } private List parseSupertypes(TypeElement typeElement) { - var supertypeElems = new ArrayList(); - var superclass = typeElement.getSuperclass(); - if (superclass instanceof DeclaredType declaredType) { + List supertypeElems = new ArrayList<>(); + TypeMirror superclass = typeElement.getSuperclass(); + if (superclass instanceof DeclaredType) { + DeclaredType declaredType = (DeclaredType) superclass; supertypeElems.add((TypeElement) declaredType.asElement()); } - var interfaceTypes = typeElement.getInterfaces(); + List interfaceTypes = typeElement.getInterfaces(); for (TypeMirror interfaceType : interfaceTypes) { - var declaredType = (DeclaredType) interfaceType; + DeclaredType declaredType = (DeclaredType) interfaceType; supertypeElems.add((TypeElement) declaredType.asElement()); } @@ -83,12 +85,12 @@ private List parseSupertypes(TypeElement typeElement) { } private List parseComponents(TypeElement typeElement, Config config) { - var componentElems = resolveComponents(typeElement, config); + List> componentElems = resolveComponents(typeElement, config); - var fields = new ArrayList(componentElems.size()); - for (var tuple : componentElems) { - var element = tuple.a(); - var fieldInfo = FieldComponentInfo.builder() + List fields = new ArrayList<>(componentElems.size()); + for (Tuple tuple : componentElems) { + Element element = tuple.a(); + FieldComponentInfo fieldInfo = FieldComponentInfo.builder() .name(tuple.b()) .modifiers(element.getModifiers()) .optional(element.getAnnotation(ctx.getProps().getOptionalAnno()) != null) @@ -101,46 +103,53 @@ private List parseComponents(TypeElement typeElement, Config @VisibleForTesting List> resolveComponents(TypeElement typeElement, Config config) { - var isRecord = typeElement.getKind() == ElementKind.RECORD; - var enclosedElements = typeElement.getEnclosedElements(); - var recordAccessors = typeElement.getRecordComponents().stream().map(RecordComponentElement::getAccessor).collect(Collectors.toUnmodifiableSet()); + List enclosedElements = typeElement.getEnclosedElements(); + List> res = new ArrayList<>(enclosedElements.size()); + NamesOfTypes uniqueNamesOfTypes = new NamesOfTypes(enclosedElements.size()); + boolean includeAccessors = config.includes(SharedType.ComponentType.ACCESSORS); + boolean includeFields = config.includes(SharedType.ComponentType.FIELDS); - var res = new ArrayList>(enclosedElements.size()); - var namesOfTypes = new NamesOfTypes(enclosedElements.size()); - var includeAccessors = config.includes(SharedType.ComponentType.ACCESSORS); - var includeFields = config.includes(SharedType.ComponentType.FIELDS) && !(isRecord && includeAccessors); + Set instanceFieldNames = enclosedElements.stream() + .filter(e -> e.getKind() == ElementKind.FIELD && !e.getModifiers().contains(Modifier.STATIC)) + .map(e -> e.getSimpleName().toString()) + .collect(Collectors.toSet()); for (Element enclosedElement : enclosedElements) { if (config.isComponentIgnored(enclosedElement)) { continue; } - var type = enclosedElement.asType(); - var name = enclosedElement.getSimpleName().toString(); + TypeMirror type = enclosedElement.asType(); + String name = enclosedElement.getSimpleName().toString(); - if (includeFields && enclosedElement.getKind() == ElementKind.FIELD && enclosedElement instanceof VariableElement variableElem) { - if (namesOfTypes.contains(name, type)) { + if (includeFields && enclosedElement.getKind() == ElementKind.FIELD && enclosedElement instanceof VariableElement) { + VariableElement variableElem = (VariableElement) enclosedElement; + if (uniqueNamesOfTypes.contains(name, type) || !instanceFieldNames.contains(name)) { continue; } res.add(Tuple.of(variableElem, name)); - namesOfTypes.add(name, type); + uniqueNamesOfTypes.add(name, type); } - if (includeAccessors && enclosedElement instanceof ExecutableElement methodElem && isZeroArgNonstaticMethod(methodElem)) { + if (includeAccessors && enclosedElement instanceof ExecutableElement) { + ExecutableElement methodElem = (ExecutableElement) enclosedElement; boolean explicitAccessor = methodElem.getAnnotation(SharedType.Accessor.class) != null; - if (!explicitAccessor && isRecord && !recordAccessors.contains(methodElem)) { + if (!isZeroArgNonstaticMethod(methodElem)) { + if (explicitAccessor) { + ctx.warning("Method '%s' annotated with @SharedType.Accessor is not a zero-arg nonstatic method.", methodElem); + } continue; } - var baseName = getAccessorBaseName(name, isRecord); + String baseName = getAccessorBaseName(name, instanceFieldNames.contains(name), explicitAccessor); if (baseName == null) { continue; } - var returnType = methodElem.getReturnType(); - if (namesOfTypes.contains(baseName, returnType)) { + TypeMirror returnType = methodElem.getReturnType(); + if (uniqueNamesOfTypes.contains(baseName, returnType)) { continue; } res.add(Tuple.of(methodElem, baseName)); - namesOfTypes.add(baseName, returnType); + uniqueNamesOfTypes.add(baseName, returnType); } // TODO: CONSTANTS @@ -157,13 +166,16 @@ private static boolean isZeroArgNonstaticMethod(ExecutableElement componentElem) } @Nullable - private String getAccessorBaseName(String name, boolean isRecord) { + private String getAccessorBaseName(String name, boolean isFluentGetter, boolean isExplicitAccessor) { + if (isFluentGetter) { + return name; + } for (String accessorGetterPrefix : ctx.getProps().getAccessorGetterPrefixes()) { if (name.startsWith(accessorGetterPrefix)) { return Utils.substringAndUncapitalize(name, accessorGetterPrefix.length()); } } - if (isRecord) { + if (isExplicitAccessor) { return name; } return null; @@ -177,7 +189,7 @@ private final class NamesOfTypes { } boolean contains(String name, TypeMirror componentType) { - var type = namesOfTypes.get(name); + TypeMirror type = namesOfTypes.get(name); if (type == null) { return false; } diff --git a/processor/src/main/java/org/sharedtype/processor/parser/CompositeTypeDefParser.java b/processor/src/main/java/org/sharedtype/processor/parser/CompositeTypeDefParser.java index 4310d57..b2f9a80 100644 --- a/processor/src/main/java/org/sharedtype/processor/parser/CompositeTypeDefParser.java +++ b/processor/src/main/java/org/sharedtype/processor/parser/CompositeTypeDefParser.java @@ -12,7 +12,7 @@ @RequiredArgsConstructor final class CompositeTypeDefParser implements TypeDefParser { private final Context ctx; - private final Map parsers; + private final Map parsers; @Override public TypeDef parse(TypeElement typeElement) { @@ -20,17 +20,17 @@ public TypeDef parse(TypeElement typeElement) { return null; } String qualifiedName = typeElement.getQualifiedName().toString(); - var cachedDef = ctx.getTypeCache().getTypeDef(qualifiedName); + TypeDef cachedDef = ctx.getTypeCache().getTypeDef(qualifiedName); if (cachedDef != null) { return cachedDef; } ctx.info("Processing: " + typeElement.getQualifiedName()); - var parser = parsers.get(typeElement.getKind()); + TypeDefParser parser = parsers.get(typeElement.getKind().name()); if (parser == null) { throw new SharedTypeInternalError(String.format("Unsupported element: %s, kind=%s", typeElement, typeElement.getKind())); } - var typeDef = parser.parse(typeElement); + TypeDef typeDef = parser.parse(typeElement); ctx.getTypeCache().saveTypeDef(qualifiedName, typeDef); return typeDef; } diff --git a/processor/src/main/java/org/sharedtype/processor/parser/EnumTypeDefParser.java b/processor/src/main/java/org/sharedtype/processor/parser/EnumTypeDefParser.java index 127b55e..aca1a4c 100644 --- a/processor/src/main/java/org/sharedtype/processor/parser/EnumTypeDefParser.java +++ b/processor/src/main/java/org/sharedtype/processor/parser/EnumTypeDefParser.java @@ -1,13 +1,16 @@ package org.sharedtype.processor.parser; +import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.LiteralTree; import com.sun.source.tree.NewClassTree; +import com.sun.source.tree.Tree; import com.sun.source.tree.VariableTree; import lombok.RequiredArgsConstructor; import org.sharedtype.annotation.SharedType; import org.sharedtype.domain.EnumDef; import org.sharedtype.domain.EnumValueInfo; import org.sharedtype.domain.TypeDef; +import org.sharedtype.domain.TypeInfo; import org.sharedtype.processor.context.Config; import org.sharedtype.processor.context.Context; import org.sharedtype.processor.parser.type.TypeInfoParser; @@ -31,11 +34,11 @@ final class EnumTypeDefParser implements TypeDefParser { @Override public TypeDef parse(TypeElement typeElement) { - var config = new Config(typeElement); - var enclosedElements = typeElement.getEnclosedElements(); + Config config = new Config(typeElement); + List enclosedElements = typeElement.getEnclosedElements(); List enumConstantElems = new ArrayList<>(enclosedElements.size()); - var enumValueMarker = new EnumValueMarker(ctx, config); + EnumValueMarker enumValueMarker = new EnumValueMarker(ctx, config); for (Element enclosedElement : enclosedElements) { if (enclosedElement.getKind() == ElementKind.ENUM_CONSTANT) { enumConstantElems.add((VariableElement) enclosedElement); @@ -65,18 +68,23 @@ private static List useEnumConstantNames(List en private List parseEnumConstants(List enumConstants, EnumValueMarker enumValueMarker) { List res = new ArrayList<>(enumConstants.size()); - var valueTypeInfo = typeInfoParser.parse(enumValueMarker.enumValueVariableElem.asType()); - var ctorArgIdx = enumValueMarker.matchAndGetConstructorArgIdx(); + TypeInfo valueTypeInfo = typeInfoParser.parse(enumValueMarker.enumValueVariableElem.asType()); + int ctorArgIdx = enumValueMarker.matchAndGetConstructorArgIdx(); if (ctorArgIdx < 0) { return Collections.emptyList(); } for (VariableElement enumConstant : enumConstants) { - var tree = ctx.getTrees().getTree(enumConstant); - if (tree instanceof VariableTree variableTree) { - var value = resolveValue(variableTree, ctorArgIdx); + Tree tree = ctx.getTrees().getTree(enumConstant); + if (tree instanceof VariableTree) { + VariableTree variableTree = (VariableTree) tree; + Object value = resolveValue(variableTree, ctorArgIdx); if (value != null) { res.add(new EnumValueInfo(valueTypeInfo, value)); } + } else if (tree == null) { + ctx.error("Literal value cannot be parsed from enum constant: %s, because source tree from the element is null." + + " This could mean at the time of the annotation processing, the source tree was not available." + + " Is this class from a dependency jar/compiled class file? Please refer to the documentation for more information.", enumConstant); } else { throw new SharedTypeInternalError(String.format("Unsupported tree, kind: %s, tree: %s, element: %s", tree.getKind(), tree, enumConstant)); } @@ -85,11 +93,13 @@ private List parseEnumConstants(List enumConstan } private Object resolveValue(VariableTree tree, int ctorArgIdx) { - var init = tree.getInitializer(); - if (init instanceof NewClassTree newClassTree) { + ExpressionTree init = tree.getInitializer(); + if (init instanceof NewClassTree) { + NewClassTree newClassTree = (NewClassTree) init; try { - var argTree = newClassTree.getArguments().get(ctorArgIdx); - if (argTree instanceof LiteralTree argLiteralTree) { + ExpressionTree argTree = newClassTree.getArguments().get(ctorArgIdx); + if (argTree instanceof LiteralTree) { + LiteralTree argLiteralTree = (LiteralTree) argTree; return argLiteralTree.getValue(); } else { ctx.error("Unsupported argument: %s in %s, argIndex: %s. Only literals are supported as enum value." diff --git a/processor/src/main/java/org/sharedtype/processor/parser/TypeDefParser.java b/processor/src/main/java/org/sharedtype/processor/parser/TypeDefParser.java index 76b2e4c..b317267 100644 --- a/processor/src/main/java/org/sharedtype/processor/parser/TypeDefParser.java +++ b/processor/src/main/java/org/sharedtype/processor/parser/TypeDefParser.java @@ -7,6 +7,7 @@ import javax.annotation.Nullable; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; +import java.util.HashMap; import java.util.Map; public interface TypeDefParser { @@ -18,11 +19,11 @@ public interface TypeDefParser { static TypeDefParser create(Context ctx) { TypeInfoParser typeInfoParser = TypeInfoParser.create(ctx); - return new CompositeTypeDefParser(ctx, Map.of( - ElementKind.CLASS, new ClassTypeDefParser(ctx, typeInfoParser), - ElementKind.INTERFACE, new ClassTypeDefParser(ctx, typeInfoParser), - ElementKind.ENUM, new EnumTypeDefParser(ctx, typeInfoParser), - ElementKind. RECORD, new ClassTypeDefParser(ctx, typeInfoParser) - )); + Map parsers = new HashMap<>(4); + parsers.put(ElementKind.CLASS.name(), new ClassTypeDefParser(ctx, typeInfoParser)); + parsers.put(ElementKind.INTERFACE.name(), new ClassTypeDefParser(ctx, typeInfoParser)); + parsers.put(ElementKind.ENUM.name(), new EnumTypeDefParser(ctx, typeInfoParser)); + parsers.put("RECORD", new ClassTypeDefParser(ctx, typeInfoParser)); + return new CompositeTypeDefParser(ctx, parsers); } } diff --git a/processor/src/main/java/org/sharedtype/processor/parser/type/TypeInfoParserImpl.java b/processor/src/main/java/org/sharedtype/processor/parser/type/TypeInfoParserImpl.java index 2ef4487..082a74a 100644 --- a/processor/src/main/java/org/sharedtype/processor/parser/type/TypeInfoParserImpl.java +++ b/processor/src/main/java/org/sharedtype/processor/parser/type/TypeInfoParserImpl.java @@ -16,6 +16,8 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; import static org.sharedtype.domain.Constants.PRIMITIVES; import static org.sharedtype.processor.support.Preconditions.checkArgument; @@ -26,7 +28,7 @@ final class TypeInfoParserImpl implements TypeInfoParser { @Override public TypeInfo parse(TypeMirror typeMirror) { - var typeKind = typeMirror.getKind(); + TypeKind typeKind = typeMirror.getKind(); // TODO: use enumMap if (typeKind.isPrimitive()) { @@ -44,10 +46,10 @@ public TypeInfo parse(TypeMirror typeMirror) { } private TypeInfo parseDeclared(DeclaredType declaredType) { - var typeElement = (TypeElement) declaredType.asElement(); - var qualifiedName = typeElement.getQualifiedName().toString(); - var simpleName = typeElement.getSimpleName().toString(); - var typeArgs = declaredType.getTypeArguments(); + TypeElement typeElement = (TypeElement) declaredType.asElement(); + String qualifiedName = typeElement.getQualifiedName().toString(); + String simpleName = typeElement.getSimpleName().toString(); + List typeArgs = declaredType.getTypeArguments(); int arrayStack = 0; boolean isTypeVar = false; @@ -56,13 +58,15 @@ private TypeInfo parseDeclared(DeclaredType declaredType) { checkArgument(typeArgs.size() == 1, "Array type must have exactly one type argument, but got: %s, type: %s", typeArgs.size(), currentType); arrayStack++; currentType = typeArgs.get(0); - if (currentType instanceof DeclaredType argDeclaredType) { - var element = (TypeElement) argDeclaredType.asElement(); + if (currentType instanceof DeclaredType) { + DeclaredType argDeclaredType = (DeclaredType) currentType; + TypeElement element = (TypeElement) argDeclaredType.asElement(); qualifiedName = element.getQualifiedName().toString(); simpleName = element.getSimpleName().toString(); typeArgs = argDeclaredType.getTypeArguments(); - } else if (currentType instanceof TypeVariable argTypeVariable) { - var typeVarInfo = parseTypeVariable(argTypeVariable); + } else if (currentType instanceof TypeVariable) { + TypeVariable argTypeVariable = (TypeVariable) currentType; + TypeVariableInfo typeVarInfo = parseTypeVariable(argTypeVariable); qualifiedName = typeVarInfo.getName(); simpleName = typeVarInfo.getName(); typeArgs = Collections.emptyList(); @@ -72,8 +76,8 @@ private TypeInfo parseDeclared(DeclaredType declaredType) { TypeInfo typeInfo = ctx.getTypeCache().getTypeInfo(qualifiedName); if (typeInfo == null) { - var resolved = isTypeVar || ctx.getTypeCache().contains(qualifiedName); - var parsedTypeArgs = typeArgs.stream().map(this::parse).toList(); + boolean resolved = isTypeVar || ctx.getTypeCache().contains(qualifiedName); + List parsedTypeArgs = typeArgs.stream().map(this::parse).collect(Collectors.toList()); typeInfo = ConcreteTypeInfo.builder() .qualifiedName(qualifiedName) .simpleName(simpleName) diff --git a/processor/src/main/java/org/sharedtype/processor/resolver/LoopTypeResolver.java b/processor/src/main/java/org/sharedtype/processor/resolver/LoopTypeResolver.java index 21b7298..4bcd30b 100644 --- a/processor/src/main/java/org/sharedtype/processor/resolver/LoopTypeResolver.java +++ b/processor/src/main/java/org/sharedtype/processor/resolver/LoopTypeResolver.java @@ -15,6 +15,7 @@ import org.sharedtype.processor.support.annotation.SideEffect; import org.sharedtype.processor.support.exception.SharedTypeInternalError; +import javax.lang.model.element.TypeElement; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; @@ -28,14 +29,14 @@ final class LoopTypeResolver implements TypeResolver { @Override public List resolve(List typeDefs) { - var n = typeDefs.size() * DEPENDENCY_COUNT_EXPANSION_FACTOR; - var resolvedDefs = new ArrayList(n); - var processingDefStack = new ArrayDeque(n); // TODO: pass metadata from ctx to better size these buffers - var processingInfoStack = new ArrayDeque(n); + int n = typeDefs.size() * DEPENDENCY_COUNT_EXPANSION_FACTOR; + List resolvedDefs = new ArrayList<>(n); + Deque processingDefStack = new ArrayDeque<>(n); // TODO: pass metadata from ctx to better size these buffers + Deque processingInfoStack = new ArrayDeque<>(n); processingDefStack.addAll(typeDefs); while (!processingDefStack.isEmpty()) { - var typeDef = processingDefStack.pop(); + TypeDef typeDef = processingDefStack.pop(); if (typeDef.resolved()) { resolvedDefs.add(typeDef); continue; @@ -43,7 +44,8 @@ public List resolve(List typeDefs) { processingDefStack.push(typeDef); - if (typeDef instanceof ClassDef classDef) { + if (typeDef instanceof ClassDef) { + ClassDef classDef = (ClassDef) typeDef; for (FieldComponentInfo fieldComponentInfo : classDef.components()) { if (!fieldComponentInfo.resolved()) { processingInfoStack.push(fieldComponentInfo.type()); @@ -59,7 +61,8 @@ public List resolve(List typeDefs) { processingInfoStack.push(typeVariableInfo); } } - } else if (typeDef instanceof EnumDef enumDef) { + } else if (typeDef instanceof EnumDef) { + EnumDef enumDef = (EnumDef) typeDef; for (EnumValueInfo component : enumDef.components()) { if (!component.resolved()) { processingInfoStack.push(component.type()); @@ -79,10 +82,11 @@ public List resolve(List typeDefs) { private void resolveTypeInfo(Deque processingDefStack, Deque processingInfoStack) { while (!processingInfoStack.isEmpty()) { TypeInfo typeInfo = processingInfoStack.pop(); - if (typeInfo instanceof ConcreteTypeInfo concreteTypeInfo) { + if (typeInfo instanceof ConcreteTypeInfo) { + ConcreteTypeInfo concreteTypeInfo = (ConcreteTypeInfo) typeInfo; if (!concreteTypeInfo.shallowResolved()) { - var typeElement = ctx.getProcessingEnv().getElementUtils().getTypeElement(concreteTypeInfo.qualifiedName()); - var parsed = typeDefParser.parse(typeElement); + TypeElement typeElement = ctx.getProcessingEnv().getElementUtils().getTypeElement(concreteTypeInfo.qualifiedName()); + TypeDef parsed = typeDefParser.parse(typeElement); if (parsed != null) { concreteTypeInfo.markShallowResolved(); processingDefStack.push(parsed); @@ -93,11 +97,13 @@ private void resolveTypeInfo(Deque processingDefStack, Deque processingInfoStack.push(typeArg); } } - } else if (typeInfo instanceof ArrayTypeInfo arrayTypeInfo) { + } else if (typeInfo instanceof ArrayTypeInfo) { + ArrayTypeInfo arrayTypeInfo = (ArrayTypeInfo) typeInfo; if (!arrayTypeInfo.resolved()) { processingInfoStack.push(arrayTypeInfo.component()); } - } else if (typeInfo instanceof TypeVariableInfo typeVariableInfo) { + } else if (typeInfo instanceof TypeVariableInfo) { + TypeVariableInfo typeVariableInfo = (TypeVariableInfo) typeInfo; throw new UnsupportedOperationException("Type variable not supported yet: " + typeVariableInfo); } else { throw new SharedTypeInternalError( diff --git a/processor/src/main/java/org/sharedtype/processor/support/utils/Tuple.java b/processor/src/main/java/org/sharedtype/processor/support/utils/Tuple.java index aac60cb..5a4ec6c 100644 --- a/processor/src/main/java/org/sharedtype/processor/support/utils/Tuple.java +++ b/processor/src/main/java/org/sharedtype/processor/support/utils/Tuple.java @@ -1,10 +1,24 @@ package org.sharedtype.processor.support.utils; -public record Tuple(A a, B b) { +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public final class Tuple { + private final A a; + private final B b; + public static Tuple of(A a, B b) { return new Tuple<>(a, b); } + public A a() { + return a; + } + + public B b() { + return b; + } + @Override public String toString() { return String.format("(%s, %s)", a, b); diff --git a/processor/src/main/java/org/sharedtype/processor/support/utils/Utils.java b/processor/src/main/java/org/sharedtype/processor/support/utils/Utils.java index fba19fe..2bf16b8 100644 --- a/processor/src/main/java/org/sharedtype/processor/support/utils/Utils.java +++ b/processor/src/main/java/org/sharedtype/processor/support/utils/Utils.java @@ -8,4 +8,5 @@ private Utils() { public static String substringAndUncapitalize(String str, int beginIndex) { return Character.toLowerCase(str.charAt(beginIndex)) + str.substring(beginIndex + 1); // TODO: see if can optimize } + } diff --git a/processor/src/main/java/org/sharedtype/processor/writer/JavaSerializationFileWriter.java b/processor/src/main/java/org/sharedtype/processor/writer/JavaSerializationFileWriter.java index 398e665..6052d34 100644 --- a/processor/src/main/java/org/sharedtype/processor/writer/JavaSerializationFileWriter.java +++ b/processor/src/main/java/org/sharedtype/processor/writer/JavaSerializationFileWriter.java @@ -4,9 +4,11 @@ import org.sharedtype.processor.context.Context; import javax.annotation.processing.Filer; +import javax.tools.FileObject; import javax.tools.StandardLocation; import java.io.IOException; import java.io.ObjectOutputStream; +import java.io.OutputStream; import java.util.List; /** @@ -23,9 +25,9 @@ final class JavaSerializationFileWriter implements TypeWriter { public void write(List typeDefs) { try { for (TypeDef typeDef : typeDefs) { - var file = filer.createResource(StandardLocation.CLASS_OUTPUT, "", typeDef.simpleName() + ".ser"); - try(var outputStream = file.openOutputStream(); - var oos = new ObjectOutputStream(outputStream)) { + FileObject file = filer.createResource(StandardLocation.CLASS_OUTPUT, "", typeDef.simpleName() + ".ser"); + try(OutputStream outputStream = file.openOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(outputStream)) { oos.writeObject(typeDef); } } diff --git a/processor/src/main/java/org/sharedtype/processor/writer/TypescriptTypeFileWriter.java b/processor/src/main/java/org/sharedtype/processor/writer/TypescriptTypeFileWriter.java index 5571aac..2a2c7e3 100644 --- a/processor/src/main/java/org/sharedtype/processor/writer/TypescriptTypeFileWriter.java +++ b/processor/src/main/java/org/sharedtype/processor/writer/TypescriptTypeFileWriter.java @@ -1,5 +1,7 @@ package org.sharedtype.processor.writer; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import org.sharedtype.domain.ArrayTypeInfo; import org.sharedtype.domain.ClassDef; import org.sharedtype.domain.ConcreteTypeInfo; @@ -18,36 +20,45 @@ import org.sharedtype.processor.writer.render.TemplateRenderer; import javax.lang.model.util.Elements; +import javax.tools.FileObject; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.Writer; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; final class TypescriptTypeFileWriter implements TypeWriter { - private static final Map PREDEFINED_TYPE_NAME_MAPPINGS = Map.ofEntries( - Map.entry(Constants.BOOLEAN_TYPE_INFO, "boolean"), - Map.entry(Constants.BYTE_TYPE_INFO, "number"), - Map.entry(Constants.CHAR_TYPE_INFO, "string"), - Map.entry(Constants.DOUBLE_TYPE_INFO, "number"), - Map.entry(Constants.FLOAT_TYPE_INFO, "number"), - Map.entry(Constants.INT_TYPE_INFO, "number"), - Map.entry(Constants.LONG_TYPE_INFO, "number"), - Map.entry(Constants.SHORT_TYPE_INFO, "number"), - - Map.entry(Constants.BOXED_BOOLEAN_TYPE_INFO, "boolean"), - Map.entry(Constants.BOXED_BYTE_TYPE_INFO, "number"), - Map.entry(Constants.BOXED_CHAR_TYPE_INFO, "string"), - Map.entry(Constants.BOXED_DOUBLE_TYPE_INFO, "number"), - Map.entry(Constants.BOXED_FLOAT_TYPE_INFO, "number"), - Map.entry(Constants.BOXED_INT_TYPE_INFO, "number"), - Map.entry(Constants.BOXED_LONG_TYPE_INFO, "number"), - Map.entry(Constants.BOXED_SHORT_TYPE_INFO, "number"), - - Map.entry(Constants.STRING_TYPE_INFO, "string"), - Map.entry(Constants.VOID_TYPE_INFO, "never") - ); + private static final Map PREDEFINED_TYPE_NAME_MAPPINGS; + static { + Map tempMap = new HashMap<>(20); + tempMap.put(Constants.BOOLEAN_TYPE_INFO, "boolean"); + tempMap.put(Constants.BYTE_TYPE_INFO, "number"); + tempMap.put(Constants.CHAR_TYPE_INFO, "string"); + tempMap.put(Constants.DOUBLE_TYPE_INFO, "number"); + tempMap.put(Constants.FLOAT_TYPE_INFO, "number"); + tempMap.put(Constants.INT_TYPE_INFO, "number"); + tempMap.put(Constants.LONG_TYPE_INFO, "number"); + tempMap.put(Constants.SHORT_TYPE_INFO, "number"); + + tempMap.put(Constants.BOXED_BOOLEAN_TYPE_INFO, "boolean"); + tempMap.put(Constants.BOXED_BYTE_TYPE_INFO, "number"); + tempMap.put(Constants.BOXED_CHAR_TYPE_INFO, "string"); + tempMap.put(Constants.BOXED_DOUBLE_TYPE_INFO, "number"); + tempMap.put(Constants.BOXED_FLOAT_TYPE_INFO, "number"); + tempMap.put(Constants.BOXED_INT_TYPE_INFO, "number"); + tempMap.put(Constants.BOXED_LONG_TYPE_INFO, "number"); + tempMap.put(Constants.BOXED_SHORT_TYPE_INFO, "number"); + + tempMap.put(Constants.STRING_TYPE_INFO, "string"); + tempMap.put(Constants.VOID_TYPE_INFO, "never"); + + PREDEFINED_TYPE_NAME_MAPPINGS = Collections.unmodifiableMap(tempMap); + } private final Context ctx; private final Elements elements; @@ -73,7 +84,8 @@ final class TypescriptTypeFileWriter implements TypeWriter { public void write(List typeDefs) throws IOException { List> data = new ArrayList<>(typeDefs.size()); for (TypeDef typeDef : typeDefs) { - if (typeDef instanceof EnumDef enumDef) { + if (typeDef instanceof EnumDef) { + EnumDef enumDef = (EnumDef) typeDef; List values = new ArrayList<>(enumDef.components().size()); for (EnumValueInfo component : enumDef.components()) { try { @@ -85,20 +97,21 @@ public void write(List typeDefs) throws IOException { } } data.add(Tuple.of(Template.TEMPLATE_ENUM_UNION, new EnumUnionExpr(enumDef.simpleName(), values))); - } else if (typeDef instanceof ClassDef classDef) { - var value = new InterfaceExpr( + } else if (typeDef instanceof ClassDef) { + ClassDef classDef = (ClassDef) typeDef; + InterfaceExpr value = new InterfaceExpr( classDef.simpleName(), - classDef.typeVariables().stream().map(this::toTypeExpr).toList(), - classDef.supertypes().stream().map(this::toTypeExpr).toList(), - classDef.components().stream().map(this::toPropertyExpr).toList() + classDef.typeVariables().stream().map(this::toTypeExpr).collect(Collectors.toList()), + classDef.supertypes().stream().map(this::toTypeExpr).collect(Collectors.toList()), + classDef.components().stream().map(this::toPropertyExpr).collect(Collectors.toList()) ); data.add(Tuple.of(Template.TEMPLATE_INTERFACE, value)); } } - var file = ctx.createSourceOutput(ctx.getProps().getTypescript().getOutputFileName()); - try (var outputStream = file.openOutputStream(); - var writer = new OutputStreamWriter(outputStream)) { + FileObject file = ctx.createSourceOutput(ctx.getProps().getTypescript().getOutputFileName()); + try (OutputStream outputStream = file.openOutputStream(); + Writer writer = new OutputStreamWriter(outputStream)) { renderer.render(writer, data); } } @@ -115,13 +128,14 @@ private PropertyExpr toPropertyExpr(FieldComponentInfo field) { } private String toTypeExpr(TypeInfo typeInfo) { - var typeExprBuilder = new StringBuilder(); + StringBuilder typeExprBuilder = new StringBuilder(); buildTypeExprRecursively(typeInfo, typeExprBuilder); return typeExprBuilder.toString(); } private void buildTypeExprRecursively(TypeInfo typeInfo, @SideEffect StringBuilder nameBuilder) { // TODO: abstract up - if (typeInfo instanceof ConcreteTypeInfo concreteTypeInfo) { + if (typeInfo instanceof ConcreteTypeInfo) { + ConcreteTypeInfo concreteTypeInfo = (ConcreteTypeInfo) typeInfo; nameBuilder.append(typeNameMappings.getOrDefault(concreteTypeInfo, concreteTypeInfo.simpleName())); if (!concreteTypeInfo.typeArgs().isEmpty()) { nameBuilder.append("<"); @@ -132,21 +146,24 @@ private void buildTypeExprRecursively(TypeInfo typeInfo, @SideEffect StringBuild nameBuilder.setLength(nameBuilder.length() - 2); nameBuilder.append(">"); } - } else if (typeInfo instanceof TypeVariableInfo typeVariableInfo) { + } else if (typeInfo instanceof TypeVariableInfo) { + TypeVariableInfo typeVariableInfo = (TypeVariableInfo) typeInfo; nameBuilder.append(typeVariableInfo.getName()); - } else if (typeInfo instanceof ArrayTypeInfo arrayTypeInfo) { + } else if (typeInfo instanceof ArrayTypeInfo) { + ArrayTypeInfo arrayTypeInfo = (ArrayTypeInfo) typeInfo; buildTypeExprRecursively(arrayTypeInfo.component(), nameBuilder); nameBuilder.append("[]"); } } + @RequiredArgsConstructor @SuppressWarnings("unused") - record InterfaceExpr( - String name, - List typeParameters, - List supertypes, - List properties - ) { + static final class InterfaceExpr{ + final String name; + final List typeParameters; + final List supertypes; + final List properties; + String typeParametersExpr() { if (typeParameters.isEmpty()) { return null; @@ -162,20 +179,21 @@ String supertypesExpr() { } } - record PropertyExpr( - String name, - String type, - char propDelimiter, - boolean optional, - boolean unionNull, - boolean unionUndefined - ) { + @RequiredArgsConstructor + static final class PropertyExpr{ + final String name; + final String type; + final char propDelimiter; + final boolean optional; + final boolean unionNull; + final boolean unionUndefined; } - record EnumUnionExpr( - String name, - List values - ) { + @RequiredArgsConstructor + static final class EnumUnionExpr { + final String name; + final List values; + @SuppressWarnings("unused") String valuesExpr() { return String.join(" | ", values); diff --git a/processor/src/main/java/org/sharedtype/processor/writer/render/MustacheTemplateRenderer.java b/processor/src/main/java/org/sharedtype/processor/writer/render/MustacheTemplateRenderer.java index 775bbc1..9ec993d 100644 --- a/processor/src/main/java/org/sharedtype/processor/writer/render/MustacheTemplateRenderer.java +++ b/processor/src/main/java/org/sharedtype/processor/writer/render/MustacheTemplateRenderer.java @@ -26,9 +26,9 @@ public void loadTemplates(Template... templates) { @Override public void render(Writer writer, List> data) { for (Tuple tuple : data) { - var template = tuple.a(); - var values = tuple.b(); - var mustache = compiledTemplates.get(template); + Template template = tuple.a(); + Object values = tuple.b(); + Mustache mustache = compiledTemplates.get(template); if (mustache == null) { throw new SharedTypeInternalError(String.format("Template not found: '%s'", template)); } diff --git a/processor/src/test/java/org/sharedtype/processor/context/AbstractElementMock.java b/processor/src/test/java/org/sharedtype/processor/context/AbstractElementMock.java index 2477d25..82f8269 100644 --- a/processor/src/test/java/org/sharedtype/processor/context/AbstractElementMock.java +++ b/processor/src/test/java/org/sharedtype/processor/context/AbstractElementMock.java @@ -10,6 +10,7 @@ import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.List; import static org.assertj.core.api.Fail.fail; import static org.mockito.Mockito.mock; @@ -35,8 +36,9 @@ public final M withElementKind(ElementKind elementKind) { } public final M withTypeArguments(TypeMirror... typeArgsArr) { - var typeArgs = Arrays.asList(typeArgsArr); - if (type instanceof DeclaredType declaredType) { + List typeArgs = Arrays.asList(typeArgsArr); + if (type instanceof DeclaredType) { + DeclaredType declaredType = (DeclaredType) type; when(declaredType.getTypeArguments()).thenAnswer(invoc -> typeArgs); } else { fail("Not a DeclaredType: " + type); @@ -58,13 +60,13 @@ public final T type() { } static void setQualifiedName(TypeElement typeElement, String qualifiedName) { - var typeElementName = mock(Name.class); + Name typeElementName = mock(Name.class); when(typeElement.getQualifiedName()).thenReturn(typeElementName); when(typeElementName.toString()).thenReturn(qualifiedName); } static void setSimpleName(Element element, String simpleName) { - var elementName = mock(Name.class); + Name elementName = mock(Name.class); when(element.getSimpleName()).thenReturn(elementName); when(elementName.toString()).thenReturn(simpleName); } diff --git a/processor/src/test/java/org/sharedtype/processor/context/IdentifierTreeMock.java b/processor/src/test/java/org/sharedtype/processor/context/IdentifierTreeMock.java index 4ee0030..0e62952 100644 --- a/processor/src/test/java/org/sharedtype/processor/context/IdentifierTreeMock.java +++ b/processor/src/test/java/org/sharedtype/processor/context/IdentifierTreeMock.java @@ -10,7 +10,7 @@ public final class IdentifierTreeMock extends ExpressionTreeMock { IdentifierTreeMock(String name, Context ctx) { super(mock(IdentifierTree.class, String.format("Tree(%s)", name)), ctx); - var elementName = mock(Name.class); + Name elementName = mock(Name.class); when(tree.getName()).thenReturn(elementName); when(elementName.toString()).thenReturn(name); } diff --git a/processor/src/test/java/org/sharedtype/processor/context/NewClassTreeMock.java b/processor/src/test/java/org/sharedtype/processor/context/NewClassTreeMock.java index 9a2e59a..ca27dde 100644 --- a/processor/src/test/java/org/sharedtype/processor/context/NewClassTreeMock.java +++ b/processor/src/test/java/org/sharedtype/processor/context/NewClassTreeMock.java @@ -4,6 +4,7 @@ import com.sun.source.tree.NewClassTree; import java.util.Arrays; +import java.util.stream.Collectors; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -15,7 +16,7 @@ public final class NewClassTreeMock extends AbstractTreeMock> NewClassTreeMock withArguments(ExpressionTreeMock... arguments) { - when(tree.getArguments()).then(invoc -> Arrays.stream(arguments).map(arg -> arg.tree).toList()); + when(tree.getArguments()).then(invoc -> Arrays.stream(arguments).map(arg -> arg.tree).collect(Collectors.toList())); return this; } } diff --git a/processor/src/test/java/org/sharedtype/processor/context/PropsFactoryTest.java b/processor/src/test/java/org/sharedtype/processor/context/PropsFactoryTest.java index bc67709..541844b 100644 --- a/processor/src/test/java/org/sharedtype/processor/context/PropsFactoryTest.java +++ b/processor/src/test/java/org/sharedtype/processor/context/PropsFactoryTest.java @@ -14,7 +14,7 @@ final class PropsFactoryTest { @Test void loadUserProps() { - var props = PropsFactory.loadProps(resolveResource("test-sharedtype-user.properties")); + Props props = PropsFactory.loadProps(resolveResource("test-sharedtype-user.properties")); assertThat(props.getTargets()).containsExactly(OutputTarget.TYPESCRIPT, OutputTarget.CONSOLE); assertThat(props.getOptionalAnno()).isEqualTo(Override.class); assertThat(props.getTypescript().getJavaObjectMapType()).isEqualTo("unknown"); @@ -22,7 +22,7 @@ void loadUserProps() { @Test void loadDefaultProps() { - var props = PropsFactory.loadProps(Paths.get("not-exist")); + Props props = PropsFactory.loadProps(Paths.get("not-exist")); assertThat(props.getTargets()).containsExactly(OutputTarget.TYPESCRIPT); assertThat(props.getOptionalAnno()).isEqualTo(Nullable.class); assertThat(props.getAccessorGetterPrefixes()).containsExactly("get", "is"); @@ -35,7 +35,7 @@ void loadDefaultProps() { "java.lang.Record" ); - var typescriptProps = props.getTypescript(); + Props.Typescript typescriptProps = props.getTypescript(); assertThat(typescriptProps.getOutputFileName()).isEqualTo("types.d.ts"); assertThat(typescriptProps.getInterfacePropertyDelimiter()).isEqualTo(';'); assertThat(typescriptProps.getJavaObjectMapType()).isEqualTo("any"); diff --git a/processor/src/test/java/org/sharedtype/processor/parser/ClassTypeDefParserForRecordTest.java b/processor/src/test/java/org/sharedtype/processor/parser/ClassTypeDefParserForRecordTest.java index 402a982..a71a8af 100644 --- a/processor/src/test/java/org/sharedtype/processor/parser/ClassTypeDefParserForRecordTest.java +++ b/processor/src/test/java/org/sharedtype/processor/parser/ClassTypeDefParserForRecordTest.java @@ -65,12 +65,12 @@ void setUp() { } @Test - void ignoreFieldsWhenAccessor() { + void resolveFieldsAndAccessors() { var components = parser.resolveComponents(recordElement, config); assertThat(components).hasSize(2); var component1 = components.get(0); - assertThat(component1.a()).isEqualTo(method1.element()); + assertThat(component1.a()).isEqualTo(field1.element()); assertThat(component1.b()).isEqualTo("value"); var component2 = components.get(1); @@ -81,27 +81,27 @@ void ignoreFieldsWhenAccessor() { } @Test - void resolveField() { + void resolveFields() { when(config.includes(SharedType.ComponentType.ACCESSORS)).thenReturn(false); var components = parser.resolveComponents(recordElement, config); assertThat(components).satisfiesExactly(component -> { - assertThat(component.a()).isEqualTo(field1.element()); - assertThat(component.b()).isEqualTo("value"); + assertThat(component.a()).describedAs("element").isEqualTo(field1.element()); + assertThat(component.b()).describedAs("name").isEqualTo("value"); }); } @Test - void resolveAccessor() { + void resolveAccessors() { when(config.includes(SharedType.ComponentType.FIELDS)).thenReturn(false); var components = parser.resolveComponents(recordElement, config); assertThat(components).satisfiesExactly( component1 -> { - assertThat(component1.a()).isEqualTo(method1.element()); - assertThat(component1.b()).isEqualTo("value"); + assertThat(component1.a()).describedAs("element").isEqualTo(method1get.element()); + assertThat(component1.b()).describedAs("name").isEqualTo("value"); }, component2 -> { - assertThat(component2.a()).isEqualTo(method2.element()); - assertThat(component2.b()).isEqualTo("value2"); + assertThat(component2.a()).describedAs("element").isEqualTo(method2.element()); + assertThat(component2.b()).describedAs("name").isEqualTo("value2"); } ); } diff --git a/processor/src/test/java/org/sharedtype/processor/parser/CompositeTypeDefParserTest.java b/processor/src/test/java/org/sharedtype/processor/parser/CompositeTypeDefParserTest.java index 3fd564f..ad24dcf 100644 --- a/processor/src/test/java/org/sharedtype/processor/parser/CompositeTypeDefParserTest.java +++ b/processor/src/test/java/org/sharedtype/processor/parser/CompositeTypeDefParserTest.java @@ -38,8 +38,8 @@ void setUp() { parser = new CompositeTypeDefParser( ctxMocks.getContext(), Map.of( - ElementKind.RECORD, delegate1, - ElementKind.ENUM, delegate2 + ElementKind.RECORD.name(), delegate1, + ElementKind.ENUM.name(), delegate2 )); when(ctxMocks.getTypeCache().getTypeDef("com.github.cuzfrog.Abc")).thenReturn(null); } diff --git a/processor/src/test/java/org/sharedtype/processor/parser/EnumTypeDefParserTest.java b/processor/src/test/java/org/sharedtype/processor/parser/EnumTypeDefParserTest.java index db845eb..a685ffe 100644 --- a/processor/src/test/java/org/sharedtype/processor/parser/EnumTypeDefParserTest.java +++ b/processor/src/test/java/org/sharedtype/processor/parser/EnumTypeDefParserTest.java @@ -33,7 +33,7 @@ void simpleEnum() { ctxMocks.declaredTypeVariable("Value2", enumType.type()).withElementKind(ElementKind.ENUM_CONSTANT).element() ); - var typeDef = (EnumDef)parser.parse(enumType.element()); + EnumDef typeDef = (EnumDef)parser.parse(enumType.element()); assert typeDef != null; assertThat(typeDef.qualifiedName()).isEqualTo("com.github.cuzfrog.EnumA"); assertThat(typeDef.simpleName()).isEqualTo("EnumA"); @@ -76,7 +76,7 @@ void enumValueMarkedOnField() { ctxMocks.primitiveVariable("field2", TypeKind.CHAR).withAnnotation(SharedType.EnumValue.class).element() ); - var typeDef = (EnumDef)parser.parse(enumType.element()); + EnumDef typeDef = (EnumDef)parser.parse(enumType.element()); assert typeDef != null; assertThat(typeDef.qualifiedName()).isEqualTo("com.github.cuzfrog.EnumA"); assertThat(typeDef.simpleName()).isEqualTo("EnumA"); diff --git a/processor/src/test/java/org/sharedtype/processor/resolver/LoopTypeResolverTest.java b/processor/src/test/java/org/sharedtype/processor/resolver/LoopTypeResolverTest.java index 06fa068..ad0d01c 100644 --- a/processor/src/test/java/org/sharedtype/processor/resolver/LoopTypeResolverTest.java +++ b/processor/src/test/java/org/sharedtype/processor/resolver/LoopTypeResolverTest.java @@ -6,12 +6,16 @@ import org.sharedtype.domain.EnumDef; import org.sharedtype.domain.EnumValueInfo; import org.sharedtype.domain.FieldComponentInfo; +import org.sharedtype.domain.TypeDef; +import org.sharedtype.domain.TypeInfo; import org.sharedtype.domain.TypeVariableInfo; import org.junit.jupiter.api.Test; import org.sharedtype.processor.context.ContextMocks; import org.sharedtype.processor.parser.TypeDefParser; import javax.lang.model.element.TypeElement; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -26,18 +30,18 @@ final class LoopTypeResolverTest { @Test void resolveFullClass() { - var aTypeInfo = ConcreteTypeInfo.builder() + TypeInfo aTypeInfo = ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.A") .resolved(false) .build(); - var typeDef = ClassDef.builder() + TypeDef typeDef = ClassDef.builder() .qualifiedName("com.github.cuzfrog.Abc").simpleName("Abc") - .components(List.of( + .components(Collections.singletonList( FieldComponentInfo.builder().name("tuple").type( ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.Tuple") .resolved(false) - .typeArgs(List.of( + .typeArgs(Arrays.asList( aTypeInfo, new ArrayTypeInfo(ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.B") @@ -47,10 +51,10 @@ void resolveFullClass() { .build() ).build() )) - .typeVariables(List.of( + .typeVariables(Collections.singletonList( TypeVariableInfo.builder().name("T").build() )) - .supertypes(List.of( + .supertypes(Collections.singletonList( ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.SuperClassA") .resolved(false) @@ -58,36 +62,36 @@ void resolveFullClass() { )) .build(); - var tupleDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.Tuple").simpleName("Tuple").build(); + ClassDef tupleDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.Tuple").simpleName("Tuple").build(); when(typeDefParser.parse(mockElementByName("com.github.cuzfrog.Tuple"))).thenReturn(tupleDef); - var aDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.A").simpleName("A").build(); + ClassDef aDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.A").simpleName("A").build(); when(typeDefParser.parse(mockElementByName("com.github.cuzfrog.A"))).thenReturn(aDef); - var bDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.B").simpleName("B").build(); + ClassDef bDef = ClassDef.builder().qualifiedName("com.github.cuzfrog.B").simpleName("B").build(); when(typeDefParser.parse(mockElementByName("com.github.cuzfrog.B"))).thenReturn(bDef); - var superADef = ClassDef.builder() + ClassDef superADef = ClassDef.builder() .qualifiedName("com.github.cuzfrog.SuperClassA").simpleName("SuperClassA") - .components(List.of( + .components(Collections.singletonList( FieldComponentInfo.builder().name("a").type(aTypeInfo).build() )) .build(); when(typeDefParser.parse(mockElementByName("com.github.cuzfrog.SuperClassA"))).thenReturn(superADef); - var defs = resolver.resolve(List.of(typeDef)); + List defs = resolver.resolve(Collections.singletonList(typeDef)); assertThat(defs).hasSize(5); { - var a = (ClassDef) defs.get(0); + ClassDef a = (ClassDef) defs.get(0); assertThat(a).isSameAs(aDef); } { - var b = (ClassDef) defs.get(1); + ClassDef b = (ClassDef) defs.get(1); assertThat(b).isSameAs(bDef); } { - var tuple = (ClassDef) defs.get(2); + ClassDef tuple = (ClassDef) defs.get(2); assertThat(tuple).isSameAs(tupleDef); } { - var superclassA = (ClassDef) defs.get(3); + ClassDef superclassA = (ClassDef) defs.get(3); assertThat(superclassA.qualifiedName()).isEqualTo("com.github.cuzfrog.SuperClassA"); assertThat(superclassA.simpleName()).isEqualTo("SuperClassA"); assertThat(superclassA.components()).hasSize(1); @@ -98,7 +102,7 @@ void resolveFullClass() { assertThat(fieldType.qualifiedName()).isEqualTo("com.github.cuzfrog.A"); } { - var abc = (ClassDef) defs.get(4); + ClassDef abc = (ClassDef) defs.get(4); assertThat(abc).isSameAs(typeDef); FieldComponentInfo field = abc.components().get(0); assertThat(field.resolved()).isTrue(); @@ -122,22 +126,22 @@ void resolveFullClass() { @Test void resolveSimpleEnum() { - var typeDef = EnumDef.builder() + EnumDef typeDef = EnumDef.builder() .qualifiedName("com.github.cuzfrog.EnumA").simpleName("EnumA") - .enumValueInfos(List.of( + .enumValueInfos(Arrays.asList( new EnumValueInfo(STRING_TYPE_INFO, "Value1"), new EnumValueInfo(STRING_TYPE_INFO, "Value2") )) .build(); - var defs = resolver.resolve(List.of(typeDef)); + List defs = resolver.resolve(Collections.singletonList(typeDef)); assertThat(defs).hasSize(1); - var enumA = (EnumDef) defs.get(0); + EnumDef enumA = (EnumDef) defs.get(0); assertThat(enumA).isSameAs(typeDef); } private TypeElement mockElementByName(String qualifiedName) { - var typeElement = ctxMocks.typeElement(qualifiedName).element(); + TypeElement typeElement = ctxMocks.typeElement(qualifiedName).element(); when(ctxMocks.getElements().getTypeElement(qualifiedName)).thenReturn(typeElement); return typeElement; } diff --git a/processor/src/test/java/org/sharedtype/processor/writer/TypescriptTypeFileWriterTest.java b/processor/src/test/java/org/sharedtype/processor/writer/TypescriptTypeFileWriterTest.java index 8af491f..257bc9b 100644 --- a/processor/src/test/java/org/sharedtype/processor/writer/TypescriptTypeFileWriterTest.java +++ b/processor/src/test/java/org/sharedtype/processor/writer/TypescriptTypeFileWriterTest.java @@ -23,6 +23,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -55,15 +57,15 @@ void setUp() throws IOException { @Test void writeEnumUnion() throws IOException { doAnswer(invoc -> { - var writer = invoc.getArgument(0, Writer.class); + Writer writer = invoc.getArgument(0); writer.write("some-value"); return null; }).when(renderer).render(any(), any()); - var enumDef = EnumDef.builder() + EnumDef enumDef = EnumDef.builder() .simpleName("EnumA") .qualifiedName("com.github.cuzfrog.EnumA") - .enumValueInfos(List.of( + .enumValueInfos(Arrays.asList( new EnumValueInfo(STRING_TYPE_INFO, "Value1"), new EnumValueInfo(INT_TYPE_INFO, 123) )) @@ -71,42 +73,42 @@ void writeEnumUnion() throws IOException { when(ctxMocks.getElements().getConstantExpression("Value1")).thenReturn("\"Value1\""); when(ctxMocks.getElements().getConstantExpression(123)).thenReturn("123"); - writer.write(List.of(enumDef)); + writer.write(Collections.singletonList(enumDef)); verify(renderer).render(any(), renderDataCaptor.capture()); assertThat(outputStream.toString()).isEqualTo("some-value"); - var data = renderDataCaptor.getValue(); + List> data = renderDataCaptor.getValue(); assertThat(data).hasSize(1); assertThat(data.get(0).a()).isEqualTo(Template.TEMPLATE_ENUM_UNION); - var model = (TypescriptTypeFileWriter.EnumUnionExpr) data.get(0).b(); - assertThat(model.name()).isEqualTo("EnumA"); - assertThat(model.values()).containsExactly("\"Value1\"", "123"); + TypescriptTypeFileWriter.EnumUnionExpr model = (TypescriptTypeFileWriter.EnumUnionExpr) data.get(0).b(); + assertThat(model.name).isEqualTo("EnumA"); + assertThat(model.values).containsExactly("\"Value1\"", "123"); when(ctxMocks.getElements().getConstantExpression(123)).thenThrow(IllegalArgumentException.class); - assertThatThrownBy(() -> writer.write(List.of(enumDef))) + assertThatThrownBy(() -> writer.write(Collections.singletonList(enumDef))) .hasMessageContaining("Failed to get constant expression for enum value: 123 of type int in enum"); } @Test void writeInterface() throws IOException { when(ctxMocks.getContext().createSourceOutput("types.d.ts")).thenReturn(fileObject); - var classDef = ClassDef.builder() + ClassDef classDef = ClassDef.builder() .qualifiedName("com.github.cuzfrog.ClassA") .simpleName("ClassA") - .typeVariables(List.of( + .typeVariables(Arrays.asList( TypeVariableInfo.builder().name("T").build(), TypeVariableInfo.builder().name("U").build() )) - .supertypes(List.of( + .supertypes(Collections.singletonList( ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.SuperClassA") .simpleName("SuperClassA") - .typeArgs(List.of(TypeVariableInfo.builder().name("U").build())) + .typeArgs(Collections.singletonList(TypeVariableInfo.builder().name("U").build())) .build() )) - .components(List.of( + .components(Arrays.asList( FieldComponentInfo.builder().name("field1").type(INT_TYPE_INFO).optional(true).build(), FieldComponentInfo.builder().name("field2").type(STRING_TYPE_INFO).optional(false).build(), FieldComponentInfo.builder().name("field3") @@ -116,7 +118,7 @@ void writeInterface() throws IOException { ConcreteTypeInfo.builder() .qualifiedName("com.github.cuzfrog.Container") .simpleName("Container") - .typeArgs(List.of(TypeVariableInfo.builder().name("T").build())) + .typeArgs(Collections.singletonList(TypeVariableInfo.builder().name("T").build())) .build() ) ) @@ -128,34 +130,34 @@ void writeInterface() throws IOException { )) .build(); - writer.write(List.of(classDef)); + writer.write(Collections.singletonList(classDef)); verify(renderer).render(any(), renderDataCaptor.capture()); - var data = renderDataCaptor.getValue(); + List> data = renderDataCaptor.getValue(); assertThat(data).hasSize(1); assertThat(data.get(0).a()).isEqualTo(Template.TEMPLATE_INTERFACE); - var model = (TypescriptTypeFileWriter.InterfaceExpr) data.get(0).b(); - assertThat(model.name()).isEqualTo("ClassA"); - assertThat(model.typeParameters()).containsExactly("T", "U"); - assertThat(model.supertypes()).containsExactly("SuperClassA"); - assertThat(model.properties()).hasSize(4); - var prop1 = model.properties().get(0); - assertThat(prop1.name()).isEqualTo("field1"); - assertThat(prop1.type()).isEqualTo("number"); - assertThat(prop1.optional()).isTrue(); - - var prop2 = model.properties().get(1); - assertThat(prop2.name()).isEqualTo("field2"); - assertThat(prop2.type()).isEqualTo("string"); - assertThat(prop2.optional()).isFalse(); - - var prop3 = model.properties().get(2); - assertThat(prop3.name()).isEqualTo("field3"); - assertThat(prop3.type()).isEqualTo("Container[][]"); - assertThat(prop3.optional()).isFalse(); - - var prop4 = model.properties().get(3); - assertThat(prop4.name()).isEqualTo("field4"); - assertThat(prop4.type()).isEqualTo("T[]"); - assertThat(prop4.optional()).isFalse(); + TypescriptTypeFileWriter.InterfaceExpr model = (TypescriptTypeFileWriter.InterfaceExpr) data.get(0).b(); + assertThat(model.name).isEqualTo("ClassA"); + assertThat(model.typeParameters).containsExactly("T", "U"); + assertThat(model.supertypes).containsExactly("SuperClassA"); + assertThat(model.properties).hasSize(4); + TypescriptTypeFileWriter.PropertyExpr prop1 = model.properties.get(0); + assertThat(prop1.name).isEqualTo("field1"); + assertThat(prop1.type).isEqualTo("number"); + assertThat(prop1.optional).isTrue(); + + TypescriptTypeFileWriter.PropertyExpr prop2 = model.properties.get(1); + assertThat(prop2.name).isEqualTo("field2"); + assertThat(prop2.type).isEqualTo("string"); + assertThat(prop2.optional).isFalse(); + + TypescriptTypeFileWriter.PropertyExpr prop3 = model.properties.get(2); + assertThat(prop3.name).isEqualTo("field3"); + assertThat(prop3.type).isEqualTo("Container[][]"); + assertThat(prop3.optional).isFalse(); + + TypescriptTypeFileWriter.PropertyExpr prop4 = model.properties.get(3); + assertThat(prop4.name).isEqualTo("field4"); + assertThat(prop4.type).isEqualTo("T[]"); + assertThat(prop4.optional).isFalse(); } } diff --git a/processor/src/test/java/org/sharedtype/processor/writer/render/MustacheTemplateRendererTest.java b/processor/src/test/java/org/sharedtype/processor/writer/render/MustacheTemplateRendererTest.java index 3fd32b2..1ab9529 100644 --- a/processor/src/test/java/org/sharedtype/processor/writer/render/MustacheTemplateRendererTest.java +++ b/processor/src/test/java/org/sharedtype/processor/writer/render/MustacheTemplateRendererTest.java @@ -11,6 +11,8 @@ import org.sharedtype.processor.support.utils.Tuple; import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -38,13 +40,13 @@ void loadTemplatesAndRender() { when(mf.compile("templates/go/test.mustache")).thenReturn(compiledMustache); renderer.loadTemplates(template); - renderer.render(writer, List.of(Tuple.of(template, new HashMap<>()))); + renderer.render(writer, Collections.singletonList(Tuple.of(template, new HashMap<>()))); verify(compiledMustache).execute(writer, new HashMap<>()); } @Test void errorIfTemplateNotLoaded() { - assertThatThrownBy(() -> renderer.render(writer, List.of(Tuple.of(template, new HashMap<>())))) + assertThatThrownBy(() -> renderer.render(writer, Collections.singletonList(Tuple.of(template, new HashMap<>())))) .hasMessageContaining("Template not found"); } } diff --git a/setenv b/setenv index 2bdb87f..bbd3b43 100755 --- a/setenv +++ b/setenv @@ -1,6 +1,23 @@ #!/bin/bash +version=$1 -export JAVA_HOME=$JAVA17_HOME -export PATH=$JAVA_HOME/bin:$PATH +if [ -z "$version" ];then + version="17" + echo "No version provided, use default jdk$version" +fi + +if [[ "$version" == "17" ]];then + export JAVA_HOME=$JAVA17_HOME +elif [[ "$version" == "8" ]];then + export JAVA_HOME=$JAVA8_HOME +elif [[ "$version" == "11" ]];then + export JAVA_HOME=$JAVA11_HOME +elif [[ "$version" == "21" ]];then + export JAVA_HOME=$JAVA21_HOME +else + echo "Unsupported version $version" + return +fi +export PATH=$JAVA_HOME/bin:$PATH java -version diff --git a/setenv.bat b/setenv.bat deleted file mode 100644 index 94eef57..0000000 --- a/setenv.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -set PATH=%$JAVA17_HOME%\bin;%PATH% -set JAVA_HOME=%$JAVA17_HOME% - -java -version