/*
 * Copyright (c) 2010, 2021, 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 6930507
 * @summary Symbols for anonymous and local classes made too late for use by java tree API
 * @modules jdk.compiler
 */

import java.io.*;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.tools.Diagnostic;
import static javax.lang.model.util.ElementFilter.*;

import com.sun.source.tree.*;
import com.sun.source.util.*;

@SupportedOptions({"test", "last"})
@SupportedAnnotationTypes("*")
public class TestGetElement extends AbstractProcessor {
    public static void main(String... args) throws Exception {
        new TestGetElement().run();
    }

    public TestGetElement() { }

    public void run() throws Exception {
        final String testSrc = System.getProperty("test.src");
        final String testClasses = System.getProperty("test.classes");
        final String myClassName = getClass().getName();
        final String mySrc = new File(testSrc, myClassName + ".java").getPath();

        final int NUM_TESTS = 90; // #decls in this source file
        for (int i = 1; i <= NUM_TESTS; i++) {
            System.err.println("test " + i);
            File testDir = new File("test" + i);
            File classesDir = new File(testDir, "classes");
            classesDir.mkdirs();
            String[] args = {
                "-d", classesDir.getPath(),
                "-processorpath", testClasses,
                "-processor", myClassName,
                "-proc:only",
                "-Atest=" + i,
                "-Alast=" + (i == NUM_TESTS),
                mySrc
            };

//            System.err.println("compile: " + Arrays.asList(args));

            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            int rc = com.sun.tools.javac.Main.compile(args, pw);
            pw.close();
            String out = sw.toString();
            if (out != null)
                System.err.println(out);
            if (rc != 0) {
                System.err.println("compilation failed: rc=" + rc);
                errors++;
            }
        }

        if (errors > 0)
            throw new Exception(errors + " errors occurred");
    }


    int errors;

    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnvironment)
    {
        if (roundEnvironment.processingOver())
            return true;

        Map<String,String> options = processingEnv.getOptions();
        int test = Integer.parseInt(options.get("test"));
        boolean _last = Boolean.parseBoolean(options.get("last"));

        Trees trees = Trees.instance(processingEnv);
        Scanner scanner = new Scanner(trees, _last);
        int nelems = 0;
        for (TypeElement e : typesIn(roundEnvironment.getRootElements())) {
            nelems += scanner.scan(trees.getPath(e), test);
        }

        Messager m = processingEnv.getMessager();
        int EXPECT = 1;
        if (nelems != EXPECT) {
            m.printError("Unexpected number of elements found: " + nelems + " expected: " + EXPECT);
        }
        return true;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }

    class Scanner extends TreePathScanner<Integer,Integer> {
        final Trees trees;
        final boolean last;
        int count;

        Scanner(Trees trees, boolean last) {
            this.trees = trees;
            this.last = last;
        }

        @Override
        public Integer visitClass(ClassTree tree, Integer test) {
            return reduce(check(test), super.visitClass(tree, test));
        }

        @Override
        public Integer visitMethod(MethodTree tree, Integer test) {
            return reduce(check(test), super.visitMethod(tree, test));
        }

        @Override
        public Integer visitVariable(VariableTree tree, Integer test) {
            return reduce(check(test), super.visitVariable(tree, test));
        }

        @Override
        public Integer reduce(Integer i1, Integer i2) {
            if (i1 == null || i1.intValue() == 0)
                return i2;
            if (i2 == null || i2.intValue() == 0)
                return i1;
            return (i1 + i2);
        }

        int check(int test) {
            count++;

            if (count != test)
                return 0;

            TreePath p = getCurrentPath();
            Element e = trees.getElement(p);

            String text = p.getLeaf().toString().replaceAll("\\s+", " ").trim();
            int MAXLEN = 40;
            if (text.length() > MAXLEN)
                text = text.substring(0, MAXLEN - 3) + "...";

            System.err.println(String.format("%3d: %-" + MAXLEN + "s -- %s",
                    count, text,
                    (e == null ? "null" : e.getKind() + " " + e)));

            Messager m = processingEnv.getMessager();
            if (e == null) {
                m.printError("Null element found for " + text);
                return 0;
            }

            if (last && !e.getSimpleName().contentEquals("last")) {
                m.printError("Unexpected name in last test: "
                             + e.getSimpleName() + ", expected: last");
            }

            return 1;
        }
    }

    // following are all fodder for the test

    class MemberClass {
        class NestedMemberClass { }
    }

    {
        class InnerClassInInit { }
        Object o = new Object() { };
    }

    TestGetElement(TestGetElement unused) {
        class InnerClassInConstr { }
        Object o = new Object() { };
    }

    void m() {
        class InnerClassInMethod { }
        Object o = new Object() { };

        class C {
            class MemberClass {
                class NestedMemberClass { }
            }

            {
                class InnerClassInInit { }
                Object o = new Object() { };
            }

            C(Object unused) {
                class InnerClassInConstr { }
                Object o = new Object() { };
            }

            void m() {
                class InnerClassInMethod { }
                Object o = new Object() { };
            }
        }
    }

    int last; // this name is verified by the test to make sure that all decls are checked
}
