514N/A/*
936N/A * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
514N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
514N/A *
514N/A * This code is free software; you can redistribute it and/or modify it
514N/A * under the terms of the GNU General Public License version 2 only, as
514N/A * published by the Free Software Foundation.
514N/A *
514N/A * This code is distributed in the hope that it will be useful, but WITHOUT
514N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
514N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
514N/A * version 2 for more details (a copy is included in the LICENSE file that
514N/A * accompanied this code).
514N/A *
514N/A * You should have received a copy of the GNU General Public License version
514N/A * 2 along with this work; if not, write to the Free Software Foundation,
514N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
514N/A *
553N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
553N/A * or visit www.oracle.com if you need additional information or have any
553N/A * questions.
514N/A */
514N/A
514N/A/*
514N/A * @test
936N/A * @bug 6449781 6930508
514N/A * @summary Test that reported names of anonymous classes are non-null.
514N/A * @author Joseph D. Darcy
698N/A * @library ../../../lib
698N/A * @build JavacTestingAbstractProcessor TestAnonSourceNames
671N/A * @compile -processor TestAnonSourceNames TestAnonClassNames.java
514N/A * @run main TestAnonClassNames
514N/A */
514N/A
514N/A/*
514N/A * This test operates in phases to test retrieving the qualified name
514N/A * of anonymous classes from type elements modeling the anonymous
514N/A * class. The type elements are generated using both source files and
514N/A * class files as the basis of constructing the elements.
514N/A *
514N/A * Source files will be tested by the @compile line which runs
514N/A * TestAnonSourceNames as an annotation processor over this file.
514N/A *
514N/A * Class files are tested by the @run command on this type. This
514N/A * class gets the names of classes with different nesting kinds,
514N/A * including anonymous classes, and then invokes the compiler with an
514N/A * annotation processor having the class files names as inputs. The
514N/A * compiler is invoked via the javax.tools mechanism.
514N/A */
514N/A
514N/Aimport java.lang.annotation.*;
514N/Aimport javax.lang.model.element.*;
514N/Aimport javax.annotation.processing.*;
514N/Aimport javax.lang.model.SourceVersion;
514N/Aimport javax.lang.model.element.*;
514N/Aimport javax.lang.model.util.*;
514N/Aimport javax.tools.*;
514N/Aimport java.util.*;
514N/A
514N/Aimport static java.lang.annotation.RetentionPolicy.*;
514N/Aimport static javax.lang.model.element.NestingKind.*;
514N/Aimport static javax.lang.model.util.ElementFilter.*;
514N/Aimport static javax.tools.Diagnostic.Kind.*;
514N/Aimport static javax.tools.StandardLocation.*;
514N/A
514N/A@Nesting(TOP_LEVEL)
514N/Apublic class TestAnonClassNames {
514N/A @Nesting(MEMBER)
514N/A static class MemberClass1{}
514N/A
514N/A @Nesting(MEMBER)
514N/A class MemberClass2{}
514N/A
514N/A @Nesting(MEMBER)
514N/A class Win$$AtVegas { } // Class with funny name.
514N/A
514N/A public static void main(String... argv) {
514N/A @Nesting(LOCAL)
514N/A class LocalClass{};
514N/A
721N/A Object o = new /*@Nesting(ANONYMOUS)*/ Object() { // An anonymous annotated class
514N/A public String toString() {
514N/A return "I have no name!";
514N/A }
514N/A };
514N/A
514N/A Class<?>[] classes = {
514N/A MemberClass1.class,
514N/A MemberClass2.class,
514N/A LocalClass.class,
514N/A Win$$AtVegas.class,
514N/A o.getClass(),
514N/A TestAnonClassNames.class,
514N/A };
514N/A
936N/A List<String> names = new ArrayList<String>();
514N/A for(Class<?> clazz : classes) {
514N/A String name = clazz.getName();
721N/A Nesting anno = clazz.getAnnotation(Nesting.class);
514N/A System.out.format("%s is %s%n",
514N/A clazz.getName(),
721N/A anno == null ? "(unset/ANONYMOUS)" : anno.value());
514N/A testClassName(name);
936N/A names.add(name);
514N/A }
936N/A
936N/A // test all names together
936N/A testClassNames(names);
936N/A
936N/A if (errors > 0)
936N/A throw new RuntimeException(errors + " errors occurred");
514N/A }
514N/A
514N/A /**
514N/A * Perform annotation processing on the class file name and verify
514N/A * the existence of different flavors of class names when the
514N/A * input classes are modeled as elements.
514N/A */
514N/A static void testClassName(String className) {
936N/A testClassNames(Arrays.asList(className));
936N/A }
936N/A
936N/A /**
936N/A * Perform annotation processing on a list of class file names and verify
936N/A * the existence of different flavors of class names when the
936N/A * input classes are modeled as elements.
936N/A */
936N/A static void testClassNames(List<String> classNames) {
936N/A System.out.println("test: " + classNames);
514N/A
535N/A List<String> options = new ArrayList<String>();
514N/A options.add("-proc:only");
514N/A options.add("-classpath");
514N/A options.add(System.getProperty("test.classes"));
514N/A
936N/A JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
514N/A JavaCompiler.CompilationTask compileTask =
514N/A javaCompiler.getTask(null, // Output
514N/A null, // File manager
514N/A null, // Diagnostics
514N/A options,
514N/A classNames,
514N/A null); // Sources
535N/A List<Processor> processors = new ArrayList<Processor>();
514N/A processors.add(new ClassNameProber());
514N/A compileTask.setProcessors(processors);
514N/A Boolean goodResult = compileTask.call();
514N/A if (!goodResult) {
936N/A error("Errors found during compile.");
514N/A }
514N/A }
936N/A
936N/A static int errors = 0;
936N/A
936N/A static void error(String msg) {
936N/A System.out.println("Error: " + msg);
936N/A errors++;
936N/A }
514N/A}
514N/A
514N/A@Retention(RUNTIME)
514N/A@interface Nesting {
514N/A NestingKind value();
514N/A}
514N/A
514N/A/**
514N/A * Probe at the various kinds of names of a type element.
514N/A */
698N/Aclass ClassNameProber extends JavacTestingAbstractProcessor {
514N/A public ClassNameProber(){super();}
514N/A
514N/A private boolean classesFound=false;
514N/A
514N/A public boolean process(Set<? extends TypeElement> annotations,
514N/A RoundEnvironment roundEnv) {
514N/A if (!roundEnv.processingOver()) {
514N/A for(TypeElement typeElt : typesIn(roundEnv.getRootElements())) {
514N/A classesFound = true;
514N/A
514N/A // Verify different names are non-null; an NPE will
514N/A // result in failed compile status being reported.
514N/A NestingKind nestingKind = typeElt.getNestingKind();
514N/A System.out.printf("\tSimple name: ''%s''\tQualified Name: ''%s''\tKind ''%s''\tNesting ''%s''%n",
514N/A typeElt.getSimpleName().toString(),
514N/A typeElt.getQualifiedName().toString(),
514N/A typeElt.getKind().toString(),
514N/A nestingKind.toString());
721N/A Nesting anno = typeElt.getAnnotation(Nesting.class);
721N/A if ((anno == null ? NestingKind.ANONYMOUS : anno.value()) != nestingKind) {
514N/A throw new RuntimeException("Mismatch of expected and reported nesting kind.");
514N/A }
514N/A }
514N/A
514N/A }
514N/A
514N/A if (!classesFound) {
514N/A throw new RuntimeException("Error: no classes processed.");
514N/A }
514N/A return true;
514N/A }
514N/A}