langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationMaker.java
changeset 11870 bc664cc5f2a0
parent 11863 ac6277ec304a
parent 11869 d659025e6575
child 11871 08f8da764f8f
equal deleted inserted replaced
11863:ac6277ec304a 11870:bc664cc5f2a0
     1 /*
       
     2  * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.apt.mirror.declaration;
       
    27 
       
    28 
       
    29 import java.util.HashMap;
       
    30 import java.util.Map;
       
    31 
       
    32 import com.sun.mirror.declaration.*;
       
    33 import com.sun.tools.apt.mirror.AptEnv;
       
    34 import com.sun.tools.javac.code.*;
       
    35 import com.sun.tools.javac.code.Symbol.*;
       
    36 import com.sun.tools.javac.util.Context;
       
    37 import com.sun.tools.javac.util.Name;
       
    38 import com.sun.tools.javac.main.JavaCompiler;
       
    39 
       
    40 /**
       
    41  * Utilities for constructing and caching declarations.
       
    42  */
       
    43 @SuppressWarnings("deprecation")
       
    44 public class DeclarationMaker {
       
    45 
       
    46     private AptEnv env;
       
    47     private Context context;
       
    48     private JavaCompiler javacompiler;
       
    49     private static final Context.Key<DeclarationMaker> declarationMakerKey =
       
    50             new Context.Key<DeclarationMaker>();
       
    51 
       
    52     public static DeclarationMaker instance(Context context) {
       
    53         DeclarationMaker instance = context.get(declarationMakerKey);
       
    54         if (instance == null) {
       
    55             instance = new DeclarationMaker(context);
       
    56         }
       
    57         return instance;
       
    58     }
       
    59 
       
    60     private DeclarationMaker(Context context) {
       
    61         context.put(declarationMakerKey, this);
       
    62         env = AptEnv.instance(context);
       
    63         this.context = context;
       
    64         this.javacompiler = JavaCompiler.instance(context);
       
    65     }
       
    66 
       
    67 
       
    68 
       
    69     // Cache of package declarations
       
    70     private Map<PackageSymbol, PackageDeclaration> packageDecls =
       
    71             new HashMap<PackageSymbol, PackageDeclaration>();
       
    72 
       
    73     /**
       
    74      * Returns the package declaration for a package symbol.
       
    75      */
       
    76     public PackageDeclaration getPackageDeclaration(PackageSymbol p) {
       
    77         PackageDeclaration res = packageDecls.get(p);
       
    78         if (res == null) {
       
    79             res = new PackageDeclarationImpl(env, p);
       
    80             packageDecls.put(p, res);
       
    81         }
       
    82         return res;
       
    83     }
       
    84 
       
    85     /**
       
    86      * Returns the package declaration for the package with the given name.
       
    87      * Name is fully-qualified, or "" for the unnamed package.
       
    88      * Returns null if package declaration not found.
       
    89      */
       
    90     public PackageDeclaration getPackageDeclaration(String name) {
       
    91         PackageSymbol p = null;
       
    92         if (name.equals("") )
       
    93             p = env.symtab.unnamedPackage;
       
    94         else {
       
    95             if (!isJavaName(name))
       
    96                 return null;
       
    97             Symbol s = nameToSymbol(name, false);
       
    98             if (s instanceof PackageSymbol) {
       
    99                 p = (PackageSymbol) s;
       
   100                 if (!p.exists())
       
   101                     return null;
       
   102             } else
       
   103                 return null;
       
   104         }
       
   105         return getPackageDeclaration(p);
       
   106     }
       
   107 
       
   108     // Cache of type declarations
       
   109     private Map<ClassSymbol, TypeDeclaration> typeDecls =
       
   110             new HashMap<ClassSymbol, TypeDeclaration>();
       
   111 
       
   112     /**
       
   113      * Returns the type declaration for a class symbol.
       
   114      * Forces completion, and returns null on error.
       
   115      */
       
   116     public TypeDeclaration getTypeDeclaration(ClassSymbol c) {
       
   117         long flags = AptEnv.getFlags(c);        // forces symbol completion
       
   118         if (c.kind == Kinds.ERR) {
       
   119             return null;
       
   120         }
       
   121         TypeDeclaration res = typeDecls.get(c);
       
   122         if (res == null) {
       
   123             if ((flags & Flags.ANNOTATION) != 0) {
       
   124                 res = new AnnotationTypeDeclarationImpl(env, c);
       
   125             } else if ((flags & Flags.INTERFACE) != 0) {
       
   126                 res = new InterfaceDeclarationImpl(env, c);
       
   127             } else if ((flags & Flags.ENUM) != 0) {
       
   128                 res = new EnumDeclarationImpl(env, c);
       
   129             } else {
       
   130                 res = new ClassDeclarationImpl(env, c);
       
   131             }
       
   132             typeDecls.put(c, res);
       
   133         }
       
   134         return res;
       
   135     }
       
   136 
       
   137     /**
       
   138      * Returns the type declaration for the type with the given canonical name.
       
   139      * Returns null if type declaration not found.
       
   140      */
       
   141     public TypeDeclaration getTypeDeclaration(String name) {
       
   142         if (!isJavaName(name))
       
   143             return null;
       
   144         Symbol s = nameToSymbol(name, true);
       
   145         if (s instanceof ClassSymbol) {
       
   146             ClassSymbol c = (ClassSymbol) s;
       
   147             return getTypeDeclaration(c);
       
   148         } else
       
   149             return null;
       
   150     }
       
   151 
       
   152     /**
       
   153      * Returns a symbol given the type's or packages's canonical name,
       
   154      * or null if the name isn't found.
       
   155      */
       
   156     private Symbol nameToSymbol(String name, boolean classCache) {
       
   157         Symbol s = null;
       
   158         Name nameName = env.names.fromString(name);
       
   159         if (classCache)
       
   160             s = env.symtab.classes.get(nameName);
       
   161         else
       
   162             s = env.symtab.packages.get(nameName);
       
   163 
       
   164         if (s != null && s.exists())
       
   165             return s;
       
   166 
       
   167         s = javacompiler.resolveIdent(name);
       
   168         if (s.kind == Kinds.ERR  )
       
   169             return null;
       
   170 
       
   171         if (s.kind == Kinds.PCK)
       
   172             s.complete();
       
   173 
       
   174         return s;
       
   175     }
       
   176 
       
   177     // Cache of method and constructor declarations
       
   178     private Map<MethodSymbol, ExecutableDeclaration> executableDecls =
       
   179             new HashMap<MethodSymbol, ExecutableDeclaration>();
       
   180 
       
   181     /**
       
   182      * Returns the method or constructor declaration for a method symbol.
       
   183      */
       
   184     ExecutableDeclaration getExecutableDeclaration(MethodSymbol m) {
       
   185         ExecutableDeclaration res = executableDecls.get(m);
       
   186         if (res == null) {
       
   187             if (m.isConstructor()) {
       
   188                 res = new ConstructorDeclarationImpl(env, m);
       
   189             } else if (isAnnotationTypeElement(m)) {
       
   190                 res = new AnnotationTypeElementDeclarationImpl(env, m);
       
   191             } else {
       
   192                 res = new MethodDeclarationImpl(env, m);
       
   193             }
       
   194             executableDecls.put(m, res);
       
   195         }
       
   196         return res;
       
   197     }
       
   198 
       
   199     // Cache of field declarations
       
   200     private Map<VarSymbol, FieldDeclaration> fieldDecls =
       
   201             new HashMap<VarSymbol, FieldDeclaration>();
       
   202 
       
   203     /**
       
   204      * Returns the field declaration for a var symbol.
       
   205      */
       
   206     FieldDeclaration getFieldDeclaration(VarSymbol v) {
       
   207         FieldDeclaration res = fieldDecls.get(v);
       
   208         if (res == null) {
       
   209             if (hasFlag(v, Flags.ENUM)) {
       
   210                 res = new EnumConstantDeclarationImpl(env, v);
       
   211             } else {
       
   212                 res = new FieldDeclarationImpl(env, v);
       
   213             }
       
   214             fieldDecls.put(v, res);
       
   215         }
       
   216         return res;
       
   217     }
       
   218 
       
   219     /**
       
   220      * Returns a parameter declaration.
       
   221      */
       
   222     ParameterDeclaration getParameterDeclaration(VarSymbol v) {
       
   223         return new ParameterDeclarationImpl(env, v);
       
   224     }
       
   225 
       
   226     /**
       
   227      * Returns a type parameter declaration.
       
   228      */
       
   229     public TypeParameterDeclaration getTypeParameterDeclaration(TypeSymbol t) {
       
   230         return new TypeParameterDeclarationImpl(env, t);
       
   231     }
       
   232 
       
   233     /**
       
   234      * Returns an annotation.
       
   235      */
       
   236     AnnotationMirror getAnnotationMirror(Attribute.Compound a, Declaration decl) {
       
   237         return new AnnotationMirrorImpl(env, a, decl);
       
   238     }
       
   239 
       
   240 
       
   241     /**
       
   242      * Is a string a valid Java identifier?
       
   243      */
       
   244     public static boolean isJavaIdentifier(String id) {
       
   245         return javax.lang.model.SourceVersion.isIdentifier(id);
       
   246     }
       
   247 
       
   248     public static boolean isJavaName(String name) {
       
   249         for(String id: name.split("\\.")) {
       
   250             if (! isJavaIdentifier(id))
       
   251                 return false;
       
   252         }
       
   253         return true;
       
   254     }
       
   255 
       
   256     /**
       
   257      * Is a method an annotation type element?
       
   258      * It is if it's declared in an annotation type.
       
   259      */
       
   260     private static boolean isAnnotationTypeElement(MethodSymbol m) {
       
   261         return hasFlag(m.enclClass(), Flags.ANNOTATION);
       
   262     }
       
   263 
       
   264     /**
       
   265      * Does a symbol have a given flag?
       
   266      */
       
   267     private static boolean hasFlag(Symbol s, long flag) {
       
   268         return AptEnv.hasFlag(s, flag);
       
   269     }
       
   270 }