From 8efa12b240a5f0f78efe7ea8783761c0fecd198d Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Tue, 22 Mar 2022 10:22:53 +0100 Subject: [PATCH 01/11] lets see what fails --- .../support/compiler/jdt/ReferenceBuilder.java | 4 ++++ .../ConstructorCallTest.java | 14 +++++++++++++- .../constructorcall-type/TestHttpStub.java | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/constructorcall-type/TestHttpStub.java diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index db3d17b6010..3a410fc9fe4 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -449,6 +449,10 @@ CtExecutableReference getExecutableReference(AllocationExpression allocat CtExecutableReference ref; if (allocationExpression.binding != null) { ref = getExecutableReference(allocationExpression.binding); + // in some cases the binding is not null but points wrong to object type see #4643 + if (ref.getType().equals(ref.getFactory().Type().objectType()) && allocationExpression.resolvedType != null) { + ref.setType(getTypeReference(allocationExpression.resolvedType)); + } } else { ref = jdtTreeBuilder.getFactory().Core().createExecutableReference(); ref.setSimpleName(CtExecutableReference.CONSTRUCTOR_NAME); diff --git a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java index 0ce63e7e7ab..b45fa7e5c3e 100644 --- a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java +++ b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; - +import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import spoon.Launcher; @@ -221,4 +221,16 @@ private CtTypeReference getConstructorCallTypeFrom(String simpleName, String assert calls.size() == 1; return calls.get(0).getExecutable().getType(); } + + @Test + public void testConstructorCorrectTyped() { + // no constructorcall from the input has the simple object type in noclasspathmode + Launcher launcher = new Launcher(); + launcher.getEnvironment().setNoClasspath(true); + launcher.addInputResource("./src/test/resources/constructorcall-type/TestHttpStub.java"); + CtModel model = launcher.buildModel(); + for (CtConstructorCall ctConstructorCall : model.getElements(new TypeFilter<>(CtConstructorCall.class))) { + assertThat(ctConstructorCall.getType(), CoreMatchers.not(ctConstructorCall.getFactory().Type().objectType())); + } + } } diff --git a/src/test/resources/constructorcall-type/TestHttpStub.java b/src/test/resources/constructorcall-type/TestHttpStub.java new file mode 100644 index 00000000000..64cd58c75a6 --- /dev/null +++ b/src/test/resources/constructorcall-type/TestHttpStub.java @@ -0,0 +1,16 @@ +package com.test; + +public class TestHttpStub { + + private static com.ibm.ws.webservices.engine.description.OperationDesc _getInformationOperation0 = + null; + + private static void _getInformationOperation0() { + com.ibm.ws.webservices.engine.description.FaultDesc[] _faults0 = + new com.ibm.ws.webservices.engine.description[] {}; + _getInformationOperation0 = + new com.ibm.ws.webservices.engine.description.OperationDesc("getVerificationInformation", + new javax.xml.namespace.QName("", "getVerificationInformation"), _faults0, + "http://com.gov//getVerificationInformation");//constructor call which needs to be transformed + } +} From 89ad81a1937f63b930963486550b60c03a9ed1d6 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Tue, 22 Mar 2022 10:30:35 +0100 Subject: [PATCH 02/11] up --- src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index 3a410fc9fe4..fce7e7326ca 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -452,6 +452,8 @@ CtExecutableReference getExecutableReference(AllocationExpression allocat // in some cases the binding is not null but points wrong to object type see #4643 if (ref.getType().equals(ref.getFactory().Type().objectType()) && allocationExpression.resolvedType != null) { ref.setType(getTypeReference(allocationExpression.resolvedType)); + ref.getExecutableDeclaration().setType(getTypeReference(allocationExpression.resolvedType)); + ref.setDeclaringType(getTypeReference(allocationExpression.resolvedType)); } } else { ref = jdtTreeBuilder.getFactory().Core().createExecutableReference(); From 7c42a3e7ec7a88223976fcec50efed9d61248499 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Tue, 22 Mar 2022 10:32:23 +0100 Subject: [PATCH 03/11] up --- .../test/constructorcallnewclass/ConstructorCallTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java index b45fa7e5c3e..de718eb4770 100644 --- a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java +++ b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java @@ -22,7 +22,6 @@ import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; -import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import spoon.Launcher; @@ -42,6 +41,7 @@ import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; @@ -229,8 +229,10 @@ public void testConstructorCorrectTyped() { launcher.getEnvironment().setNoClasspath(true); launcher.addInputResource("./src/test/resources/constructorcall-type/TestHttpStub.java"); CtModel model = launcher.buildModel(); - for (CtConstructorCall ctConstructorCall : model.getElements(new TypeFilter<>(CtConstructorCall.class))) { - assertThat(ctConstructorCall.getType(), CoreMatchers.not(ctConstructorCall.getFactory().Type().objectType())); + for (CtConstructorCall ctConstructorCall : model + .getElements(new TypeFilter<>(CtConstructorCall.class))) { + assertThat(ctConstructorCall.getExecutable().getType().getSimpleName(), not(equalTo("Object"))); + assertThat(ctConstructorCall.getType(), not(ctConstructorCall.getFactory().Type().objectType())); } } } From e5e076d391f9b93569c87ad65e7f45e705f3ca20 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Thu, 7 Apr 2022 14:19:38 +0200 Subject: [PATCH 04/11] up --- .../java/spoon/NoClasspathWorkaround.java | 18 +++++++++ .../compiler/jdt/ReferenceBuilder.java | 39 ++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/main/java/spoon/NoClasspathWorkaround.java diff --git a/src/main/java/spoon/NoClasspathWorkaround.java b/src/main/java/spoon/NoClasspathWorkaround.java new file mode 100644 index 00000000000..21efb4c79be --- /dev/null +++ b/src/main/java/spoon/NoClasspathWorkaround.java @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2019 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon. + */ +package spoon; + +/** + * This annotation is used to mark a workaround for the lack of a correct classpath so called noclasspathmode. + *

+ * Workarounds for missing informations are marked with this annotation. These methods are not part of the Spoon API and best effort. + * With any new jdt version the workaround can be removed or no longer working. + */ +public @interface NoClasspathWorkaround { + +} diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index fce7e7326ca..24e3350a94c 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -61,6 +61,7 @@ import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; import org.eclipse.jdt.internal.compiler.lookup.VoidTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; +import spoon.NoClasspathWorkaround; import spoon.reflect.code.CtLambda; import spoon.reflect.declaration.CtModule; import spoon.reflect.declaration.CtPackage; @@ -450,17 +451,16 @@ CtExecutableReference getExecutableReference(AllocationExpression allocat if (allocationExpression.binding != null) { ref = getExecutableReference(allocationExpression.binding); // in some cases the binding is not null but points wrong to object type see #4643 - if (ref.getType().equals(ref.getFactory().Type().objectType()) && allocationExpression.resolvedType != null) { - ref.setType(getTypeReference(allocationExpression.resolvedType)); - ref.getExecutableDeclaration().setType(getTypeReference(allocationExpression.resolvedType)); - ref.setDeclaringType(getTypeReference(allocationExpression.resolvedType)); + if (isIncorrectlyBoundExecutableInNoClasspath(ref, allocationExpression)) { + adjustExecutableAccordingToResolvedType(ref, allocationExpression); } } else { ref = jdtTreeBuilder.getFactory().Core().createExecutableReference(); ref.setSimpleName(CtExecutableReference.CONSTRUCTOR_NAME); ref.setDeclaringType(getTypeReference(null, allocationExpression.type)); - final List> parameters = new ArrayList<>(allocationExpression.argumentTypes.length); + final List> parameters = + new ArrayList<>(allocationExpression.argumentTypes.length); for (TypeBinding b : allocationExpression.argumentTypes) { parameters.add(getTypeReference(b, true)); } @@ -472,6 +472,35 @@ CtExecutableReference getExecutableReference(AllocationExpression allocat return ref; } + /** + * Checks if the given executable reference is incorrectly bound to the Object type and noclasspath is set. + * @param ref the executable reference to check + * @param allocationExpression the allocation expression that contains the executable reference of jdt. + * @return true if the executable reference is incorrectly bound to the Object type and noclasspath is set. + */ + @NoClasspathWorkaround + private boolean isIncorrectlyBoundExecutableInNoClasspath(CtExecutableReference ref, + AllocationExpression allocationExpression) { + boolean noClasspath = ref.getFactory().getEnvironment().getNoClasspath(); + return noClasspath && ref.getType().equals(ref.getFactory().Type().objectType()) + && allocationExpression.resolvedType != null; + } + + /** + * Adjusts the executable reference according to the resolved type. This is needed because the binding is not correct in no classpath. + * @param ref the executable reference to adjust + * @param allocationExpression the allocation expression that contains the executable reference of jdt. + */ + @NoClasspathWorkaround + @SuppressWarnings("unchecked") + private void adjustExecutableAccordingToResolvedType(CtExecutableReference ref, + AllocationExpression allocationExpression) { + CtTypeReference resolvedTypeRef = getTypeReference(allocationExpression.resolvedType); + ref.setType(resolvedTypeRef); + ref.getExecutableDeclaration().setType(resolvedTypeRef); + ref.setDeclaringType(resolvedTypeRef); + } + CtExecutableReference getExecutableReference(MessageSend messageSend) { if (messageSend.binding != null) { return getExecutableReference(messageSend.binding); From 4046389226cbeee9dd344b5e3797341135e9efdb Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Thu, 7 Apr 2022 14:22:02 +0200 Subject: [PATCH 05/11] rename type --- .../spoon/test/constructorcallnewclass/ConstructorCallTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java index de718eb4770..095bac609ca 100644 --- a/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java +++ b/src/test/java/spoon/test/constructorcallnewclass/ConstructorCallTest.java @@ -227,7 +227,7 @@ public void testConstructorCorrectTyped() { // no constructorcall from the input has the simple object type in noclasspathmode Launcher launcher = new Launcher(); launcher.getEnvironment().setNoClasspath(true); - launcher.addInputResource("./src/test/resources/constructorcall-type/TestHttpStub.java"); + launcher.addInputResource("./src/test/resources/constructorcall-type/ConstructorCallWithTypesNotOnClasspath.java"); CtModel model = launcher.buildModel(); for (CtConstructorCall ctConstructorCall : model .getElements(new TypeFilter<>(CtConstructorCall.class))) { From 9e6ae5854ef7201ddfa79d07ed7d66312df5b520 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Thu, 7 Apr 2022 14:28:39 +0200 Subject: [PATCH 06/11] up --- .../ConstructorCallWithTypesNotOnClasspath.java | 7 +++++++ .../constructorcall-type/TestHttpStub.java | 16 ---------------- 2 files changed, 7 insertions(+), 16 deletions(-) create mode 100644 src/test/resources/constructorcall-type/ConstructorCallWithTypesNotOnClasspath.java delete mode 100644 src/test/resources/constructorcall-type/TestHttpStub.java diff --git a/src/test/resources/constructorcall-type/ConstructorCallWithTypesNotOnClasspath.java b/src/test/resources/constructorcall-type/ConstructorCallWithTypesNotOnClasspath.java new file mode 100644 index 00000000000..dc7ea9222e4 --- /dev/null +++ b/src/test/resources/constructorcall-type/ConstructorCallWithTypesNotOnClasspath.java @@ -0,0 +1,7 @@ +class ConstructorCallWithTypesNotOnClasspath { + public static void main(String[] args) { + type.not.on.Classpath instanceOfTypeNotOnClasspath = null; + new another.type.not.on.Classpath(instanceOfTypeNotOnClasspath); + } +} + diff --git a/src/test/resources/constructorcall-type/TestHttpStub.java b/src/test/resources/constructorcall-type/TestHttpStub.java deleted file mode 100644 index 64cd58c75a6..00000000000 --- a/src/test/resources/constructorcall-type/TestHttpStub.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.test; - -public class TestHttpStub { - - private static com.ibm.ws.webservices.engine.description.OperationDesc _getInformationOperation0 = - null; - - private static void _getInformationOperation0() { - com.ibm.ws.webservices.engine.description.FaultDesc[] _faults0 = - new com.ibm.ws.webservices.engine.description[] {}; - _getInformationOperation0 = - new com.ibm.ws.webservices.engine.description.OperationDesc("getVerificationInformation", - new javax.xml.namespace.QName("", "getVerificationInformation"), _faults0, - "http://com.gov//getVerificationInformation");//constructor call which needs to be transformed - } -} From 66cfec8884e043220ee8b97a74b25833af07290a Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Thu, 7 Apr 2022 14:31:00 +0200 Subject: [PATCH 07/11] checkstyle --- src/main/java/spoon/NoClasspathWorkaround.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/spoon/NoClasspathWorkaround.java b/src/main/java/spoon/NoClasspathWorkaround.java index 21efb4c79be..07014602717 100644 --- a/src/main/java/spoon/NoClasspathWorkaround.java +++ b/src/main/java/spoon/NoClasspathWorkaround.java @@ -14,5 +14,4 @@ * With any new jdt version the workaround can be removed or no longer working. */ public @interface NoClasspathWorkaround { - } From 719015f6c93c822a5da2323667910f1aaab8c094 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Wed, 13 Apr 2022 10:51:00 +0200 Subject: [PATCH 08/11] add reason field --- src/main/java/spoon/NoClasspathWorkaround.java | 1 + .../java/spoon/support/compiler/jdt/ReferenceBuilder.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/spoon/NoClasspathWorkaround.java b/src/main/java/spoon/NoClasspathWorkaround.java index 07014602717..319b6f42e80 100644 --- a/src/main/java/spoon/NoClasspathWorkaround.java +++ b/src/main/java/spoon/NoClasspathWorkaround.java @@ -14,4 +14,5 @@ * With any new jdt version the workaround can be removed or no longer working. */ public @interface NoClasspathWorkaround { + String reason(); } diff --git a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java index 24e3350a94c..16a5b8af3c5 100644 --- a/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/ReferenceBuilder.java @@ -478,7 +478,7 @@ CtExecutableReference getExecutableReference(AllocationExpression allocat * @param allocationExpression the allocation expression that contains the executable reference of jdt. * @return true if the executable reference is incorrectly bound to the Object type and noclasspath is set. */ - @NoClasspathWorkaround + @NoClasspathWorkaround(reason = "https://github.com/INRIA/spoon/issues/4643") private boolean isIncorrectlyBoundExecutableInNoClasspath(CtExecutableReference ref, AllocationExpression allocationExpression) { boolean noClasspath = ref.getFactory().getEnvironment().getNoClasspath(); @@ -491,7 +491,7 @@ private boolean isIncorrectlyBoundExecutableInNoClasspath(CtExecutableReference< * @param ref the executable reference to adjust * @param allocationExpression the allocation expression that contains the executable reference of jdt. */ - @NoClasspathWorkaround + @NoClasspathWorkaround(reason = "https://github.com/INRIA/spoon/issues/4643") @SuppressWarnings("unchecked") private void adjustExecutableAccordingToResolvedType(CtExecutableReference ref, AllocationExpression allocationExpression) { From 9c8f1d19de9c326112cdb74f22f96bfc110d60b2 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Wed, 13 Apr 2022 10:55:05 +0200 Subject: [PATCH 09/11] tabs --- src/main/java/spoon/NoClasspathWorkaround.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/spoon/NoClasspathWorkaround.java b/src/main/java/spoon/NoClasspathWorkaround.java index 319b6f42e80..cc339be223f 100644 --- a/src/main/java/spoon/NoClasspathWorkaround.java +++ b/src/main/java/spoon/NoClasspathWorkaround.java @@ -14,5 +14,5 @@ * With any new jdt version the workaround can be removed or no longer working. */ public @interface NoClasspathWorkaround { - String reason(); + String reason(); } From 2c128608caf9e11ff08d202fa97365a713de3c9c Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Wed, 13 Apr 2022 11:03:45 +0200 Subject: [PATCH 10/11] doc --- src/main/java/spoon/NoClasspathWorkaround.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/spoon/NoClasspathWorkaround.java b/src/main/java/spoon/NoClasspathWorkaround.java index cc339be223f..a860e010288 100644 --- a/src/main/java/spoon/NoClasspathWorkaround.java +++ b/src/main/java/spoon/NoClasspathWorkaround.java @@ -14,5 +14,10 @@ * With any new jdt version the workaround can be removed or no longer working. */ public @interface NoClasspathWorkaround { + /** + * The reason why this workaround is needed. This is used for documentation purposes. + * A link to the originale issue is sufficient. + * @return the reason why this workaround is needed + */ String reason(); } From 1991591ba18b3c839c2a12baea9411dea9d4fa70 Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Wed, 15 Jun 2022 03:10:31 +0200 Subject: [PATCH 11/11] move package --- .../experimental/NoClasspathWorkaround.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/spoon/experimental/NoClasspathWorkaround.java diff --git a/src/main/java/spoon/experimental/NoClasspathWorkaround.java b/src/main/java/spoon/experimental/NoClasspathWorkaround.java new file mode 100644 index 00000000000..0b9bd504cc8 --- /dev/null +++ b/src/main/java/spoon/experimental/NoClasspathWorkaround.java @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2019 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon. + */ +package spoon.experimental; + +import spoon.support.Experimental; +import spoon.support.Internal; + +/** + * This annotation is used to mark a workaround for the lack of a correct classpath so called noclasspathmode. + *

+ * Workarounds for missing informations are marked with this annotation. These methods are not part of the Spoon API and best effort. + * With any new jdt version the workaround can be removed or no longer working. + */ +@Experimental +@Internal +public @interface NoClasspathWorkaround { + /** + * The reason why this workaround is needed. This is used for documentation purposes. + * A link to the originale issue is sufficient. + * @return the reason why this workaround is needed + */ + String reason(); +}