On Thu, 5 Dec 2024 16:24:29 GMT, Scott Marlow <d...@openjdk.org> wrote:

> I am getting the `Duplication annotation for class` error as mentioned in 
> https://hibernate.atlassian.net/browse/HHH-18901.  The current error message 
> does not include the application class name (e.g. container) that the 
> specified annotation is unexpectedly duplicated.  This pull request is for 
> including the class name that has the (duplicate) annotation.

I made a quick test for this, but you might not want to include it if you aim 
to backport this improvement to LTS releases as it uses the recently-finalized 
ClassFile API.


/*
 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 8345614
 * @summary Ensure message for duplicated annotations mention problematic class
 * @library /test/lib
 */

import java.lang.annotation.AnnotationFormatError;
import java.lang.classfile.Annotation;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassTransform;
import java.lang.classfile.FieldTransform;
import java.lang.classfile.MethodTransform;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import 
java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import java.lang.constant.ClassDesc;
import java.nio.file.Path;
import java.util.List;

import jdk.test.lib.ByteCodeLoader;

public class DuplicateAnnotationsTest {
    public static void main(String... args) throws Throwable {
        ClassFile cf = ClassFile.of();
        Path annoDuplicatedClass = 
Path.of(System.getProperty("test.classes")).resolve("AnnotationDuplicated.class");

        Annotation annotation = 
Annotation.of(ClassDesc.of("java.lang.Deprecated"));
        RuntimeVisibleAnnotationsAttribute rvaa = 
RuntimeVisibleAnnotationsAttribute.of(
                List.of(annotation, annotation)
        );
        List<ClassTransform> transforms = List.of(
                ClassTransform.endHandler(cob -> cob.with(rvaa)),
                ClassTransform.transformingFields(FieldTransform.endHandler(fb 
-> fb.with(rvaa))),
                
ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> 
mb.with(rvaa))),
                
ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> mb.with(
                        RuntimeVisibleParameterAnnotationsAttribute.of(
                                List.of(List.of(annotation, annotation))
                        )
                )))
        );

        var cm = cf.parse(annoDuplicatedClass);
        for (var ct : transforms) {
            var c = ByteCodeLoader.load("AnnotationDuplicated", 
cf.transformClass(cm, ct));
            try {
                c.getAnnotation(Deprecated.class);
                var field = c.getDeclaredField("field");
                field.getAnnotation(Deprecated.class);
                var ctor = c.getDeclaredConstructor(int.class);
                ctor.getAnnotation(Deprecated.class);
                ctor.getParameters()[0].getAnnotation(Deprecated.class);
            } catch (ReflectiveOperationException ex) {
                throw new AssertionError(ex);
            } catch (AnnotationFormatError err) {
                var m = err.getMessage();
                if (!m.contains("Deprecated") || 
!m.contains("AnnotationDuplicated"))
                    throw new AssertionError("Class not mentioned: " + m);
            }
        }
    }
}

// Duplicate annotations on class, field, method (constructor), method parameter
class AnnotationDuplicated {
    int field;
    AnnotationDuplicated(int arg) {}
}


Test confirms that error messages for duplicated annotations now mention both 
the duplicated annotation type and the type where the duplication happens.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/22581#issuecomment-2521703511

Reply via email to