langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java
changeset 15385 ee1eebe7e210
parent 15374 fb8f6acf09cc
child 15718 8e54c8e43d38
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jan 23 20:57:40 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jan 23 13:27:24 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, 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
@@ -453,6 +453,19 @@
             case POSTINC:
             case POSTDEC:
                 return getStartPos(((JCUnary) tree).arg);
+            case ANNOTATED_TYPE: {
+                JCAnnotatedType node = (JCAnnotatedType) tree;
+                if (node.annotations.nonEmpty()) {
+                    if (node.underlyingType.hasTag(TYPEARRAY) ||
+                            node.underlyingType.hasTag(SELECT)) {
+                        return getStartPos(node.underlyingType);
+                    } else {
+                        return getStartPos(node.annotations.head);
+                    }
+                } else {
+                    return getStartPos(node.underlyingType);
+                }
+            }
             case NEWCLASS: {
                 JCNewClass node = (JCNewClass)tree;
                 if (node.encl != null)
@@ -560,6 +573,8 @@
                 return getEndPos(((JCUnary) tree).arg, endPosTable);
             case WHILELOOP:
                 return getEndPos(((JCWhileLoop) tree).body, endPosTable);
+            case ANNOTATED_TYPE:
+                return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable);
             case ERRONEOUS: {
                 JCErroneous node = (JCErroneous)tree;
                 if (node.errs != null && node.errs.nonEmpty())
@@ -799,6 +814,8 @@
             return ((JCFieldAccess) tree).sym;
         case TYPEAPPLY:
             return symbol(((JCTypeApply) tree).clazz);
+        case ANNOTATED_TYPE:
+            return symbol(((JCAnnotatedType) tree).underlyingType);
         default:
             return null;
         }
@@ -1036,17 +1053,24 @@
         case NULLCHK:
             return Tree.Kind.OTHER;
 
+        case ANNOTATION:
+            return Tree.Kind.ANNOTATION;
+        case TYPE_ANNOTATION:
+            return Tree.Kind.TYPE_ANNOTATION;
+
         default:
             return null;
         }
     }
 
     /**
-     * Returns the underlying type of the tree if it is annotated type,
-     * or the tree itself otherwise
+     * Returns the underlying type of the tree if it is an annotated type,
+     * or the tree itself otherwise.
      */
     public static JCExpression typeIn(JCExpression tree) {
         switch (tree.getTag()) {
+        case ANNOTATED_TYPE:
+            return ((JCAnnotatedType)tree).underlyingType;
         case IDENT: /* simple names */
         case TYPEIDENT: /* primitive name */
         case SELECT: /* qualified name */
@@ -1054,20 +1078,55 @@
         case WILDCARD: /* wild cards */
         case TYPEPARAMETER: /* type parameters */
         case TYPEAPPLY: /* parameterized types */
+        case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */
             return tree;
         default:
             throw new AssertionError("Unexpected type tree: " + tree);
         }
     }
 
+    /* Return the inner-most type of a type tree.
+     * For an array that contains an annotated type, return that annotated type.
+     * TODO: currently only used by Pretty. Describe behavior better.
+     */
     public static JCTree innermostType(JCTree type) {
-        switch (type.getTag()) {
-        case TYPEARRAY:
-            return innermostType(((JCArrayTypeTree)type).elemtype);
-        case WILDCARD:
-            return innermostType(((JCWildcard)type).inner);
-        default:
-            return type;
+        JCTree lastAnnotatedType = null;
+        JCTree cur = type;
+        loop: while (true) {
+            switch (cur.getTag()) {
+            case TYPEARRAY:
+                lastAnnotatedType = null;
+                cur = ((JCArrayTypeTree)cur).elemtype;
+                break;
+            case WILDCARD:
+                lastAnnotatedType = null;
+                cur = ((JCWildcard)cur).inner;
+                break;
+            case ANNOTATED_TYPE:
+                lastAnnotatedType = cur;
+                cur = ((JCAnnotatedType)cur).underlyingType;
+                break;
+            default:
+                break loop;
+            }
+        }
+        if (lastAnnotatedType!=null) {
+            return lastAnnotatedType;
+        } else {
+            return cur;
         }
     }
+
+    private static class TypeAnnotationFinder extends TreeScanner {
+        public boolean foundTypeAnno = false;
+        public void visitAnnotation(JCAnnotation tree) {
+            foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION);
+        }
+    }
+
+    public static boolean containsTypeAnnotation(JCTree e) {
+        TypeAnnotationFinder finder = new TypeAnnotationFinder();
+        finder.scan(e);
+        return finder.foundTypeAnno;
+    }
 }