diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
index 02e7bba3..2d9f8e48 100644
--- a/.github/workflows/default.yml
+++ b/.github/workflows/default.yml
@@ -13,24 +13,19 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest,macos-latest,windows-latest ]
- java: [ 8.0.x, 9.0.x, 11.0.x, 12.0.x, 13.0.x, 14.0.x, 15.0.x, 16.0.x, 17.0.x ]
+ java: [ '8', '11', '17', '21' ]
steps:
- name: Checkout Code
- uses: actions/checkout@v1
+ uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v4
with:
+ distribution: 'zulu'
java-version: ${{ matrix.java }}
+ cache: 'maven'
- - name: Cache .m2
- uses: actions/cache@v1
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven
- name: Prepare mvnw
run: chmod +x ./mvnw
@@ -38,3 +33,5 @@ jobs:
- name: Build
run: ./mvnw clean package
+
+
diff --git a/.github/workflows/default_oracle.yml b/.github/workflows/default_oracle.yml
new file mode 100644
index 00000000..d6892c9b
--- /dev/null
+++ b/.github/workflows/default_oracle.yml
@@ -0,0 +1,35 @@
+name: default_oracle
+
+on:
+ push:
+ branches:
+ - '*'
+ - '**/*'
+ - '!master'
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ ubuntu-latest,macos-latest,windows-latest ]
+ java: [ '17', '21' ]
+
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'oracle'
+ java-version: ${{ matrix.java }}
+ cache: 'maven'
+
+
+ - name: Prepare mvnw
+ run: chmod +x ./mvnw
+
+ - name: Build
+ run: ./mvnw clean package
+
diff --git a/.github/workflows/default_temurin.yml b/.github/workflows/default_temurin.yml
new file mode 100644
index 00000000..04877f37
--- /dev/null
+++ b/.github/workflows/default_temurin.yml
@@ -0,0 +1,35 @@
+name: default_temurin
+
+on:
+ push:
+ branches:
+ - '*'
+ - '**/*'
+ - '!master'
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ ubuntu-latest,macos-latest,windows-latest ]
+ java: [ '8', '11', '17', '21' ]
+
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: ${{ matrix.java }}
+ cache: 'maven'
+
+
+ - name: Prepare mvnw
+ run: chmod +x ./mvnw
+
+ - name: Build
+ run: ./mvnw clean package
+
diff --git a/.github/workflows/dropStaging.yml b/.github/workflows/dropStaging.yml
index dd930de1..7836d736 100644
--- a/.github/workflows/dropStaging.yml
+++ b/.github/workflows/dropStaging.yml
@@ -17,13 +17,15 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
# Setup JDK and Maven
- name: Set up JDK 9
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v4
with:
- java-version: 9
+ distribution: 'zulu'
+ java-version: 17
+ cache: 'maven'
server-id: sonatype-nexus-staging
server-username: OSS_CENTRAL_USERNAME # env variable for Maven Central
server-password: OSS_CENTRAL_PASSWORD # env variable for Maven Central
diff --git a/.github/workflows/jacoco.yml b/.github/workflows/jacoco.yml
index 46456753..9661e777 100644
--- a/.github/workflows/jacoco.yml
+++ b/.github/workflows/jacoco.yml
@@ -13,20 +13,15 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v1
+ uses: actions/checkout@v4
- - name: Set up JDK 9
- uses: actions/setup-java@v1
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 9
+ distribution: 'zulu'
+ java-version: 17
+ cache: 'maven'
- - name: Cache .m2
- uses: actions/cache@v1
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven
- name: Prepare mvnw
run: chmod +x ./mvnw
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6d056bb3..718bbf49 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,15 +11,7 @@ jobs:
steps:
- name: Checkout Code
- uses: actions/checkout@v1
-
- - name: Cache .m2
- uses: actions/cache@v1
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven
+ uses: actions/checkout@v4
# Get GPG private key into GPG
- name: Import GPG Owner Trust
@@ -28,10 +20,12 @@ jobs:
run: echo ${{ secrets.GPG_SECRET_KEYS }} | base64 --decode | gpg --import --no-tty --batch --yes
# Setup JDK and Maven
- - name: Set up JDK 9
- uses: actions/setup-java@v1
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 9
+ distribution: 'zulu'
+ java-version: 17
+ cache: 'maven'
server-id: sonatype-nexus-staging
server-username: OSS_CENTRAL_USERNAME # env variable for Maven Central
server-password: OSS_CENTRAL_PASSWORD # env variable for Maven Central
diff --git a/annotationwrapper/api/pom.xml b/annotationwrapper/api/pom.xml
index 0680b126..4119864a 100644
--- a/annotationwrapper/api/pom.xml
+++ b/annotationwrapper/api/pom.xml
@@ -8,7 +8,7 @@
io.toolisticon.aptk
aptk-annotationwrapper-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-annotationwrapper-api
diff --git a/annotationwrapper/integrationtest/pom.xml b/annotationwrapper/integrationtest/pom.xml
index 454c3335..c7a5d39c 100644
--- a/annotationwrapper/integrationtest/pom.xml
+++ b/annotationwrapper/integrationtest/pom.xml
@@ -9,7 +9,7 @@
io.toolisticon.aptk
aptk-annotationwrapper-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-annotationwrapper-integrationTest
diff --git a/annotationwrapper/pom.xml b/annotationwrapper/pom.xml
index 5068d84e..e4fc4c27 100644
--- a/annotationwrapper/pom.xml
+++ b/annotationwrapper/pom.xml
@@ -11,7 +11,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
diff --git a/annotationwrapper/processor/pom.xml b/annotationwrapper/processor/pom.xml
index 5f2055b9..df8ff143 100644
--- a/annotationwrapper/processor/pom.xml
+++ b/annotationwrapper/processor/pom.xml
@@ -9,7 +9,7 @@
io.toolisticon.aptk
aptk-annotationwrapper-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-annotationwrapper-processor
diff --git a/common/pom.xml b/common/pom.xml
index 0b3c3313..cd1d67d8 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -7,7 +7,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-common
diff --git a/compilermessages/api/pom.xml b/compilermessages/api/pom.xml
index 4173655a..ff64ba8a 100644
--- a/compilermessages/api/pom.xml
+++ b/compilermessages/api/pom.xml
@@ -8,7 +8,7 @@
io.toolisticon.aptk
aptk-compilermessages-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-compilermessages-api
diff --git a/compilermessages/integrationtest/pom.xml b/compilermessages/integrationtest/pom.xml
index 1eb7e855..51b56485 100644
--- a/compilermessages/integrationtest/pom.xml
+++ b/compilermessages/integrationtest/pom.xml
@@ -9,7 +9,7 @@
io.toolisticon.aptk
aptk-compilermessages-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-compilermessages-integrationTest
diff --git a/compilermessages/pom.xml b/compilermessages/pom.xml
index 265d741c..ce55730c 100644
--- a/compilermessages/pom.xml
+++ b/compilermessages/pom.xml
@@ -11,7 +11,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
diff --git a/compilermessages/processor/pom.xml b/compilermessages/processor/pom.xml
index b3818320..3df8978b 100644
--- a/compilermessages/processor/pom.xml
+++ b/compilermessages/processor/pom.xml
@@ -9,7 +9,7 @@
io.toolisticon.aptk
aptk-compilermessages-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-compilermessages-processor
diff --git a/cute/pom.xml b/cute/pom.xml
index 5ea81dbb..ec79516d 100644
--- a/cute/pom.xml
+++ b/cute/pom.xml
@@ -8,7 +8,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-cute
diff --git a/example/example-annotationprocessor/pom.xml b/example/example-annotationprocessor/pom.xml
index f7e345ec..b54fd042 100644
--- a/example/example-annotationprocessor/pom.xml
+++ b/example/example-annotationprocessor/pom.xml
@@ -8,7 +8,7 @@
io.toolisticon.aptk
aptk-example-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-example-annotationprocessor
diff --git a/example/example-annotations/pom.xml b/example/example-annotations/pom.xml
index a77b9fc6..5af61772 100644
--- a/example/example-annotations/pom.xml
+++ b/example/example-annotations/pom.xml
@@ -7,7 +7,7 @@
io.toolisticon.aptk
aptk-example-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-example-annotations
diff --git a/example/example-usecase/pom.xml b/example/example-usecase/pom.xml
index 2de146b6..8e24038d 100644
--- a/example/example-usecase/pom.xml
+++ b/example/example-usecase/pom.xml
@@ -7,7 +7,7 @@
io.toolisticon.aptk
aptk-example-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-example-usecase
diff --git a/example/pom.xml b/example/pom.xml
index 63ce5bc6..a5069553 100644
--- a/example/pom.xml
+++ b/example/pom.xml
@@ -7,7 +7,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-example-parent
diff --git a/extensions/java9/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java b/extensions/java9/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java
deleted file mode 100644
index aeea5432..00000000
--- a/extensions/java9/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.toolisticon.aptk.tools.wrapper;
-
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ModuleElement;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class ModuleElementWrapper extends ElementWrapper {
-
- private ModuleElementWrapper(ModuleElement moduleElement) {
- super(moduleElement);
- }
-
- public String getQualifiedName() {
- return this.element.getQualifiedName().toString();
- }
-
- public boolean hasQualifiedName(String name) {
- return name != null && this.getQualifiedName().equals(name);
- }
-
- public boolean isOpen() {
- return this.element.isOpen();
- }
-
- public boolean isUnnamed() {
- return this.element.isUnnamed();
- }
-
- public List extends ModuleElement.Directive> getDirectives() {
- return this.element.getDirectives();
- }
-
- public static ModuleElementWrapper toModuleElement(Element element) {
- return ModuleElementWrapper.wrap((ModuleElement) element);
- }
-
- public static ModuleElementWrapper wrap(ModuleElement moduleElement) {
- return new ModuleElementWrapper(moduleElement);
- }
-
- public static List wrapList(List moduleElements) {
- return moduleElements.stream().map(ModuleElementWrapper::new).collect(Collectors.toList());
- }
-
-}
diff --git a/extensions/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java b/extensions/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java
deleted file mode 100644
index 406c28b2..00000000
--- a/extensions/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package io.toolisticon.aptk.wrapper;
-
-import io.toolisticon.aptk.tools.wrapper.ElementWrapper;
-import io.toolisticon.aptk.tools.wrapper.ModuleElementWrapper;
-import org.hamcrest.MatcherAssert;
-import org.hamcrest.Matchers;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ModuleElement;
-import javax.lang.model.element.Name;
-import javax.lang.model.element.TypeElement;
-
-/**
- * Unit test for {@link io.toolisticon.aptk.tools.wrapper.ModuleElementWrapper}.
- */
-public class ModuleElementWrapperTest {
-
-
- @Test
- public void testCreationOfWrapperAndUnwrap() {
- ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
- MatcherAssert.assertThat(unit, Matchers.notNullValue());
- MatcherAssert.assertThat(unit.unwrap(), Matchers.is(moduleElement));
- }
-
- @Test
- public void test_getQualifiedName() {
- ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
- Name name = Mockito.mock(Name.class);
- Mockito.when(name.toString()).thenReturn("JUPP");
- Mockito.when(moduleElement.getQualifiedName()).thenReturn(name);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
- MatcherAssert.assertThat(unit.getQualifiedName(), Matchers.is("JUPP"));
- }
-
- @Test
- public void test_hasQualifiedName() {
- ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
- Name name = Mockito.mock(Name.class);
- Mockito.when(name.toString()).thenReturn("YES");
- Mockito.when(moduleElement.getQualifiedName()).thenReturn(name);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
- MatcherAssert.assertThat(unit.hasQualifiedName("YES"), Matchers.is(true));
- MatcherAssert.assertThat(unit.hasQualifiedName("NO"), Matchers.is(false));
- MatcherAssert.assertThat(unit.hasQualifiedName(null), Matchers.is(false));
- }
-
- @Test
- public void proxyTests_isOpen() {
- ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
-
- unit.isOpen();
- Mockito.verify(moduleElement, Mockito.times(1)).isOpen();
-
- }
-
- @Test
- public void proxyTests_isUnnamed() {
- ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
-
- unit.isUnnamed();
- Mockito.verify(moduleElement, Mockito.times(1)).isUnnamed();
-
- }
-
- @Test
- public void proxyTests_getDirectives() {
- ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
- ModuleElementWrapper unit = ModuleElementWrapper.wrap(moduleElement);
-
- unit.getDirectives();
- Mockito.verify(moduleElement, Mockito.times(1)).getDirectives();
-
- }
-
- @Test
- public void test_isModuleElement() {
- ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
-
- Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
- MatcherAssert.assertThat(ElementWrapper.wrap(moduleElement).isModule(), Matchers.is(true));
-
-
- TypeElement typeElement = Mockito.mock(TypeElement.class);
- Mockito.when(typeElement.getKind()).thenReturn(ElementKind.CLASS);
- MatcherAssert.assertThat(ElementWrapper.wrap(typeElement).isModuleElement(), Matchers.is(false));
-
- }
-/*-
-
- public static boolean isModuleElement(Element element) {
- return element != null & element.getKind().equals(ElementKind.MODULE);
- }
-
- public static ModuleElementWrapperTest toModuleElement(Element element) {
- return ModuleElementWrapperTest.wrap((ModuleElement) element);
- }
-
- public static ModuleElementWrapperTest wrap(ModuleElement moduleElement) {
- return new ModuleElementWrapperTest(moduleElement);
- }
-
-
- */
-
-}
diff --git a/extensions/pom.xml b/extensions/pom.xml
deleted file mode 100644
index 5e41e6c1..00000000
--- a/extensions/pom.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
- 4.0.0
-
- extension-parent
- pom
-
-
- io.toolisticon.aptk
- aptk-parent
- 0.24.1-SNAPSHOT
-
-
- extension-parent
-
-
-
-
-
- java-9
-
- [9,)
-
-
-
- java9
-
-
-
-
-
-
diff --git a/integrationtest/java16/pom.xml b/integrationtest/java16/pom.xml
new file mode 100644
index 00000000..9c9e9b22
--- /dev/null
+++ b/integrationtest/java16/pom.xml
@@ -0,0 +1,94 @@
+
+ 4.0.0
+
+ aptk-tools-java16
+ jar
+
+
+ io.toolisticon.aptk
+ integrationtest-parent
+ 0.24.1-148_records-SNAPSHOT
+
+
+ aptk-tools-java16
+
+
+
+
+
+ io.toolisticon.aptk
+ aptk-tools
+
+
+
+
+
+
+
+
+
+
+ maven-enforcer-plugin
+
+
+ enforce
+
+ enforce
+
+
+
+
+ [3.0.4,)
+
+
+ 16
+
+
+ false
+
+ *
+
+
+ io.toolisticon.aptk:aptk-tools:*
+ *:*:*:*:test:*
+ *:*:*:*:provided:*
+
+
+
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+ 16
+
+
+
+
+ org.codehaus.mojo
+ animal-sniffer-maven-plugin
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/java16/src/test/java/io/toolisticon/aptk/tools/wrapper/Java16Tests.java b/integrationtest/java16/src/test/java/io/toolisticon/aptk/tools/wrapper/Java16Tests.java
new file mode 100644
index 00000000..6bb9b3d8
--- /dev/null
+++ b/integrationtest/java16/src/test/java/io/toolisticon/aptk/tools/wrapper/Java16Tests.java
@@ -0,0 +1,171 @@
+package io.toolisticon.aptk.tools.wrapper;
+
+import io.toolisticon.aptk.common.ToolingProvider;
+import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
+import io.toolisticon.cute.Cute;
+import io.toolisticon.cute.PassIn;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class Java16Tests {
+
+ @PassIn
+ record MyRecord(String name, String surname) {
+ }
+
+ @Test
+ public void test_records_isRecord() {
+ Cute.unitTest().when().passInElement().fromClass(MyRecord.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ ElementWrapper> elementWrapper = ElementWrapper.wrap(element);
+
+ MatcherAssert.assertThat("Should detect record ", elementWrapper.isRecord());
+ MatcherAssert.assertThat("Should not detect record ", !TypeElementWrapper.getByClass(Java16Tests.class).get().isRecord());
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+ @Test
+ public void test_records_isTypeElement() {
+ Cute.unitTest().when().passInElement().fromClass(MyRecord.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ ElementWrapper> elementWrapper = ElementWrapper.wrap(element);
+
+ MatcherAssert.assertThat("Should detect record ", elementWrapper.isTypeElement());
+ MatcherAssert.assertThat("Should return false", !elementWrapper.isExecutableElement());
+ MatcherAssert.assertThat("Should return false ", !elementWrapper.isVariableElement());
+ MatcherAssert.assertThat("Should return false ", !elementWrapper.isTypeParameterElement());
+ MatcherAssert.assertThat("Should return false", !elementWrapper.isModuleElement());
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+
+ @Test
+ public void test_recordComponent_isRecordComponent() {
+ Cute.unitTest().when().passInElement().fromClass(MyRecord.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ TypeElement typeElement = (TypeElement) element;
+
+ ElementWrapper> elementWrapper = ElementWrapper.wrap(typeElement.getRecordComponents().get(0));
+
+ MatcherAssert.assertThat("Should detect record ", elementWrapper.isRecordComponent());
+ MatcherAssert.assertThat("Should not detect record ", !TypeElementWrapper.getByClass(Java16Tests.class).get().isRecordComponent());
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+ @Test
+ public void test_recordComponent_isTypeElement() {
+ Cute.unitTest().when().passInElement().fromClass(MyRecord.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ TypeElement typeElement = (TypeElement) element;
+
+ ElementWrapper> elementWrapper = ElementWrapper.wrap(typeElement.getRecordComponents().get(0));
+
+ MatcherAssert.assertThat("Should detect RecordComponentElement ", elementWrapper.isRecordComponentElement());
+ MatcherAssert.assertThat("Should detect false ", !elementWrapper.isTypeElement());
+ MatcherAssert.assertThat("Should return false", !elementWrapper.isExecutableElement());
+ MatcherAssert.assertThat("Should return false ", !elementWrapper.isVariableElement());
+ MatcherAssert.assertThat("Should return false ", !elementWrapper.isTypeParameterElement());
+ MatcherAssert.assertThat("Should return false", !elementWrapper.isModuleElement());
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+ @Test
+ public void test_recordComponent_accessWrapperMethods() {
+ Cute.unitTest().when().passInElement().fromClass(MyRecord.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+ TypeElementWrapper typeElement = TypeElementWrapper.wrap(element);
+
+ RecordComponentElementWrapper elementWrapper = typeElement.getRecordComponents().get(0);
+ MatcherAssert.assertThat(elementWrapper.getSimpleName(), Matchers.is("name"));
+ MatcherAssert.assertThat("Must be methods", elementWrapper.getAccessor().isMethod());
+ MatcherAssert.assertThat(elementWrapper.getEnclosingRecordTypeElement().getQualifiedName(), Matchers.is(MyRecord.class.getCanonicalName()));
+ MatcherAssert.assertThat(TypeElementWrapper.toTypeElement(elementWrapper.getEnclosingElement().get()).getQualifiedName(), Matchers.is(MyRecord.class.getCanonicalName()));
+
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+
+ @Test
+ public void test_recordComponent_filtering_byTypeElement() {
+ Cute.unitTest().when((processingEnvironment) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+ TypeElementWrapper typeElement = TypeElementWrapper.getByClass(Java16Tests.class).get();
+
+ Set enclosedTypeElements = typeElement.filterFlattenedEnclosedElementTree().applyFilter(AptkCoreMatchers.IS_TYPE_ELEMENT).getResult().stream().map(e -> e.getQualifiedName().toString()).collect(Collectors.toSet());
+
+ MatcherAssert.assertThat(enclosedTypeElements, Matchers.contains(MyRecord.class.getCanonicalName()));
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+ @Test
+ public void test_recordComponent_filtering_byRecord() {
+ Cute.unitTest().when((processingEnvironment) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+ TypeElementWrapper typeElement = TypeElementWrapper.getByClass(Java16Tests.class).get();
+
+ Set enclosedTypeElements = typeElement.filterFlattenedEnclosedElementTree().applyFilter(AptkCoreMatchers.IS_RECORD).getResult().stream().map(e -> e.getQualifiedName().toString()).collect(Collectors.toSet());
+
+ MatcherAssert.assertThat(enclosedTypeElements, Matchers.hasSize(1));
+ MatcherAssert.assertThat(enclosedTypeElements, Matchers.contains(MyRecord.class.getCanonicalName()));
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+}
diff --git a/integrationtest/java17/pom.xml b/integrationtest/java17/pom.xml
new file mode 100644
index 00000000..a5c9c710
--- /dev/null
+++ b/integrationtest/java17/pom.xml
@@ -0,0 +1,94 @@
+
+ 4.0.0
+
+ aptk-tools-java17
+ jar
+
+
+ io.toolisticon.aptk
+ integrationtest-parent
+ 0.24.1-148_records-SNAPSHOT
+
+
+ aptk-tools-java17
+
+
+
+
+
+ io.toolisticon.aptk
+ aptk-tools
+
+
+
+
+
+
+
+
+
+
+ maven-enforcer-plugin
+
+
+ enforce
+
+ enforce
+
+
+
+
+ [3.0.4,)
+
+
+ 17
+
+
+ false
+
+ *
+
+
+ io.toolisticon.aptk:aptk-tools:*
+ *:*:*:*:test:*
+ *:*:*:*:provided:*
+
+
+
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+ 17
+
+
+
+
+ org.codehaus.mojo
+ animal-sniffer-maven-plugin
+
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtest/java17/src/test/java/io/toolisticon/aptk/tools/wrapper/Java17Tests.java b/integrationtest/java17/src/test/java/io/toolisticon/aptk/tools/wrapper/Java17Tests.java
new file mode 100644
index 00000000..c78b9c17
--- /dev/null
+++ b/integrationtest/java17/src/test/java/io/toolisticon/aptk/tools/wrapper/Java17Tests.java
@@ -0,0 +1,66 @@
+package io.toolisticon.aptk.tools.wrapper;
+
+import io.toolisticon.aptk.common.ToolingProvider;
+import io.toolisticon.cute.Cute;
+import io.toolisticon.cute.PassIn;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.stream.Collectors;
+
+public class Java17Tests {
+
+
+ @Test
+ public void test_sealedClassesFeature_unsealed() {
+ Cute.unitTest().when((processingEnvironment) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ TypeElementWrapper elementWrapper = TypeElementWrapper.getByClass(Java17Tests.class).get();
+
+ MatcherAssert.assertThat(elementWrapper.getPermittedSubclasses(), Matchers.empty());
+ MatcherAssert.assertThat(elementWrapper.unwrap().getPermittedSubclasses(), Matchers.empty());
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+
+ static final class AllowedClass extends SealedClass {
+
+ }
+
+ @PassIn
+ static sealed class SealedClass permits AllowedClass {
+
+ }
+
+
+ @Test
+ public void test_sealedClassesFeature_sealed() {
+ Cute.unitTest().when().passInElement().fromClass(SealedClass.class).intoUnitTest((processingEnvironment, element) -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+
+ TypeElementWrapper elementWrapper = TypeElementWrapper.wrap(element);
+
+ MatcherAssert.assertThat(elementWrapper.getPermittedSubclasses().stream().map(e -> e.getQualifiedName()).collect(Collectors.toSet()), Matchers.contains(AllowedClass.class.getCanonicalName()));
+ MatcherAssert.assertThat(element.getPermittedSubclasses().stream().map(e -> e.toString()).collect(Collectors.toSet()), Matchers.contains(AllowedClass.class.getCanonicalName()));
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+
+ }).thenExpectThat().compilationSucceeds().executeTest();
+
+ }
+
+
+}
diff --git a/extensions/java9/pom.xml b/integrationtest/java9/pom.xml
similarity index 88%
rename from extensions/java9/pom.xml
rename to integrationtest/java9/pom.xml
index b856cd97..761d794e 100644
--- a/extensions/java9/pom.xml
+++ b/integrationtest/java9/pom.xml
@@ -7,8 +7,8 @@
io.toolisticon.aptk
- extension-parent
- 0.24.1-SNAPSHOT
+ integrationtest-parent
+ 0.24.1-148_records-SNAPSHOT
aptk-tools-java9
@@ -77,6 +77,13 @@
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
diff --git a/integrationtest/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java b/integrationtest/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java
new file mode 100644
index 00000000..595362ab
--- /dev/null
+++ b/integrationtest/java9/src/test/java/io/toolisticon/aptk/wrapper/ModuleElementWrapperTest.java
@@ -0,0 +1,179 @@
+package io.toolisticon.aptk.wrapper;
+
+import io.toolisticon.aptk.common.ToolingProvider;
+import io.toolisticon.aptk.tools.wrapper.ElementWrapper;
+import io.toolisticon.aptk.tools.wrapper.ModuleElementWrapper;
+import io.toolisticon.aptk.tools.wrapper.TypeElementWrapper;
+import io.toolisticon.cute.Cute;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.annotation.processing.Processor;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import java.util.Optional;
+
+/**
+ * Unit test for {@link io.toolisticon.aptk.tools.wrapper.ModuleElementWrapper}.
+ */
+public class ModuleElementWrapperTest {
+
+
+ @Test
+ public void testCreationOfWrapperAndUnwrap() {
+ ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element) moduleElement);
+ MatcherAssert.assertThat(unit, Matchers.notNullValue());
+ MatcherAssert.assertThat(unit.unwrap(), Matchers.is(moduleElement));
+ }
+
+ @Test
+ public void test_getQualifiedName() {
+ ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ Name name = Mockito.mock(Name.class);
+ Mockito.when(name.toString()).thenReturn("JUPP");
+ Mockito.when(moduleElement.getQualifiedName()).thenReturn(name);
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element) moduleElement);
+ MatcherAssert.assertThat(unit.getQualifiedName(), Matchers.is("JUPP"));
+ }
+
+ @Test
+ public void test_hasQualifiedName() {
+ ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ Name name = Mockito.mock(Name.class);
+ Mockito.when(name.toString()).thenReturn("YES");
+ Mockito.when(moduleElement.getQualifiedName()).thenReturn(name);
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element) moduleElement);
+ MatcherAssert.assertThat(unit.hasQualifiedName("YES"), Matchers.is(true));
+ MatcherAssert.assertThat(unit.hasQualifiedName("NO"), Matchers.is(false));
+ MatcherAssert.assertThat(unit.hasQualifiedName(null), Matchers.is(false));
+ }
+
+ @Test
+ public void proxyTests_isOpen() {
+ ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element) moduleElement);
+
+ unit.isOpen();
+ Mockito.verify(moduleElement, Mockito.times(1)).isOpen();
+
+ }
+
+ @Test
+ public void proxyTests_isUnnamed() {
+ ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element) moduleElement);
+
+ unit.isUnnamed();
+ Mockito.verify(moduleElement, Mockito.times(1)).isUnnamed();
+
+ }
+
+ /*-
+ // TODO: MUST IMPLEMENT DIRECTIVES VIA REFLECTION
+ @Test
+ public void proxyTests_getDirectives() {
+ ModuleElement moduleElement = Mockito.spy(ModuleElement.class);
+ ModuleElementWrapper unit = ModuleElementWrapper.wrap((Element)moduleElement);
+
+ unit.getDirectives();
+ Mockito.verify(moduleElement, Mockito.times(1)).getDirectives();
+
+ }
+ */
+
+ @Test
+ public void test_isModuleElement() {
+ ModuleElement moduleElement = Mockito.mock(ModuleElement.class);
+ Mockito.when(moduleElement.getKind()).thenReturn(ElementKind.MODULE);
+
+ MatcherAssert.assertThat(ElementWrapper.wrap(moduleElement).isModule(), Matchers.is(true));
+
+
+ TypeElement typeElement = Mockito.mock(TypeElement.class);
+ Mockito.when(typeElement.getKind()).thenReturn(ElementKind.CLASS);
+ MatcherAssert.assertThat(ElementWrapper.wrap(typeElement).isModuleElement(), Matchers.is(false));
+
+ }
+
+
+ @Test
+ public void test_blackbox_ModuleElementWrapper_variousTests() {
+ Cute.unitTest().given().useSourceFiles("/testcases/namedModule/module-info.java", "/testcases/namedModule/TestClass.java", "/testcases/namedModule/MyProcessor.java")
+ .when().unitTestWithoutPassIn(processingEnvironment -> {
+ try {
+ ToolingProvider.setTooling(processingEnvironment);
+ TypeElementWrapper typeElementWrapper = TypeElementWrapper.getByFqn("io.toolisticon.aptk.example.regularmodule.TestClass").get();
+ Optional moduleElementWrapper = typeElementWrapper.getModule();
+ MatcherAssert.assertThat("Should find module", moduleElementWrapper.isPresent());
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().isModuleElement());
+
+ MatcherAssert.assertThat(moduleElementWrapper.get().getQualifiedName(), Matchers.is("io.toolisticon.aptk.example"));
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives(), Matchers.hasSize(7));
+
+ // default: requires java.base
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(0).isRequiresDirective());
+ MatcherAssert.assertThat("Should be false for non static", !moduleElementWrapper.get().getDirectives().get(0).toRequiresDirective().isStatic());
+ MatcherAssert.assertThat("Should be false for non transitive", !moduleElementWrapper.get().getDirectives().get(0).toRequiresDirective().isTransitive());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(0).toRequiresDirective().getDependency().getQualifiedName(), Matchers.is("java.base"));
+
+ // exports io.toolisticon.aptk.example.regularmodule;
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(1).isExportDirective());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(1).toExportsDirective().getPackage().getQualifiedName(), Matchers.is("io.toolisticon.aptk.example.regularmodule"));
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(1).toExportsDirective().getTargetModules(), Matchers.hasSize(1));
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(1).toExportsDirective().getTargetModules().get(0).getQualifiedName(), Matchers.is("cute"));
+
+ // requires cute
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(2).isRequiresDirective());
+ MatcherAssert.assertThat("Should be false for non static", !moduleElementWrapper.get().getDirectives().get(2).toRequiresDirective().isStatic());
+ MatcherAssert.assertThat("Should be true for non transitive", moduleElementWrapper.get().getDirectives().get(2).toRequiresDirective().isTransitive());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(2).toRequiresDirective().getDependency().getQualifiedName(), Matchers.is("cute"));
+
+ // requires jdk.compiler;
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(3).isRequiresDirective());
+ MatcherAssert.assertThat("Should be true for non static", moduleElementWrapper.get().getDirectives().get(3).toRequiresDirective().isStatic());
+ MatcherAssert.assertThat("Should be false for non transitive", !moduleElementWrapper.get().getDirectives().get(3).toRequiresDirective().isTransitive());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(3).toRequiresDirective().getDependency().getQualifiedName(), Matchers.is("jdk.compiler"));
+
+ // uses Processor
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(4).isUsesDirective());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(4).toUsesDirective().getService().getQualifiedName(), Matchers.is(Processor.class.getCanonicalName()));
+
+ // opens io.toolisticon.aptk.example.regularmodule to cute
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(5).isOpensDirective());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(5).toOpensDirective().getPackage().getQualifiedName(), Matchers.is("io.toolisticon.aptk.example.regularmodule"));
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(5).toOpensDirective().getTargetModules().get(0).getQualifiedName(), Matchers.is("cute"));
+
+ // provides Processor with io.toolisticon.aptk.example.regularmodule.MyProcessor;
+ MatcherAssert.assertThat("Should be true", moduleElementWrapper.get().getDirectives().get(6).isProvidesDirective());
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(6).toProvidesDirective().getService().getQualifiedName(), Matchers.is(Processor.class.getCanonicalName()));
+ MatcherAssert.assertThat(moduleElementWrapper.get().getDirectives().get(6).toProvidesDirective().getImplementations().get(0).getQualifiedName(), Matchers.is("io.toolisticon.aptk.example.regularmodule.MyProcessor"));
+
+
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+ })
+ .thenExpectThat()
+ .compilationSucceeds()
+ .executeTest();
+
+ }
+
+
+}
diff --git a/integrationtest/java9/src/test/resources/testcases/namedModule/MyProcessor.java b/integrationtest/java9/src/test/resources/testcases/namedModule/MyProcessor.java
new file mode 100644
index 00000000..137d7f5c
--- /dev/null
+++ b/integrationtest/java9/src/test/resources/testcases/namedModule/MyProcessor.java
@@ -0,0 +1,15 @@
+package io.toolisticon.aptk.example.regularmodule;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+public class MyProcessor extends AbstractProcessor {
+
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/integrationtest/java9/src/test/resources/testcases/namedModule/TestClass.java b/integrationtest/java9/src/test/resources/testcases/namedModule/TestClass.java
new file mode 100644
index 00000000..462a35ac
--- /dev/null
+++ b/integrationtest/java9/src/test/resources/testcases/namedModule/TestClass.java
@@ -0,0 +1,8 @@
+package io.toolisticon.aptk.example.regularmodule;
+
+import io.toolisticon.cute.PassIn;
+
+@PassIn
+public class TestClass{
+
+}
\ No newline at end of file
diff --git a/integrationtest/java9/src/test/resources/testcases/namedModule/module-info.java b/integrationtest/java9/src/test/resources/testcases/namedModule/module-info.java
new file mode 100644
index 00000000..35ebfde5
--- /dev/null
+++ b/integrationtest/java9/src/test/resources/testcases/namedModule/module-info.java
@@ -0,0 +1,12 @@
+import javax.annotation.processing.Processor;
+
+module io.toolisticon.aptk.example {
+
+ exports io.toolisticon.aptk.example.regularmodule to cute;
+ requires transitive cute;
+ requires static jdk.compiler;
+ uses Processor;
+ opens io.toolisticon.aptk.example.regularmodule to cute;
+ provides Processor with io.toolisticon.aptk.example.regularmodule.MyProcessor;
+
+}
\ No newline at end of file
diff --git a/integrationtest/pom.xml b/integrationtest/pom.xml
new file mode 100644
index 00000000..a168efd2
--- /dev/null
+++ b/integrationtest/pom.xml
@@ -0,0 +1,56 @@
+
+ 4.0.0
+
+ integrationtest-parent
+ pom
+
+
+ io.toolisticon.aptk
+ aptk-parent
+ 0.24.1-148_records-SNAPSHOT
+
+
+ integrationtest-parent
+
+
+
+
+
+ java-9
+
+ [9,)
+
+
+
+ java9
+
+
+
+
+ java-16
+
+ [16,)
+
+
+
+ java9
+ java16
+
+
+
+
+ java-17
+
+ [17,)
+
+
+
+ java9
+ java16
+ java17
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 78407101..cacf3f49 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
pom
aptk-parent
@@ -18,7 +18,7 @@
tools
example
templating
- extensions
+ integrationtest
annotationwrapper
@@ -58,11 +58,6 @@
2017
-
- 3.6.0
-
-
-
https://github.com/toolisticon/aptk/issues
GitHub Issues
@@ -87,12 +82,13 @@
0.11.0
- 1.0.0_RC1
+ 1.7.0
4.13.2
2.2
- 4.3.1
+ 4.11.0
+ 5.11.0
https://oss.sonatype.org/content/repositories/snapshots/
@@ -202,18 +198,6 @@
-
- org.codehaus.mojo
- build-helper-maven-plugin
- ${maven-build-helper-plugin.version}
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- ${maven-source-plugin.version}
-
com.amashchenko.maven.plugin
@@ -559,6 +543,19 @@
[1.8,9)
+
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+
+
@@ -573,7 +570,7 @@
- check_java17
+ check_java8
test
@@ -611,9 +608,22 @@
jdkgreaterthan8
- [9,99)
+ [9,11)
+
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+
+
@@ -671,6 +681,82 @@
+
+ jdkgreaterthan11
+
+ [11,99)
+
+
+
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito_jdk11.version}
+ test
+
+
+
+
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ animal-sniffer-maven-plugin
+ 1.18
+
+
+
+ com.sun.source.util.Trees
+ com.sun.source.tree.*
+
+
+
+
+
+
+
+ check_java18
+
+ test
+
+
+ check
+
+
+
+
+ io.toolisticon.cute:*
+
+
+
+ org.codehaus.mojo.signature
+ java18
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -689,8 +775,6 @@
-
-
junit
@@ -709,7 +793,6 @@
org.mockito
mockito-core
- ${mockito.version}
test
@@ -760,6 +843,18 @@
${project.version}
+
+ io.toolisticon.aptk
+ aptk-tools-java9
+ ${project.version}
+
+
+
+ io.toolisticon.aptk
+ aptk-tools-java16
+ ${project.version}
+
+
io.toolisticon.spiap
spiap-api
diff --git a/templating/pom.xml b/templating/pom.xml
index 64951be1..8d0fe47c 100644
--- a/templating/pom.xml
+++ b/templating/pom.xml
@@ -7,7 +7,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-templating
diff --git a/tools/pom.xml b/tools/pom.xml
index f7164e7a..db1d866d 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -8,7 +8,7 @@
io.toolisticon.aptk
aptk-parent
- 0.24.1-SNAPSHOT
+ 0.24.1-148_records-SNAPSHOT
aptk-tools
@@ -100,6 +100,7 @@
+
system
${java.home}/../Classes/classes.jar
-
+ -->
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/BeanUtils.java b/tools/src/main/java/io/toolisticon/aptk/tools/BeanUtils.java
index dc0cb27f..2229dab3 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/BeanUtils.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/BeanUtils.java
@@ -1,6 +1,5 @@
package io.toolisticon.aptk.tools;
-import com.sun.source.tree.StatementTree;
import io.toolisticon.aptk.tools.command.impl.GetAttributesCommand;
import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
import io.toolisticon.aptk.tools.fluentfilter.FluentElementFilter;
@@ -20,7 +19,6 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.regex.Pattern;
/**
* Utility class to handle bean related tasks.
@@ -163,6 +161,7 @@ public static boolean isDefaultNoargConstructor(ExecutableElement element) {
return false;
}
+ /*-
// now check statements of constructor
List extends StatementTree> statements = ProcessingEnvironmentUtils.getTrees().getTree(element).getBody().getStatements();
@@ -171,7 +170,8 @@ public static boolean isDefaultNoargConstructor(ExecutableElement element) {
}
return Pattern.compile("^\\s*super\\(\\);?\\s*$").matcher(statements.get(0).toString()).matches();
-
+ */
+ return true;
}
public static boolean isAttribute(VariableElement field) {
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/ElementUtils.java b/tools/src/main/java/io/toolisticon/aptk/tools/ElementUtils.java
index 3315e388..8c8c3319 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/ElementUtils.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/ElementUtils.java
@@ -42,6 +42,16 @@ public static final class CheckKindOfElement {
*/
private final static String KIND_MODULE = "MODULE";
+ /**
+ * Needed for handling Record Type until source level is java 16.
+ */
+ private final static String KIND_RECORD = "RECORD";
+
+ /**
+ * Needed for handling Record Component Type until source level is java 16.
+ */
+ private final static String KIND_RECORD_COMPONENT = "RECORD_COMPONENT";
+
/**
* Hidden constructor.
*/
@@ -60,6 +70,26 @@ public static boolean isEnum(Element e) {
return isOfKind(e, ElementKind.ENUM);
}
+ /**
+ * Checks if passed Element instance is of kind enum.
+ *
+ * @param e the element to check
+ * @return true if passed element is of kind enum, otherwise false
+ */
+ public static boolean isRecord(Element e) {
+ return (e != null && e.getKind().name().equals(KIND_RECORD));
+ }
+
+ /**
+ * Checks if passed Element instance is of kind enum.
+ *
+ * @param e the element to check
+ * @return true if passed element is of kind enum, otherwise false
+ */
+ public static boolean isRecordComponent(Element e) {
+ return (e != null && e.getKind().name().equals(KIND_RECORD_COMPONENT));
+ }
+
/**
* Checks if passed Element instance is of kind class.
*
@@ -204,7 +234,8 @@ public static boolean isOfKind(Element e, ElementKind kind) {
public static final class CastElement {
// look up tables for the different kind of types
- private static final Set TYPE_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet(ElementKind.CLASS, ElementKind.INTERFACE, ElementKind.ENUM, ElementKind.ANNOTATION_TYPE);
+ private static final Set TYPE_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet(ElementKind.CLASS.name(), ElementKind.INTERFACE.name(), ElementKind.ENUM.name(), ElementKind.ANNOTATION_TYPE.name(), "RECORD");
+ private static final Set RECORD_COMPONENT_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet( "RECORD_COMPONENT");
private static final Set TYPE_PARAMETER_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet(ElementKind.TYPE_PARAMETER);
private static final Set VARIABLE_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet(ElementKind.PARAMETER, ElementKind.FIELD);
private static final Set EXECUTABLE_ELEMENT_KIND_LUT = Utilities.convertVarargsToSet(ElementKind.CONSTRUCTOR, ElementKind.METHOD);
@@ -227,7 +258,17 @@ private CastElement() {
* @return true if passed element can be cast to TypeElement, otherwise false
*/
public static boolean isTypeElement(Element e) {
- return e != null && TYPE_ELEMENT_KIND_LUT.contains(e.getKind());
+ return e != null && TYPE_ELEMENT_KIND_LUT.contains(e.getKind().name());
+ }
+
+ /**
+ * Checks if passed element can be cast to RecordComponentElement.
+ *
+ * @param e the element to check
+ * @return true if passed element can be cast to RecordComponentElement, otherwise false
+ */
+ public static boolean isRecordComponentElement(Element e) {
+ return e != null && RECORD_COMPONENT_ELEMENT_KIND_LUT.contains(e.getKind().name());
}
/**
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/ProcessingEnvironmentUtils.java b/tools/src/main/java/io/toolisticon/aptk/tools/ProcessingEnvironmentUtils.java
index 1645872e..43799f44 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/ProcessingEnvironmentUtils.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/ProcessingEnvironmentUtils.java
@@ -1,6 +1,5 @@
package io.toolisticon.aptk.tools;
-import com.sun.source.util.Trees;
import io.toolisticon.aptk.common.ToolingProvider;
import javax.annotation.processing.Filer;
@@ -67,14 +66,4 @@ public static ProcessingEnvironment getProcessingEnvironment() {
return ToolingProvider.getTooling().getProcessingEnvironment();
}
- /**
- * Gets Trees instance.
- *
- * @return The trees instance
- */
- public static Trees getTrees() {
- return Trees.instance(ToolingProvider.getTooling().getProcessingEnvironment());
- }
-
-
}
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/AptkCoreMatchers.java b/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/AptkCoreMatchers.java
index 85c3511c..dc04e290 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/AptkCoreMatchers.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/AptkCoreMatchers.java
@@ -42,6 +42,7 @@
import io.toolisticon.aptk.tools.matcher.impl.IsPackageElementMatcher;
import io.toolisticon.aptk.tools.matcher.impl.IsPackageMatcher;
import io.toolisticon.aptk.tools.matcher.impl.IsParameterMatcher;
+import io.toolisticon.aptk.tools.matcher.impl.IsRecordMatcher;
import io.toolisticon.aptk.tools.matcher.impl.IsSetterMethodMatcher;
import io.toolisticon.aptk.tools.matcher.impl.IsTypeElementMatcher;
import io.toolisticon.aptk.tools.matcher.impl.IsTypeEqualFqnMatcher;
@@ -252,67 +253,73 @@ protected AptkCoreMatchers() {
/**
* Matcher to check if passed element is a ExecutableElement.
*/
- public final static IsCoreMatcher IS_EXECUTABLE_ELEMENT = new IsCoreMatcher<>(new IsExecutableElementMatcher(), CoreMatcherValidationMessages.IS_EXECUTABLE_ELEMENT);
+ public final static IsCoreMatcher IS_EXECUTABLE_ELEMENT = new IsCoreMatcher<>(new IsExecutableElementMatcher<>(), CoreMatcherValidationMessages.IS_EXECUTABLE_ELEMENT);
/**
* Matcher to check if passed element is a TypeElement.
*/
- public final static IsCoreMatcher IS_TYPE_ELEMENT = new IsCoreMatcher<>(new IsTypeElementMatcher(), CoreMatcherValidationMessages.IS_TYPE_ELEMENT);
+ public final static IsCoreMatcher IS_TYPE_ELEMENT = new IsCoreMatcher<>(new IsTypeElementMatcher<>(), CoreMatcherValidationMessages.IS_TYPE_ELEMENT);
/**
* Matcher to check if passed element is a VariableElement.
*/
- public final static IsCoreMatcher IS_VARIABLE_ELEMENT = new IsCoreMatcher<>(new IsVariableElementMatcher(), CoreMatcherValidationMessages.IS_VARIABLE_ELEMENT);
+ public final static IsCoreMatcher IS_VARIABLE_ELEMENT = new IsCoreMatcher<>(new IsVariableElementMatcher<>(), CoreMatcherValidationMessages.IS_VARIABLE_ELEMENT);
/**
* Matcher to check if passed element is a PackageElement.
*/
- public final static IsCoreMatcher IS_PACKAGE_ELEMENT = new IsCoreMatcher<>(new IsPackageElementMatcher(), CoreMatcherValidationMessages.IS_PACKAGE_ELEMENT);
+ public final static IsCoreMatcher IS_PACKAGE_ELEMENT = new IsCoreMatcher<>(new IsPackageElementMatcher<>(), CoreMatcherValidationMessages.IS_PACKAGE_ELEMENT);
/**
* Matcher to check if passed element represents a package.
*/
- public final static IsElementBasedCoreMatcher IS_PACKAGE = new IsElementBasedCoreMatcher<>(new IsPackageMatcher(), CoreMatcherValidationMessages.IS_PACKAGE);
+ public final static IsElementBasedCoreMatcher IS_PACKAGE = new IsElementBasedCoreMatcher<>(new IsPackageMatcher<>(), CoreMatcherValidationMessages.IS_PACKAGE);
/**
* Matcher to check if passed element represents a class.
*/
- public final static IsElementBasedCoreMatcher IS_CLASS = new IsElementBasedCoreMatcher<>(new IsClassMatcher(), CoreMatcherValidationMessages.IS_CLASS);
+ public final static IsElementBasedCoreMatcher IS_CLASS = new IsElementBasedCoreMatcher<>(new IsClassMatcher<>(), CoreMatcherValidationMessages.IS_CLASS);
/**
* Matcher to check if passed element represents an enum.
*/
- public final static IsElementBasedCoreMatcher IS_ENUM = new IsElementBasedCoreMatcher<>(new IsEnumMatcher(), CoreMatcherValidationMessages.IS_ENUM);
+ public final static IsElementBasedCoreMatcher IS_ENUM = new IsElementBasedCoreMatcher<>(new IsEnumMatcher<>(), CoreMatcherValidationMessages.IS_ENUM);
+
+ /**
+ * Matcher to check if passed element represents a record.
+ */
+ public final static IsElementBasedCoreMatcher IS_RECORD = new IsElementBasedCoreMatcher<>(new IsRecordMatcher<>(), CoreMatcherValidationMessages.IS_RECORD);
+
/**
* Matcher to check if passed element represents an interface.
*/
- public final static IsElementBasedCoreMatcher IS_INTERFACE = new IsElementBasedCoreMatcher<>(new IsInterfaceMatcher(), CoreMatcherValidationMessages.IS_INTERFACE);
+ public final static IsElementBasedCoreMatcher IS_INTERFACE = new IsElementBasedCoreMatcher<>(new IsInterfaceMatcher<>(), CoreMatcherValidationMessages.IS_INTERFACE);
/**
* Matcher to check if passed element represents a method.
*/
- public final static IsElementBasedCoreMatcher IS_METHOD = new IsElementBasedCoreMatcher<>(new IsMethodMatcher(), CoreMatcherValidationMessages.IS_METHOD);
+ public final static IsElementBasedCoreMatcher IS_METHOD = new IsElementBasedCoreMatcher<>(new IsMethodMatcher<>(), CoreMatcherValidationMessages.IS_METHOD);
/**
* Matcher to check if passed element represents a constructor.
*/
- public final static IsElementBasedCoreMatcher IS_CONSTRUCTOR = new IsElementBasedCoreMatcher<>(new IsConstructorMatcher(), CoreMatcherValidationMessages.IS_CONSTRUCTOR);
+ public final static IsElementBasedCoreMatcher IS_CONSTRUCTOR = new IsElementBasedCoreMatcher<>(new IsConstructorMatcher<>(), CoreMatcherValidationMessages.IS_CONSTRUCTOR);
/**
* Matcher to check if passed element represents an annotation type.
*/
- public final static IsElementBasedCoreMatcher IS_ANNOTATION_TYPE = new IsElementBasedCoreMatcher<>(new IsAnnotationTypeMatcher(), CoreMatcherValidationMessages.IS_ANNOTATION_TYPE);
+ public final static IsElementBasedCoreMatcher IS_ANNOTATION_TYPE = new IsElementBasedCoreMatcher<>(new IsAnnotationTypeMatcher<>(), CoreMatcherValidationMessages.IS_ANNOTATION_TYPE);
/**
* Matcher to check if passed element represents a field.
*/
- public final static IsElementBasedCoreMatcher IS_FIELD = new IsElementBasedCoreMatcher<>(new IsFieldMatcher(), CoreMatcherValidationMessages.IS_FIELD);
+ public final static IsElementBasedCoreMatcher IS_FIELD = new IsElementBasedCoreMatcher<>(new IsFieldMatcher<>(), CoreMatcherValidationMessages.IS_FIELD);
/**
* Matcher to check if passed element represents a parameter.
*/
- public final static IsElementBasedCoreMatcher IS_PARAMETER = new IsElementBasedCoreMatcher<>(new IsParameterMatcher(), CoreMatcherValidationMessages.IS_PARAMETER);
+ public final static IsElementBasedCoreMatcher IS_PARAMETER = new IsElementBasedCoreMatcher<>(new IsParameterMatcher<>(), CoreMatcherValidationMessages.IS_PARAMETER);
}
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/CoreMatcherValidationMessages.java b/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/CoreMatcherValidationMessages.java
index aafe2a36..a27b3168 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/CoreMatcherValidationMessages.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/corematcher/CoreMatcherValidationMessages.java
@@ -39,6 +39,9 @@ public enum CoreMatcherValidationMessages implements ValidationMessage {
IS_CLASS("CM_IS_CLASS", "Element must ${0} represent a Class"),
IS_ENUM("CM_IS_ENUM", "Element must ${0} represent an enum"),
+
+ IS_RECORD("CM_IS_ENUM", "Element must ${0} represent a record"),
+
IS_INTERFACE("CM_IS_INTERFACE", "Element must ${0} represent an interface"),
IS_METHOD("CM_IS_METHOD", "Element must ${0} represent a method"),
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/matcher/impl/IsRecordMatcher.java b/tools/src/main/java/io/toolisticon/aptk/tools/matcher/impl/IsRecordMatcher.java
new file mode 100644
index 00000000..ec3e479f
--- /dev/null
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/matcher/impl/IsRecordMatcher.java
@@ -0,0 +1,19 @@
+package io.toolisticon.aptk.tools.matcher.impl;
+
+import io.toolisticon.aptk.tools.ElementUtils;
+import io.toolisticon.aptk.tools.matcher.ImplicitMatcher;
+
+import javax.lang.model.element.Element;
+
+
+/**
+ * Implicit matcher that checks if a passed element is an enum.
+ */
+public class IsRecordMatcher implements ImplicitMatcher {
+
+ @Override
+ public boolean check(ELEMENT element) {
+ return ElementUtils.CheckKindOfElement.isRecord(element);
+ }
+
+}
\ No newline at end of file
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ElementWrapper.java b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ElementWrapper.java
index 7f5075fb..99856592 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ElementWrapper.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ElementWrapper.java
@@ -16,6 +16,7 @@
import javax.lang.model.element.TypeElement;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -93,6 +94,19 @@ public boolean hasSimplePackageName(String name) {
return name != null && this.getSimplePackageName().equals(name);
}
+ /**
+ * Gets the module of the wrapped element
+ *
+ * @return an optional containing the wrapped module element
+ */
+ public Optional getModule() {
+ try {
+ Element element = ElementUtils.AccessEnclosingElements.getFirstEnclosingElementOfKind(this.element, ElementKind.valueOf("MODULE"));
+ return element != null ? Optional.of(ModuleElementWrapper.wrap(element)) : Optional.empty();
+ } catch (IllegalArgumentException e) {
+ return Optional.empty();
+ }
+ }
/**
* Gets the simple name of the element.
@@ -175,6 +189,7 @@ public FluentElementFilter filterFlattenedEnclosedElementTree(boolean i
/**
* Gets all wrapped annotations of element.
+ *
* @return a list containing all annotations of the element
*/
public List getAnnotations() {
@@ -347,6 +362,7 @@ public Optional getAnnotationMirror(String annotationTy
/**
* Checks if passed annotation is present.
+ *
* @param annotation the annotation tom check
* @return true if passed annotation is present, otherwise false
*/
@@ -356,6 +372,7 @@ public boolean hasAnnotation(Class extends Annotation> annotation) {
/**
* Checks if passed annotation is present.
+ *
* @param annotationFqn the annotation tom check
* @return true if passed annotation is present, otherwise false
*/
@@ -375,7 +392,7 @@ public Optional getAnnotation(Class annotationType)
return Optional.ofNullable(element.getAnnotation(annotationType));
}
- public Optional> getRepeatableAnnotation (Class extends Annotation> annotationType) {
+ public Optional> getRepeatableAnnotation(Class extends Annotation> annotationType) {
List result = new ArrayList<>();
@@ -520,6 +537,24 @@ public boolean isEnum() {
return ElementUtils.CheckKindOfElement.isEnum(this.element);
}
+ /**
+ * Checks if wrapped element represents a record.
+ *
+ * @return true if wrapped element represents a record, otherwise false
+ */
+ public boolean isRecord() {
+ return ElementUtils.CheckKindOfElement.isRecord(this.element);
+ }
+
+ /**
+ * Checks if wrapped element represents a record.
+ *
+ * @return true if wrapped element represents a record, otherwise false
+ */
+ public boolean isRecordComponent() {
+ return ElementUtils.CheckKindOfElement.isRecordComponent(this.element);
+ }
+
/**
* Checks if wrapped element represents an annotation.
*
@@ -529,21 +564,24 @@ public boolean isAnnotation() {
return ElementUtils.CheckKindOfElement.isAnnotation(this.element);
}
+
/**
* Checks if wrapped element is a repeatable annotation.
+ *
* @return if wrapped element represents a repeatable annotation, otherwise false
*/
- public boolean isRepeatableAnnotation(){
+ public boolean isRepeatableAnnotation() {
return isAnnotation() && hasAnnotation(Repeatable.class);
}
/**
* Gets an Optional containing the wrapped repeatable TypeMirror, if the wrapped represents a repeatable annotation.
+ *
* @return The wrapped repeatable annotation Type Mirror or an empty Optional if it doesn't exist
*/
- public Optional getRepeatableWrapperType(){
+ public Optional getRepeatableWrapperType() {
- if(isRepeatableAnnotation()){
+ if (isRepeatableAnnotation()) {
return Optional.of(getAnnotationMirror(Repeatable.class).get().getAttribute().get().getClassValue());
}
@@ -626,6 +664,14 @@ public boolean isTypeElement() {
return ElementUtils.CastElement.isTypeElement(element);
}
+ /**
+ * Checks if wrapped element is a RecordComponentElement.
+ *
+ * @return true if wrapped element is a RecordComponentElement, otherwise false
+ */
+ public boolean isRecordComponentElement() {
+ return ElementUtils.CastElement.isRecordComponentElement(element);
+ }
/**
* Checks if wrapped element is a ExecutableElement.
@@ -719,4 +765,33 @@ public static ExecutableElementWrapper toExecutableElementWrapper(ElementWrapper
return ExecutableElementWrapper.wrap(ElementUtils.CastElement.castToExecutableElement(wrapper.unwrap()));
}
+
+
+ protected TARGET_TYPE invokeParameterlessMethodOfElement(String interfaceName, String methodName) {
+ return ElementWrapper.invokeParameterlessMethodOfElement(element, interfaceName, methodName);
+ }
+
+ protected static TARGET_TYPE invokeParameterlessMethodOfElement(Object instance, String interfaceName, String methodName) {
+ try {
+ Class> interfaceClass = Class.forName(interfaceName);
+ return (TARGET_TYPE) interfaceClass.getMethod(methodName).invoke(instance);
+ } catch (Exception e) {
+ // This usually shouldn't be thrown since the caller must ensure that the call is available in the used java version
+ throw new IllegalStateException("Couldn't invoke " + interfaceName + "." + methodName + "()", e);
+ }
+ }
+
+ protected boolean hasMethod(String interfaceName, String methodName) {
+ try {
+
+ Class> interfaceClass = Class.forName(interfaceName);
+ Method method = interfaceClass.getMethod(methodName);
+ return true;
+
+ } catch (Exception e) {
+ // This usually shouldn't be thrown since the caller must ensure that the call is available in the used java version
+ return false;
+ }
+ }
+
}
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java
new file mode 100644
index 00000000..b1653979
--- /dev/null
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/ModuleElementWrapper.java
@@ -0,0 +1,378 @@
+package io.toolisticon.aptk.tools.wrapper;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class ModuleElementWrapper extends ElementWrapper {
+
+ private final static String MODULE_ELEMENT_CLASS_NAME = "javax.lang.model.element.ModuleElement";
+ private final static String DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$Directive";
+ private final static String EXPORTS_DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$ExportsDirective";
+
+ private final static String PROVIDES_DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$ProvidesDirective";
+
+ private final static String USES_DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$UsesDirective";
+
+
+ private final static String OPENS_DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$OpensDirective";
+
+ private final static String REQUIRES_DIRECTIVE_CLASS_NAME = MODULE_ELEMENT_CLASS_NAME + "$RequiresDirective";
+
+
+ public abstract static class Directive {
+
+ protected final Object wrappedDirective;
+
+ private Directive(Object wrappedDirective) {
+ this.wrappedDirective = wrappedDirective;
+ }
+
+ public boolean isExportDirective() {
+ return isExportDirective(wrappedDirective);
+ }
+
+ private static boolean isExportDirective(Object instance) {
+ return "EXPORTS".equals(ElementWrapper.invokeParameterlessMethodOfElement(instance, DIRECTIVE_CLASS_NAME, "getKind").toString());
+ }
+
+ public ExportsDirective toExportsDirective() {
+ return (ExportsDirective) this;
+ }
+
+
+ public boolean isOpensDirective() {
+ return isOpensDirective(wrappedDirective);
+ }
+
+ private static boolean isOpensDirective(Object instance) {
+ return "OPENS".equals(ElementWrapper.invokeParameterlessMethodOfElement(instance, DIRECTIVE_CLASS_NAME, "getKind").toString());
+ }
+
+ public OpensDirective toOpensDirective() {
+ return (OpensDirective) this;
+ }
+
+ public boolean isProvidesDirective() {
+ return isProvidesDirective(wrappedDirective);
+ }
+
+ private static boolean isProvidesDirective(Object instance) {
+ return "PROVIDES".equals(ElementWrapper.invokeParameterlessMethodOfElement(instance, DIRECTIVE_CLASS_NAME, "getKind").toString());
+ }
+
+ public ProvidesDirective toProvidesDirective() {
+ return (ProvidesDirective) this;
+ }
+
+ public boolean isRequiresDirective() {
+ return isRequiresDirective(wrappedDirective);
+ }
+
+ private static boolean isRequiresDirective(Object instance) {
+ return "REQUIRES".equals(ElementWrapper.invokeParameterlessMethodOfElement(instance, DIRECTIVE_CLASS_NAME, "getKind").toString());
+ }
+
+ public RequiresDirective toRequiresDirective() {
+ return (RequiresDirective) this;
+ }
+
+ public boolean isUsesDirective() {
+ return isUsesDirective(wrappedDirective);
+ }
+
+ private static boolean isUsesDirective(Object instance) {
+ return "USES".equals(ElementWrapper.invokeParameterlessMethodOfElement(instance, DIRECTIVE_CLASS_NAME, "getKind").toString());
+ }
+
+
+ public UsesDirective toUsesDirective() {
+ return (UsesDirective) this;
+ }
+
+
+ }
+
+
+ public interface ExportsDirective {
+
+ /**
+ * Returns the package being exported.
+ *
+ * @return the package being exported
+ */
+ PackageElementWrapper getPackage();
+
+ /**
+ * Returns the specific modules to which the package is being exported, or null, if the package is exported to all modules which have readability to this module.
+ *
+ * @return the specific modules to which the package is being exported
+ */
+ List getTargetModules();
+
+ }
+
+ static class ExportsDirectiveImpl extends Directive implements ExportsDirective {
+
+
+ private ExportsDirectiveImpl(Object wrappedDirective) {
+ super(wrappedDirective);
+ }
+
+ @Override
+ public PackageElementWrapper getPackage() {
+ return PackageElementWrapper.wrap( ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, EXPORTS_DIRECTIVE_CLASS_NAME, "getPackage"));
+ }
+
+ @Override
+ public List getTargetModules() {
+ return ModuleElementWrapper.wrapList(ElementWrapper.>invokeParameterlessMethodOfElement(wrappedDirective, EXPORTS_DIRECTIVE_CLASS_NAME, "getTargetModules"));
+ }
+
+
+ }
+
+ public interface OpensDirective {
+
+
+ /**
+ * Returns the package being opened.
+ *
+ * @return the package being opened
+ */
+ PackageElementWrapper getPackage();
+
+ /**
+ * Returns the specific modules to which the package is being open or null, if the package is open all modules which have readability to this module.
+ *
+ * @return the specific modules to which the package is being opened
+ */
+ List getTargetModules();
+
+ }
+
+ static class OpensDirectiveImpl extends Directive implements OpensDirective {
+
+
+ private OpensDirectiveImpl(Object wrappedDirective) {
+ super(wrappedDirective);
+ }
+
+ @Override
+ public PackageElementWrapper getPackage() {
+ return PackageElementWrapper.wrap(ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, OPENS_DIRECTIVE_CLASS_NAME, "getPackage"));
+ }
+
+ @Override
+ public List getTargetModules() {
+ return ModuleElementWrapper.wrapList(ElementWrapper.>invokeParameterlessMethodOfElement(wrappedDirective, OPENS_DIRECTIVE_CLASS_NAME, "getTargetModules"));
+ }
+
+ }
+
+ public interface ProvidesDirective {
+
+ /**
+ * Returns the service being provided
+ *
+ * @return the service being provided
+ */
+ TypeElementWrapper getService();
+
+ /**
+ * Returns the implementations of the service being provided.
+ *
+ * @return the implementations of the service being provided
+ */
+ List getImplementations();
+
+ }
+
+ static class ProvidesDirectiveImpl extends Directive implements ProvidesDirective {
+
+
+ private ProvidesDirectiveImpl(Object wrappedDirective) {
+ super(wrappedDirective);
+ }
+
+ @Override
+ public TypeElementWrapper getService() {
+ return TypeElementWrapper.wrap(ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, PROVIDES_DIRECTIVE_CLASS_NAME, "getService"));
+ }
+
+ @Override
+ public List getImplementations() {
+ List implementations = (ElementWrapper.>invokeParameterlessMethodOfElement(wrappedDirective, PROVIDES_DIRECTIVE_CLASS_NAME, "getImplementations"));
+ return implementations.stream().map(TypeElementWrapper::wrap).collect(Collectors.toList());
+ }
+
+ }
+
+ public interface RequiresDirective {
+
+ /**
+ * Returns the module that is required
+ *
+ * @return the module that is required
+ */
+ ModuleElementWrapper getDependency();
+
+
+ /**
+ * Returns whether or not this is a static dependency.
+ *
+ * @return whether or not this is a static dependency.
+ */
+ boolean isStatic();
+
+ /**
+ * Returns whether or not this is a transitive dependency.
+ *
+ * @return whether or not this is a transitive dependency.
+ */
+ boolean isTransitive();
+
+ }
+
+ static class RequiresDirectiveImpl extends Directive implements RequiresDirective {
+
+
+ private RequiresDirectiveImpl(Object wrappedDirective) {
+ super(wrappedDirective);
+ }
+
+ @Override
+ public ModuleElementWrapper getDependency() {
+ return ModuleElementWrapper.wrap(ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, REQUIRES_DIRECTIVE_CLASS_NAME, "getDependency"));
+ }
+
+
+ @Override
+ public boolean isStatic() {
+ return ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, REQUIRES_DIRECTIVE_CLASS_NAME, "isStatic");
+ }
+
+ @Override
+ public boolean isTransitive() {
+ return ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, REQUIRES_DIRECTIVE_CLASS_NAME, "isTransitive");
+ }
+
+ }
+
+ public interface UsesDirective {
+
+ /**
+ * Returns the service being used
+ *
+ * @return the service being used
+ */
+ TypeElementWrapper getService();
+
+
+ }
+
+ public static class UsesDirectiveImpl extends Directive implements UsesDirective {
+
+ private UsesDirectiveImpl(Object wrappedDirective) {
+ super(wrappedDirective);
+ }
+
+ @Override
+ public TypeElementWrapper getService() {
+ return TypeElementWrapper.wrap(ElementWrapper.invokeParameterlessMethodOfElement(wrappedDirective, USES_DIRECTIVE_CLASS_NAME, "getService"));
+ }
+
+
+ }
+
+ private static Directive createDirective(Object instance) {
+ if (instance == null) {
+ return null;
+ }
+
+ if (Directive.isExportDirective(instance)) {
+ return new ExportsDirectiveImpl(instance);
+ } else if (Directive.isOpensDirective(instance)) {
+ return new OpensDirectiveImpl(instance);
+ } else if (Directive.isProvidesDirective(instance)) {
+ return new ProvidesDirectiveImpl(instance);
+ } else if (Directive.isRequiresDirective(instance)) {
+ return new RequiresDirectiveImpl(instance);
+ } else if (Directive.isUsesDirective(instance)) {
+ return new UsesDirectiveImpl(instance);
+ }
+
+ return null;
+ }
+
+ private static List createDirectives(List> directives) {
+
+ return directives.stream().map(e -> createDirective(e)).filter(Objects::nonNull).collect(Collectors.toList());
+
+ }
+
+ private ModuleElementWrapper(Element moduleElement) {
+ super(moduleElement);
+ }
+
+ public String getQualifiedName() {
+ return this.invokeParameterlessMethodOfElement(MODULE_ELEMENT_CLASS_NAME, "getQualifiedName").toString();
+ }
+
+ public boolean hasQualifiedName(String name) {
+ return name != null && this.getQualifiedName().equals(name);
+ }
+
+ public boolean isOpen() {
+ return this.invokeParameterlessMethodOfElement(MODULE_ELEMENT_CLASS_NAME, "isOpen");
+ }
+
+ public boolean isUnnamed() {
+ return this.invokeParameterlessMethodOfElement(MODULE_ELEMENT_CLASS_NAME, "isUnnamed");
+ }
+
+
+ public List getDirectives() {
+ return createDirectives(this.>invokeParameterlessMethodOfElement(MODULE_ELEMENT_CLASS_NAME, "getDirectives"));
+ }
+
+
+ /**
+ * Converts an ElementWrapper to a ModuleElementWrapper id the wrapped element is a ModuleElement
+ *
+ * @param element the element to convert
+ * @return a ModuleElementWrapper wrapping passed ElementWrapper wraps a ModuleElement, otherwise null
+ */
+ public static ModuleElementWrapper toModuleElement(ElementWrapper> element) {
+ return ModuleElementWrapper.wrap(element.unwrap());
+ }
+
+ /**
+ * Wraps the passed element in ModuleElementWrapper if it is a ModuleElement.
+ *
+ * @param element the element to wrap
+ * @return a ModuleElementWrapper wrapping passed element if it is a ModuleElement, otherwise null
+ */
+ public static ModuleElementWrapper wrap(Element element) {
+ return (element == null || !"MODULE".equals(element.getKind().name())) ? null : new ModuleElementWrapper(element);
+ }
+
+ /**
+ * Wraps a List of ModuleElements.
+ * Unfortunately because of backward compatibility it is not possible to limit lists component type to ModuleElement.
+ * So this method will try to wrap all Elements of the passed list. It will drop those not being ModuleElements.
+ *
+ * @param moduleElements A List of ModuleElements.
+ * @return A list of ModuleElementWrapper of elements representing modules that could successfully be wrapped, or an empty list.
+ */
+ public static List wrapList(List moduleElements) {
+ return moduleElements.stream().map(ModuleElementWrapper::wrap).filter(Objects::nonNull).collect(Collectors.toList());
+ }
+
+}
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/RecordComponentElementWrapper.java b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/RecordComponentElementWrapper.java
new file mode 100644
index 00000000..6643952a
--- /dev/null
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/RecordComponentElementWrapper.java
@@ -0,0 +1,81 @@
+package io.toolisticon.aptk.tools.wrapper;
+
+import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import java.util.List;
+
+/**
+ * Wrapper class for RecordComponentElementWrapper.
+ */
+public class RecordComponentElementWrapper extends ElementWrapper {
+
+ private final static String RECORD_COMPONENT_ELEMENT_CLASS_NAME = "javax.lang.model.element.RecordComponentElement";
+
+
+ private RecordComponentElementWrapper(Element recordComponentElement) {
+ super(recordComponentElement);
+ }
+
+ /**
+ * Gets the enclosing records TypeElement
+ *
+ * @return the wrapped enclosing records TypeElement
+ */
+ public TypeElementWrapper getEnclosingRecordTypeElement() {
+ return TypeElementWrapper.wrap((TypeElement) element.getEnclosingElement());
+ }
+
+ /**
+ * Wraps the getAccessor method, but returns a ExecutableElementWrapper
+ * !!! WARNING THERE SEEMS TO BE DIFFERENT BEHAVIOR BETWEEN DIFFERENT JDK DISTRIBUTIONS !!!
+ * So it will look up the accessor manually if necessary
+ * @return the accessors wrapped ExecutableElement, might return null if even the workaround doesn't work
+ */
+ public ExecutableElementWrapper getAccessor() {
+ // safe to call since it's guaranteed that the wrapped element is a RecordComponentElement
+ ExecutableElement executableElement = this.invokeParameterlessMethodOfElement(RECORD_COMPONENT_ELEMENT_CLASS_NAME, "getAccessor");
+
+ return executableElement != null ? ExecutableElementWrapper.wrap(executableElement) : determineAccessorWorkaround();
+ }
+
+ private ExecutableElementWrapper determineAccessorWorkaround(){
+ List results = this.getEnclosingRecordTypeElement().filterEnclosedElements()
+ .applyFilter(AptkCoreMatchers.IS_METHOD)
+ .applyFilter(AptkCoreMatchers.BY_NAME).filterByOneOf(getSimpleName())
+ .applyFilter(AptkCoreMatchers.HAS_NO_PARAMETERS)
+ .getResult();
+
+ return results.isEmpty() ? null : ExecutableElementWrapper.wrap(results.get(0));
+ }
+
+ /**
+ * Re-wraps an ElementWrapper to a RecordComponentElementWrapper.
+ *
+ * @param element the wrapper to re-wrap
+ * @return The RecordComponentElementWrapper or null if the passed ElementWrapper doesn't wrap a RecordComponentElement
+ */
+ public static RecordComponentElementWrapper toRecordComponentElement(ElementWrapper> element) {
+ if (element == null) {
+ return null;
+ }
+ return RecordComponentElementWrapper.wrap(element.unwrap());
+ }
+
+ /**
+ * Wraps an element with the RecordComponentElementWrapper.
+ *
+ * @param element the element to wrap
+ * @return the wrapped element, or null if passed element isn't an RecordComponentElement
+ */
+ public static RecordComponentElementWrapper wrap(Element element) {
+ if (element == null || !"RECORD_COMPONENT".equals(element.getKind().name())) {
+ return null;
+ }
+ return new RecordComponentElementWrapper(element);
+ }
+
+
+}
diff --git a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/TypeElementWrapper.java b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/TypeElementWrapper.java
index 830676e0..dffc6504 100644
--- a/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/TypeElementWrapper.java
+++ b/tools/src/main/java/io/toolisticon/aptk/tools/wrapper/TypeElementWrapper.java
@@ -5,6 +5,7 @@
import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
import io.toolisticon.aptk.tools.fluentfilter.FluentElementFilter;
+import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
@@ -12,6 +13,7 @@
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -23,6 +25,8 @@
*/
public class TypeElementWrapper extends ElementWrapper {
+ private final static String TYPE_ELEMENT_CLASS_NAME = "javax.lang.model.element.TypeElement";
+
/**
* Hidden constructor.
*
@@ -261,6 +265,39 @@ public List getEnumValues() {
: null;
}
+ /**
+ * Returns the record components of this class or interface element in declaration order.
+ * @return the record components, or an empty list if there are none
+ */
+ public List getRecordComponents() {
+
+ // This method is available from Java 16 - the introduction of records, so this check is sufficient to prevent reflective calling of method
+ if (!isRecord()) {
+ return Collections.EMPTY_LIST;
+ }
+ List extends Element> recordComponentElements = this.>invokeParameterlessMethodOfElement(TYPE_ELEMENT_CLASS_NAME, "getRecordComponents");
+
+ return recordComponentElements.stream().map(RecordComponentElementWrapper::wrap).collect(Collectors.toList());
+
+ }
+
+ /**
+ * Returns the permitted classes of this class or interface element in declaration order.
+ * @return the permitted classes, or an empty list if there are none
+ */
+ public List getPermittedSubclasses() {
+
+ // must make sure that method exists, otherwise return the default value
+ if (!hasMethod(TYPE_ELEMENT_CLASS_NAME, "getPermittedSubclasses")) {
+ // TODO MUST CHECK WHAT SHOULD BE RETURNED FOR NON SEALED CLASSES!
+ return Collections.EMPTY_LIST;
+ }
+
+ List typeMirrors = this.>invokeParameterlessMethodOfElement(TYPE_ELEMENT_CLASS_NAME, "getPermittedSubclasses");
+ return typeMirrors.stream().map(TypeMirrorWrapper::wrap).collect(Collectors.toList());
+ }
+
+
/**
* Wraps a TypeElement.
*
diff --git a/tools/src/test/java/io/toolisticon/aptk/tools/BeanUtilsTest.java b/tools/src/test/java/io/toolisticon/aptk/tools/BeanUtilsTest.java
index e5300485..688d80b8 100644
--- a/tools/src/test/java/io/toolisticon/aptk/tools/BeanUtilsTest.java
+++ b/tools/src/test/java/io/toolisticon/aptk/tools/BeanUtilsTest.java
@@ -1,6 +1,5 @@
package io.toolisticon.aptk.tools;
-import com.sun.source.tree.StatementTree;
import io.toolisticon.aptk.cute.APTKUnitTestProcessor;
import io.toolisticon.aptk.tools.corematcher.AptkCoreMatchers;
import io.toolisticon.aptk.tools.fluentfilter.FluentElementFilter;
@@ -10,6 +9,7 @@
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import javax.annotation.processing.ProcessingEnvironment;
@@ -18,7 +18,6 @@
import javax.lang.model.element.VariableElement;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
/**
@@ -322,6 +321,7 @@ public void aptkUnitTest(ProcessingEnvironment processingEnvironment, TypeElemen
}
@Test
+ @Ignore
public void isDefaultNoargConstructor_explicitNoargConstructor() {
unitTestBuilder
@@ -359,9 +359,6 @@ public void aptkUnitTest(ProcessingEnvironment processingEnvironment, TypeElemen
.applyFilter(AptkCoreMatchers.IS_CONSTRUCTOR)
.getResult().get(0);
- List extends StatementTree> statements = ProcessingEnvironmentUtils.getTrees().getTree(constructor).getBody().getStatements();
-
-
MatcherAssert.assertThat("Should return true for explicit constructor that looks like default constructor", BeanUtils.isDefaultNoargConstructor(constructor));
MatcherAssert.assertThat("Should return true for explicit constructor that looks like default constructor", BeanUtils.hasDefaultNoargsConstructor(element));
diff --git a/tools/src/test/java/io/toolisticon/aptk/tools/wrapper/ModulesElementWrapperTest.java b/tools/src/test/java/io/toolisticon/aptk/tools/wrapper/ModulesElementWrapperTest.java
new file mode 100644
index 00000000..63672ce4
--- /dev/null
+++ b/tools/src/test/java/io/toolisticon/aptk/tools/wrapper/ModulesElementWrapperTest.java
@@ -0,0 +1,60 @@
+package io.toolisticon.aptk.tools.wrapper;
+
+import io.toolisticon.aptk.common.ToolingProvider;
+import io.toolisticon.cute.Cute;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import javax.lang.model.element.Element;
+import javax.tools.Tool;
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Unit test for {@link ModuleElementWrapper}.
+ * Only handles wrapping part since this module is build with Java version <9.
+ */
+public class ModulesElementWrapperTest {
+
+ @Test
+ public void test_invalidWrap () {
+ Cute.unitTest().when().unitTestWithoutPassIn(processingEnvironment -> {
+ try{
+ ToolingProvider.setTooling(processingEnvironment);
+
+ MatcherAssert.assertThat(ModuleElementWrapper.wrap((Element) TypeElementWrapper.getByClass(ModulesElementWrapperTest.class).get().unwrap()),Matchers.nullValue());
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+ }).executeTest();
+ }
+
+ @Test
+ public void test_invalidToModuleElement () {
+ Cute.unitTest().when().unitTestWithoutPassIn(processingEnvironment -> {
+ try{
+ ToolingProvider.setTooling(processingEnvironment);
+
+ MatcherAssert.assertThat(ModuleElementWrapper.toModuleElement((ElementWrapper>) TypeElementWrapper.getByClass(ModulesElementWrapperTest.class).get()),Matchers.nullValue());
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+ }).executeTest();
+ }
+
+ @Test
+ public void test_invalidWrapOfList () {
+ Cute.unitTest().when().unitTestWithoutPassIn(processingEnvironment -> {
+ try{
+ ToolingProvider.setTooling(processingEnvironment);
+
+ MatcherAssert.assertThat(ModuleElementWrapper.wrapList(Arrays.asList( TypeElementWrapper.getByClass(ModulesElementWrapperTest.class).get().unwrap())),Matchers.empty());
+ } finally {
+ ToolingProvider.clearTooling();
+ }
+ }).executeTest();
+ }
+
+
+}