diff --git a/oo-equivalence/equivalence-assertions/src/main/java/com/pragmaticobjects/oo/equivalence/assertions/AssertImplements.java b/oo-equivalence/equivalence-assertions/src/main/java/com/pragmaticobjects/oo/equivalence/assertions/AssertImplements.java new file mode 100644 index 00000000..8a3a7444 --- /dev/null +++ b/oo-equivalence/equivalence-assertions/src/main/java/com/pragmaticobjects/oo/equivalence/assertions/AssertImplements.java @@ -0,0 +1,58 @@ +/*- + * =========================================================================== + * equivalence-assertions + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Copyright (C) 2019 - 2022 Kapralov Sergey + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================ + */ +package com.pragmaticobjects.oo.equivalence.assertions; + +import io.vavr.collection.List; +import org.assertj.core.api.Assertions; + +import java.lang.reflect.Type; +import java.util.stream.Collectors; + +public class AssertImplements implements Assertion { + private final Class source; + private final String typeName; + + public AssertImplements(Class source, String typeName) { + this.source = source; + this.typeName = typeName; + } + + @Override + public final void check() throws Exception { + Assertions.assertThat( + List.of(source.getGenericInterfaces()) + .exists(iface -> iface.getTypeName().equals(typeName)) + ) + .withFailMessage( + "Expecting %s to implement %s, found %s", + source.getName(), + typeName, + List.of(source.getGenericInterfaces()).map(Type::getTypeName).collect(Collectors.joining(", ")) + ) + .isTrue(); + + } +} diff --git a/oo-equivalence/equivalence-codegen/src/main/java/com/pragmaticobjects/oo/equivalence/codegen/ii/IIMarkAsEObject.java b/oo-equivalence/equivalence-codegen/src/main/java/com/pragmaticobjects/oo/equivalence/codegen/ii/IIMarkAsEObject.java index 0477c145..50628403 100644 --- a/oo-equivalence/equivalence-codegen/src/main/java/com/pragmaticobjects/oo/equivalence/codegen/ii/IIMarkAsEObject.java +++ b/oo-equivalence/equivalence-codegen/src/main/java/com/pragmaticobjects/oo/equivalence/codegen/ii/IIMarkAsEObject.java @@ -38,12 +38,16 @@ import net.bytebuddy.jar.asm.signature.SignatureWriter; import net.bytebuddy.pool.TypePool; import net.bytebuddy.utility.OpenedClassReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * * @author skapral */ public class IIMarkAsEObject implements InstrumentationIteration { + private final static Logger log = LoggerFactory.getLogger(IIMarkAsEObject.class); + @Override public final DynamicType.Builder apply(DynamicType.Builder builder, TypeDescription typeDescription) { @@ -77,23 +81,40 @@ public void visit(int version, int access, String name, String signature, String superName = "com/pragmaticobjects/oo/equivalence/base/EObject"; if (signature != null) { SignatureWriter sw = new SignatureWriter() { - private boolean typeArg = false; + private boolean superclass = false; @Override public void visitFormalTypeParameter(String name) { - typeArg = true; + log.debug("visitFormalTypeParameter: " + name + " " + superclass); + superclass = false; super.visitFormalTypeParameter(name); } @Override public SignatureVisitor visitSuperclass() { - typeArg = false; + log.debug("visitSuperclass: " + superclass); + superclass = true; return super.visitSuperclass(); } + @Override + public void visitEnd() { + log.debug("visitEnd: " + superclass); + superclass = false; + super.visitEnd(); + } + + @Override + public SignatureVisitor visitInterface() { + log.debug("visitInterface: " + superclass); + superclass = false; + return super.visitInterface(); + } + @Override public void visitClassType(String name) { - if (!typeArg && "java/lang/Object".equals(name)) { + log.debug("visitClassType: " + name + " " + superclass); + if (superclass && "java/lang/Object".equals(name)) { name = "com/pragmaticobjects/oo/equivalence/base/EObject"; } super.visitClassType(name); diff --git a/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTest.java b/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTest.java new file mode 100644 index 00000000..06d4ce1b --- /dev/null +++ b/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTest.java @@ -0,0 +1,37 @@ +/*- + * =========================================================================== + * equivalence-itests + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Copyright (C) 2019 - 2022 Kapralov Sergey + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================ + */ +package com.pragmaticobjects.oo.equivalence.itests.classes; + + +import io.vavr.collection.Map; + + +public class GenericsTest implements GenericsTestIface> { + @Override + public final Map get() { + return null; + } +} diff --git a/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTestIface.java b/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTestIface.java new file mode 100644 index 00000000..27422de3 --- /dev/null +++ b/oo-equivalence/equivalence-itests/src/main/java/com/pragmaticobjects/oo/equivalence/itests/classes/GenericsTestIface.java @@ -0,0 +1,30 @@ +/*- + * =========================================================================== + * equivalence-itests + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Copyright (C) 2019 - 2022 Kapralov Sergey + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * ============================================================================ + */ +package com.pragmaticobjects.oo.equivalence.itests.classes; + +public interface GenericsTestIface { + T get(); +} diff --git a/oo-equivalence/equivalence-itests/src/test/java/com/pragmaticobjects/oo/equivalence/itests/TestClassesWithGenerics.java b/oo-equivalence/equivalence-itests/src/test/java/com/pragmaticobjects/oo/equivalence/itests/TestClassesWithGenerics.java index 7b7a2123..ee73bd43 100644 --- a/oo-equivalence/equivalence-itests/src/test/java/com/pragmaticobjects/oo/equivalence/itests/TestClassesWithGenerics.java +++ b/oo-equivalence/equivalence-itests/src/test/java/com/pragmaticobjects/oo/equivalence/itests/TestClassesWithGenerics.java @@ -25,9 +25,8 @@ */ package com.pragmaticobjects.oo.equivalence.itests; -import com.pragmaticobjects.oo.equivalence.assertions.AssertTwoObjectsEquality; -import com.pragmaticobjects.oo.equivalence.assertions.TestCase; -import com.pragmaticobjects.oo.equivalence.assertions.TestsSuite; +import com.pragmaticobjects.oo.equivalence.assertions.*; +import com.pragmaticobjects.oo.equivalence.itests.classes.GenericsTest; import com.pragmaticobjects.oo.equivalence.itests.classes.TreeNode; /** @@ -76,6 +75,15 @@ public TestClassesWithGenerics() { new TreeNode<>(1, new TreeNode<>(2), new TreeNode<>(4)), false ) + ), + new TestCase( + "Issue 3 regression test: see https://github.com/skapral/pragmaticobjects/issues/3", + new AssertAssertionPasses( + new AssertImplements( + GenericsTest.class, + "com.pragmaticobjects.oo.equivalence.itests.classes.GenericsTestIface>" + ) + ) ) ); }