6930507: Symbols for anonymous and local classes made too late for use by java tree API

Mon, 06 Sep 2010 12:55:09 -0700

author
jjg
date
Mon, 06 Sep 2010 12:55:09 -0700
changeset 672
ea54372637a5
parent 671
68e765b1e9ed
child 673
7ae4016c5938

6930507: Symbols for anonymous and local classes made too late for use by java tree API
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/javac/api/JavacTrees.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/tree/TreeInfo.java file | annotate | diff | comparison | revisions
test/tools/javac/api/TestGetElement.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/model/element/TestAnonClassNames.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/model/element/TestAnonSourceNames.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Fri Sep 03 12:00:21 2010 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Sep 06 12:55:09 2010 -0700
     1.3 @@ -45,6 +45,7 @@
     1.4  import com.sun.source.util.SourcePositions;
     1.5  import com.sun.source.util.TreePath;
     1.6  import com.sun.source.util.Trees;
     1.7 +import com.sun.tools.javac.code.Flags;
     1.8  import com.sun.tools.javac.code.Symbol.ClassSymbol;
     1.9  import com.sun.tools.javac.code.Symbol.TypeSymbol;
    1.10  import com.sun.tools.javac.code.Symbol;
    1.11 @@ -189,8 +190,24 @@
    1.12      }
    1.13  
    1.14      public Element getElement(TreePath path) {
    1.15 -        Tree t = path.getLeaf();
    1.16 -        return TreeInfo.symbolFor((JCTree) t);
    1.17 +        JCTree tree = (JCTree) path.getLeaf();
    1.18 +        Symbol sym = TreeInfo.symbolFor(tree);
    1.19 +        if (sym == null && TreeInfo.isDeclaration(tree)) {
    1.20 +            for (TreePath p = path; p != null; p = p.getParentPath()) {
    1.21 +                JCTree t = (JCTree) p.getLeaf();
    1.22 +                if (t.getTag() == JCTree.CLASSDEF) {
    1.23 +                    JCClassDecl ct = (JCClassDecl) t;
    1.24 +                    if (ct.sym != null) {
    1.25 +                        if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
    1.26 +                            attr.attribClass(ct.pos(), ct.sym);
    1.27 +                            sym = TreeInfo.symbolFor(tree);
    1.28 +                        }
    1.29 +                        break;
    1.30 +                    }
    1.31 +                }
    1.32 +            }
    1.33 +        }
    1.34 +        return sym;
    1.35      }
    1.36  
    1.37      public TypeMirror getTypeMirror(TreePath path) {
     2.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Fri Sep 03 12:00:21 2010 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Mon Sep 06 12:55:09 2010 -0700
     2.3 @@ -637,6 +637,18 @@
     2.4          }
     2.5      }
     2.6  
     2.7 +    public static boolean isDeclaration(JCTree node) {
     2.8 +        node = skipParens(node);
     2.9 +        switch (node.getTag()) {
    2.10 +        case JCTree.CLASSDEF:
    2.11 +        case JCTree.METHODDEF:
    2.12 +        case JCTree.VARDEF:
    2.13 +            return true;
    2.14 +        default:
    2.15 +            return false;
    2.16 +        }
    2.17 +    }
    2.18 +
    2.19      /** If this tree is an identifier or a field, return its symbol,
    2.20       *  otherwise return null.
    2.21       */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/tools/javac/api/TestGetElement.java	Mon Sep 06 12:55:09 2010 -0700
     3.3 @@ -0,0 +1,235 @@
     3.4 +/*
     3.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + *
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + *
    3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.23 + * or visit www.oracle.com if you need additional information or have any
    3.24 + * questions.
    3.25 + */
    3.26 +
    3.27 +/*
    3.28 + * @test
    3.29 + * @bug 6930507
    3.30 + * @summary Symbols for anonymous and local classes made too late for use by java tree API
    3.31 + */
    3.32 +
    3.33 +import java.io.*;
    3.34 +import java.util.*;
    3.35 +import javax.annotation.processing.*;
    3.36 +import javax.lang.model.SourceVersion;
    3.37 +import javax.lang.model.element.*;
    3.38 +import javax.tools.Diagnostic;
    3.39 +import static javax.lang.model.util.ElementFilter.*;
    3.40 +
    3.41 +import com.sun.source.tree.*;
    3.42 +import com.sun.source.util.*;
    3.43 +
    3.44 +@SupportedOptions({"test", "last"})
    3.45 +@SupportedAnnotationTypes("*")
    3.46 +public class TestGetElement extends AbstractProcessor {
    3.47 +    public static void main(String... args) throws Exception {
    3.48 +        new TestGetElement().run();
    3.49 +    }
    3.50 +
    3.51 +    public TestGetElement() { }
    3.52 +
    3.53 +    public void run() throws Exception {
    3.54 +        final String testSrc = System.getProperty("test.src");
    3.55 +        final String testClasses = System.getProperty("test.classes");
    3.56 +        final String myClassName = getClass().getName();
    3.57 +        final String mySrc = new File(testSrc, myClassName + ".java").getPath();
    3.58 +
    3.59 +        final int NUM_TESTS = 90; // #decls in this source file
    3.60 +        for (int i = 1; i <= NUM_TESTS; i++) {
    3.61 +            System.err.println("test " + i);
    3.62 +            File testDir = new File("test" + i);
    3.63 +            File classesDir = new File(testDir, "classes");
    3.64 +            classesDir.mkdirs();
    3.65 +            String[] args = {
    3.66 +                "-d", classesDir.getPath(),
    3.67 +                "-processorpath", testClasses,
    3.68 +                "-processor", myClassName,
    3.69 +                "-proc:only",
    3.70 +                "-Atest=" + i,
    3.71 +                "-Alast=" + (i == NUM_TESTS),
    3.72 +                mySrc
    3.73 +            };
    3.74 +
    3.75 +//            System.err.println("compile: " + Arrays.asList(args));
    3.76 +
    3.77 +            StringWriter sw = new StringWriter();
    3.78 +            PrintWriter pw = new PrintWriter(sw);
    3.79 +            int rc = com.sun.tools.javac.Main.compile(args, pw);
    3.80 +            pw.close();
    3.81 +            String out = sw.toString();
    3.82 +            if (out != null)
    3.83 +                System.err.println(out);
    3.84 +            if (rc != 0) {
    3.85 +                System.err.println("compilation failed: rc=" + rc);
    3.86 +                errors++;
    3.87 +            }
    3.88 +        }
    3.89 +
    3.90 +        if (errors > 0)
    3.91 +            throw new Exception(errors + " errors occurred");
    3.92 +    }
    3.93 +
    3.94 +
    3.95 +    int errors;
    3.96 +
    3.97 +    public boolean process(Set<? extends TypeElement> annotations,
    3.98 +                           RoundEnvironment roundEnvironment)
    3.99 +    {
   3.100 +        if (roundEnvironment.processingOver())
   3.101 +            return true;
   3.102 +
   3.103 +        Map<String,String> options = processingEnv.getOptions();
   3.104 +        int test = Integer.parseInt(options.get("test"));
   3.105 +        boolean _last = Boolean.parseBoolean(options.get("last"));
   3.106 +
   3.107 +        Trees trees = Trees.instance(processingEnv);
   3.108 +        Scanner scanner = new Scanner(trees, _last);
   3.109 +        int nelems = 0;
   3.110 +        for (TypeElement e : typesIn(roundEnvironment.getRootElements())) {
   3.111 +            nelems += scanner.scan(trees.getPath(e), test);
   3.112 +        }
   3.113 +
   3.114 +        Messager m = processingEnv.getMessager();
   3.115 +        int EXPECT = 1;
   3.116 +        if (nelems != EXPECT) {
   3.117 +            m.printMessage(Diagnostic.Kind.ERROR,
   3.118 +                    "Unexpected number of elements found: " + nelems + " expected: " + EXPECT);
   3.119 +        }
   3.120 +        return true;
   3.121 +    }
   3.122 +
   3.123 +    @Override
   3.124 +    public SourceVersion getSupportedSourceVersion() {
   3.125 +        return SourceVersion.latest();
   3.126 +    }
   3.127 +
   3.128 +    class Scanner extends TreePathScanner<Integer,Integer> {
   3.129 +        final Trees trees;
   3.130 +        final boolean last;
   3.131 +        int count;
   3.132 +
   3.133 +        Scanner(Trees trees, boolean last) {
   3.134 +            this.trees = trees;
   3.135 +            this.last = last;
   3.136 +        }
   3.137 +
   3.138 +        @Override
   3.139 +        public Integer visitClass(ClassTree tree, Integer test) {
   3.140 +            return reduce(check(test), super.visitClass(tree, test));
   3.141 +        }
   3.142 +
   3.143 +        @Override
   3.144 +        public Integer visitMethod(MethodTree tree, Integer test) {
   3.145 +            return reduce(check(test), super.visitMethod(tree, test));
   3.146 +        }
   3.147 +
   3.148 +        @Override
   3.149 +        public Integer visitVariable(VariableTree tree, Integer test) {
   3.150 +            return reduce(check(test), super.visitVariable(tree, test));
   3.151 +        }
   3.152 +
   3.153 +        @Override
   3.154 +        public Integer reduce(Integer i1, Integer i2) {
   3.155 +            if (i1 == null || i1.intValue() == 0)
   3.156 +                return i2;
   3.157 +            if (i2 == null || i2.intValue() == 0)
   3.158 +                return i1;
   3.159 +            return (i1 + i2);
   3.160 +        }
   3.161 +
   3.162 +        int check(int test) {
   3.163 +            count++;
   3.164 +
   3.165 +            if (count != test)
   3.166 +                return 0;
   3.167 +
   3.168 +            TreePath p = getCurrentPath();
   3.169 +            Element e = trees.getElement(p);
   3.170 +
   3.171 +            String text = p.getLeaf().toString().replaceAll("\\s+", " ").trim();
   3.172 +            int MAXLEN = 40;
   3.173 +            if (text.length() > MAXLEN)
   3.174 +                text = text.substring(0, MAXLEN - 3) + "...";
   3.175 +
   3.176 +            System.err.println(String.format("%3d: %-" + MAXLEN + "s -- %s",
   3.177 +                    count, text,
   3.178 +                    (e == null ? "null" : e.getKind() + " " + e)));
   3.179 +
   3.180 +            Messager m = processingEnv.getMessager();
   3.181 +            if (e == null) {
   3.182 +                m.printMessage(Diagnostic.Kind.ERROR, "Null element found for " + text);
   3.183 +                return 0;
   3.184 +            }
   3.185 +
   3.186 +            if (last && !e.getSimpleName().contentEquals("last")) {
   3.187 +                m.printMessage(Diagnostic.Kind.ERROR, "Unexpected name in last test: "
   3.188 +                        + e.getSimpleName() + ", expected: last");
   3.189 +            }
   3.190 +
   3.191 +            return 1;
   3.192 +        }
   3.193 +    }
   3.194 +
   3.195 +    // following are all fodder for the test
   3.196 +
   3.197 +    class MemberClass {
   3.198 +        class NestedMemberClass { }
   3.199 +    }
   3.200 +
   3.201 +    {
   3.202 +        class InnerClassInInit { }
   3.203 +        Object o = new Object() { };
   3.204 +    }
   3.205 +
   3.206 +    TestGetElement(TestGetElement unused) {
   3.207 +        class InnerClassInConstr { }
   3.208 +        Object o = new Object() { };
   3.209 +    }
   3.210 +
   3.211 +    void m() {
   3.212 +        class InnerClassInMethod { }
   3.213 +        Object o = new Object() { };
   3.214 +
   3.215 +        class C {
   3.216 +            class MemberClass {
   3.217 +                class NestedMemberClass { }
   3.218 +            }
   3.219 +
   3.220 +            {
   3.221 +                class InnerClassInInit { }
   3.222 +                Object o = new Object() { };
   3.223 +            }
   3.224 +
   3.225 +            C(Object unused) {
   3.226 +                class InnerClassInConstr { }
   3.227 +                Object o = new Object() { };
   3.228 +            }
   3.229 +
   3.230 +            void m() {
   3.231 +                class InnerClassInMethod { }
   3.232 +                Object o = new Object() { };
   3.233 +            }
   3.234 +        }
   3.235 +    }
   3.236 +
   3.237 +    int last; // this name is verified by the test to make sure that all decls are checked
   3.238 +}
     4.1 --- a/test/tools/javac/processing/model/element/TestAnonClassNames.java	Fri Sep 03 12:00:21 2010 -0700
     4.2 +++ b/test/tools/javac/processing/model/element/TestAnonClassNames.java	Mon Sep 06 12:55:09 2010 -0700
     4.3 @@ -27,8 +27,7 @@
     4.4   * @summary Test that reported names of anonymous classes are non-null.
     4.5   * @author  Joseph D. Darcy
     4.6   * @build TestAnonSourceNames
     4.7 - * @compile/fail -processor TestAnonSourceNames TestAnonClassNames.java
     4.8 - * @build TestAnonClassNames
     4.9 + * @compile -processor TestAnonSourceNames TestAnonClassNames.java
    4.10   * @run main TestAnonClassNames
    4.11   */
    4.12  
    4.13 @@ -40,10 +39,6 @@
    4.14   *
    4.15   * Source files will be tested by the @compile line which runs
    4.16   * TestAnonSourceNames as an annotation processor over this file.
    4.17 - * This compile line is expected to fail until 6930507 is fixed.  Once
    4.18 - * bug 6930507 is fixed, the "@compile/fail -processor ..." and
    4.19 - * following "@build..." steps can be replaced with a single "@compile
    4.20 - * -processor ..." directive.
    4.21   *
    4.22   * Class files are tested by the @run command on this type.  This
    4.23   * class gets the names of classes with different nesting kinds,
     5.1 --- a/test/tools/javac/processing/model/element/TestAnonSourceNames.java	Fri Sep 03 12:00:21 2010 -0700
     5.2 +++ b/test/tools/javac/processing/model/element/TestAnonSourceNames.java	Mon Sep 06 12:55:09 2010 -0700
     5.3 @@ -67,7 +67,7 @@
     5.4                       Element element = trees.getElement(trees.getPath(cu, node));
     5.5             if (element == null) {
     5.6                 processingEnv.getMessager().printMessage(ERROR,
     5.7 -                                                        "No element retreived for node named ''" +
     5.8 +                                                        "No element retrieved for node named ''" +
     5.9                                                          node.getSimpleName() + "''.");
    5.10             } else {
    5.11  

mercurial