1d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein/*
2d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * Copyright (C) 2011 Google Inc.
3d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein *
4d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
5d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * you may not use this file except in compliance with the License.
6d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * You may obtain a copy of the License at
7d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein *
8d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * http://www.apache.org/licenses/LICENSE-2.0
9d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein *
10d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
11d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
12d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * See the License for the specific language governing permissions and
14d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * limitations under the License.
15d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein */
16d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
17d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinpackage com.google.doclava;
18d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
196ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport com.google.doclava.parser.JavaLexer;
206ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport com.google.doclava.parser.JavaParser;
216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
22d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport org.antlr.runtime.ANTLRFileStream;
23d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport org.antlr.runtime.CommonToken;
246ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport org.antlr.runtime.CommonTokenStream;
256ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport org.antlr.runtime.RecognitionException;
266ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport org.antlr.runtime.debug.ParseTreeBuilder;
27d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport org.antlr.runtime.tree.ParseTree;
28d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport org.antlr.runtime.tree.Tree;
29d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
306ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport java.io.IOException;
316ba612efffba42bec102ac58a1540496158f747eAndrew Sappersteinimport java.util.ArrayList;
327c80d0e9086eef289d323661977cbfb771d95a2aMorad Abdelrahmanimport java.util.Collections;
33d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.HashMap;
34d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.HashSet;
35d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.Iterator;
36d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
37d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein/**
38d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * InfoBuilder parses an individual file and builds Doclava
39d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * objects out of the data within the file. This data is
40d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein * stored within a global cache for later use.
41d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein */
42d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinpublic class InfoBuilder {
43d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private PackageInfo mPackage;
44d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ArrayList<String> mImports;
45d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private HashSet<String> mClassNames;
466ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private String mFilename; // TODO - remove this eventually
476ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private ClassInfo mRootClass;
48d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
496ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public InfoBuilder(String filename) {
50d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        mImports = new ArrayList<String>();
51d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        mImports.add("java.lang.*"); // should allow us to resolve this properly, eventually
52d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                     // alternatively, we could add everything from java.lang.*
53d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                     // but that would probably be too brittle
54d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        mClassNames = new HashSet<String>();
556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        mFilename = filename;
566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    @Override
596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public String toString() {
606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        return mFilename;
616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public void parseFile() {
646ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        JavaLexer lex;
656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        try {
666ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            lex = new JavaLexer(new ANTLRFileStream(mFilename, "UTF8"));
676ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            CommonTokenStream tokens = new CommonTokenStream(lex);
696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
706ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            // create the ParseTreeBuilder to build a parse tree
716ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            // much easier to parse than ASTs
726ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            ParseTreeBuilder builder = new ParseTreeBuilder("compilationUnit");
736ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            JavaParser g = new JavaParser(tokens, builder);
746ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
756ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            g.compilationUnit();
766ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            ParseTree tree = builder.getTree();
776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
786ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            lex = null;
796ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            tokens = null;
806ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            builder = null;
816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            g = null;
826ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            parseFile(tree);
846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
856ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        } catch (IOException e1) {
866ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            e1.printStackTrace();
876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        } catch (RecognitionException e) {
886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            e.printStackTrace();
896ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
906ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
916ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
926ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public static void resolve() {
936ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        Caches.resolve();
94d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
95d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
96d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    // All of the print functions exist for debugging alone.
97d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    public void printStuff() {
98d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        System.out.println(mPackage.name() + "\n");
99d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
100d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        printList(mImports);
101d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
102d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Caches.printResolutions();
103d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
104d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
105d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void printList(ArrayList<String> list) {
106d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (String value : list) {
107d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.println(value);
108d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
109d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
110d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        System.out.println();
111d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
112d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1136ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public static void printClassInfo(ClassInfo cl) {
1146ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        System.out.print("Class: " + cl.toString());
1156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        printTypeVariables(cl.type());
1176ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        System.out.println();
1196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        System.out.println(cl.comment().mText);
121d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.annotations().isEmpty()) {
1236ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nAnnotations:");
1246ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            printAnnotations(cl.annotations());
1256ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
126d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (cl.superclass() != null) {
1286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.print("Superclass: " + cl.superclass().qualifiedName());
1296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            printTypeVariables(cl.superclassType());
130d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.println();
1316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
132d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.realInterfaces().isEmpty()) {
1346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nInterfaces Implemented:");
1356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            Iterator<TypeInfo> it = cl.realInterfaceTypes().iterator();
1366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (ClassInfo cls : cl.realInterfaces()) {
1376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                TypeInfo outerType = it.next();
1386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (cls == null) {
1396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(outerType.simpleTypeName());
1406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else {
1416ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(cls.qualifiedName());
1426ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
143d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printTypeVariables(outerType);
145d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
146d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                System.out.println();
147d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
148d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1496ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
1506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
151d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1526ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.allSelfFields().isEmpty()) {
1536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nFields:");
1546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (FieldInfo f : cl.allSelfFields()) {
1556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (f != cl.allSelfFields().get(0)) {
156d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    System.out.println();
157d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(f.comment().mText);
159d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printAnnotations(f.annotations());
1616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printTypeName(f.type());
162d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.print(" " + f.name());
164d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (f.constantValue() != null) {
1666ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println(": " + f.constantValue());
1676ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else if (f.hasValue()) {
1686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println(": has some value");
1696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else {
1706ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
171d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
172d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
173d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1746ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
1756ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
176d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (cl.enumConstants() != null && !cl.enumConstants().isEmpty()) {
1786ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nEnum Constants:");
1796ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (FieldInfo f : cl.enumConstants()) {
1806ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (f != cl.enumConstants().get(0)) {
1816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
182d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(f.comment().mText);
1846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printAnnotations(f.annotations());
1856ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.print(f.type().simpleTypeName() + " " + f.name());
186d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (f.constantValue() != null) {
1886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println(": " + f.constantValue());
1896ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else {
1906ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
1916ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
192d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
193d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1946ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
1956ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
196d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1976ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.allConstructors().isEmpty()) {
1986ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nConstructors:");
1996ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (MethodInfo m : cl.allConstructors()) {
2006ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m != cl.allConstructors().get(0)) {
2016ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
2026ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
203d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2046ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(m.comment().mText);
205d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printAnnotations(m.annotations());
2076ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m.getTypeParameters() != null) {
2086ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    printTypeVariableList(m.getTypeParameters());
2096ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(" ");
210d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
211d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2126ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(m.name() + m.flatSignature());
213d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
214d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
2166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
217d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.allSelfMethods().isEmpty()) {
2196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nMethods:");
2206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (MethodInfo m : cl.allSelfMethods()) {
2216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m != cl.allSelfMethods().get(0)) {
2226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
2236ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
224d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2256ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(m.comment().mText);
2266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printAnnotations(m.annotations());
2276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m.getTypeParameters() != null) {
2286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    printTypeVariableList(m.getTypeParameters());
2296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(" ");
2306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
231d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printTypeName(m.returnType());
233d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.print(" " + m.name() + m.flatSignature());
235d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m.thrownExceptions() != null && !m.thrownExceptions().isEmpty()) {
2376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(" throws ");
2386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    for (ClassInfo c : m.thrownExceptions()) {
2396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        if (c != m.thrownExceptions().get(0)) {
2406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            System.out.print(", ");
241d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        }
242d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        System.out.print(c.name());
2446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
245d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
246d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
247d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                System.out.println();
248d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
249d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
2516ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
252d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (!cl.annotationElements().isEmpty()) {
2546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nAnnotation Elements:");
255d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (MethodInfo m : cl.annotationElements()) {
2576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m != cl.annotationElements().get(0)) {
2586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.println();
2596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
260d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println(m.comment().mText);
2626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printAnnotations(m.annotations());
2636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printTypeName(m.returnType());
264d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.print(" " + m.name() + m.flatSignature());
266d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2676ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (m.defaultAnnotationElementValue() != null) {
2686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    System.out.print(" default " +
2696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            m.defaultAnnotationElementValue().valueString());
270d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
271d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
272d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                System.out.println();
273d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
2746ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
2756ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println();
2766ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
2776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
2786ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (cl.innerClasses() != null && !cl.innerClasses().isEmpty()) {
2796ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            System.out.println("\nInner Classes:");
2806ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (ClassInfo c : cl.innerClasses()) {
2816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                printClassInfo(c);
2826ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
283d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
284d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
285d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2866ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static void printTypeName(TypeInfo type) {
287d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        System.out.print(type.simpleTypeName());
288d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
289d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (type.extendsBounds() != null && !type.extendsBounds().isEmpty()) {
290d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.print(" extends ");
291d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (TypeInfo t : type.extendsBounds()) {
292d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (t != type.extendsBounds().get(0)) {
293d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    System.out.print(" & ");
294d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
295d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                printTypeName(t);
296d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
297d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
298d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
299d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (type.superBounds() != null && !type.superBounds().isEmpty()) {
300d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.print(" super ");
301d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (TypeInfo t : type.superBounds()) {
302d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (t != type.superBounds().get(0)) {
303d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    System.out.print(" & ");
304d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
305d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                printTypeName(t);
306d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
307d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
308d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
309d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        printTypeVariables(type);
310d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
311d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (type.dimension() != null) {
312d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.print(type.dimension());
313d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
314d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
315d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
3166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static void printAnnotations(ArrayList<AnnotationInstanceInfo> annotations) {
317d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (AnnotationInstanceInfo i : annotations) {
318d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.println(i);
319d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
320d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
321d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
3226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static void printTypeVariables(TypeInfo type) {
323d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        printTypeVariableList(type.typeArguments());
324d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
325d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
3266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static void printTypeVariableList(ArrayList<TypeInfo> typeList) {
327d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (typeList != null && !typeList.isEmpty()) {
328d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.print("<");
329d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (TypeInfo type : typeList) {
330d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (type != typeList.get(0)) {
331d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    System.out.print(", ");
332d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
333d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                printTypeName(type);
334d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
335d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            System.out.print(">");
336d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
337d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
338d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
339d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
340d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the file represented by the ParseTree.
341d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree A ParseTree of the file to parse.
342d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
3436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private void parseFile(ParseTree tree) {
344d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (tree.payload != null) {
345d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            String payload = tree.payload.toString();
346d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
347d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // first pass at ignore method blocks
348d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("block".equals(payload) ||
3496ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    "blockStatement".equals(payload) ||
3506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    "explicitConstructorInvocation".equals(payload)) {
351d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                tree = null;
352d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
353d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
354d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
355d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // parse package of file
356d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("packageDeclaration".equals(payload)) {
357d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                mPackage = buildPackage(tree);
358d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
359d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // parse imports
360d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("importDeclaration".equals(payload)) {
361d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                mImports.add(buildImport(tree));
362d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
363d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // classes
364d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("normalClassDeclaration".equals(payload)) {
3656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                buildClass(tree, null);
366d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
367d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // enums
368d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }  else if ("enumDeclaration".equals(payload)) {
3696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                buildEnum(tree, null);
370d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
371d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // interfaces
372d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("normalInterfaceDeclaration".equals(payload)) {
3736ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                buildInterface(tree, null);
374d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
375d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // annotations
376d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("annotationTypeDeclaration".equals(payload)) {
3776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                buildAnnotationDeclaration(tree, null);
378d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return;
379d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
380d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
381d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
382d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // if we're not at the end, recurse down the tree
383d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (int i = 0; i < tree.getChildCount(); i++) {
384d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            parseFile((ParseTree) tree.getChild(i));
385d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
386d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
387d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
388d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
389d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses a packageDeclaration in the tree. This function should only be called once per file.
390d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. packageDeclaration should be the root value.
391d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return a PackageInfo representing the package in which this file exists.
392d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
393d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private PackageInfo buildPackage(ParseTree tree) {
394d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (int i = 0; i < tree.getChildCount(); i++) {
395d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) tree.getChild(i);
396d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
397d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (child.payload != null && "qualifiedName".equals(child.payload.toString())) {
398d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                String packageName = buildQualifiedName(child);
399d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
400d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // return package because we might be creating packages for other classes
401d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return Caches.obtainPackage(packageName);
402d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
403d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
404d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
405d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return null;
406d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
407d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
408d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
409d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses a qualifiedName, returning it as a String.
410d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. qualifiedName should be the root value.
411d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return
412d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
413d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private static String buildQualifiedName(ParseTree tree) {
414d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder packageName = new StringBuilder();
415d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
416d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (int j = 0; j < tree.getChildCount(); j++) {
417d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            packageName.append(tree.getChild(j).toString());
418d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
419d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
420d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return packageName.toString();
421d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
422d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
423d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
424d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a string representing an import declaration.
425d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. importDeclaration should be the root value.
426d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return a String version of the import.
427d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
428d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private String buildImport(ParseTree tree) {
429d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder theImport = new StringBuilder();
4306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        for (int i = 1; i < tree.getChildCount(); i++) {
431d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            String part = tree.getChild(i).toString();
432d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
4336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if ((i == 1 && "static".equals(part))
4346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    || (i == tree.getChildCount()-1 && ";".equals(part))) {
4356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                continue;
436d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
4376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
4386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            theImport.append(part);
439d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
440d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
441d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return theImport.toString();
442d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
443d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
444d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
445d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a ClassInfo for a normalClassDeclaration.
446d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. normalClassDeclaration should be the root value.
447d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass The class that contains the class that will be built.
448d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * This value should be null if this class is a root class in the file.
449d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return A ClassInfo that contains all of the information about the class.
450d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
451d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ClassInfo buildClass(ParseTree tree, ClassInfo containingClass) {
452d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
453d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
454d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo cls = null;
455d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
456d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
457d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
458d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
459d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
460d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse modifiers
461d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
462d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
463d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
464d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
465d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
466d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse class name
467d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls = buildClassName(child, containingClass, modifiers,
468d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getCommentText(),
469d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getPosition(),
470d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                ClassType.ORDINARY);
471d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
472d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
473d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
474d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle generics
475d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("typeParameters".equals(child.toString())) {
476d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            cls.type().setTypeArguments(buildTypeVariables(child));
477d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
478d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
479d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
480d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
481d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle extends
482d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("extends".equals(child.toString())) {
483d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
484d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
485d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            TypeInfo type = buildType(child);
486d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            cls.setSuperclassType(type);
487d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
488d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // if ClassInfo is null, we need to add a resolution
489d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (type.asClassInfo() == null) {
4906ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                addFutureResolution(cls, "superclassQualifiedName", type.simpleTypeName(), this);
491d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
492d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
493d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            cls.setSuperClass(type.asClassInfo());
494d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
495d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
496d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
497d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
4986ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // TODO - do I have to make java.lang.Object the superclass if there is none otherwise?
4996ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
500d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle implements
501d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("implements".equals(child.toString())) {
502d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
503d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
504d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            parseInterfaces(child, cls);
505d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
506d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
507d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
508d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
509d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // finally, parse the body
510d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        buildClassBody(child, cls);
511d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
512d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return cls;
513d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
514d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
515d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
516d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the list of interfaces that the class implements.
517d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Should only be called if the implements keyword is found.
518d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. typeList should be the root element.
519d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param cls The class that implements these interfaces.
520d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
521d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void parseInterfaces(ParseTree tree, ClassInfo cls) {
522d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
523d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("type".equals(o.toString())) {
524d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                TypeInfo type = buildType((ParseTree) o);
525d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                cls.addInterfaceType(type);
526d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
527d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // if ClassInfo is null, we need to add a resolution
528d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (type.asClassInfo() == null) {
5296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    addFutureResolution(cls, "interfaceQualifiedName", type.simpleTypeName(), this);
530d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
531d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
532d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                cls.addInterface(type.asClassInfo());
533d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
534d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
535d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
536d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
537d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
538d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * ClassType exists solely to tell buildClassName which type of ClassInfo is being built.
539d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
540d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private enum ClassType {
541d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ENUM, INTERFACE, ANNOTATION, ORDINARY
542d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
543d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
544d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
545d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the class name from the declaration. Also initializes the class.
546d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree Position of the tree where the name of the class resides.
547d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass Class that this class is contained within.
548d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * <tt>null</tt> if this class is the root class.
549d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param modifiers Contains all the modifiers of this class.
550d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param commentText Javadoc comment of this class.
551d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param position Position of the class.
552d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param classType Type of class being instantiated.
553d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return the ClassInfo being initialized.
554d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
555d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ClassInfo buildClassName(ParseTree tree, ClassInfo containingClass, Modifiers modifiers,
556d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            String commentText, SourcePositionInfo position, ClassType classType) {
557d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String qualifiedClassName = null;
558d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isOrdinaryClass = true;
559d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isException = false;
560d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isError = false;
561d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isIncluded = false;
562d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isPrimitive = false;
563d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isEnum = false;
564d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isInterface = false;
565d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isAnnotation = false;
566d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
567d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // set appropriate flags based on ClassType
568d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        switch (classType) {
569d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            case ENUM:
570d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                isEnum = true;
571d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                break;
572d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            case INTERFACE:
573d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                isInterface = true;
574d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                break;
575d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            case ANNOTATION:
576d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                isAnnotation = true;
577d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                break;
578d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
579d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
580d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String qualifiedTypeName = null;
581d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo cls = null;
582d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
583d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // changes the name based upon whether this is the root class or an inner class
584d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (containingClass == null) {
585d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            qualifiedClassName = mPackage.name() + "." + tree.toString();
586d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else {
587d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            qualifiedClassName = containingClass.qualifiedName() + "." + tree.toString();
588d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
589d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
590d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        qualifiedTypeName = new String(qualifiedClassName);
591d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
592d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // add the name to mClassNames so that we can use it to resolve usages of this class
593d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        mClassNames.add(qualifiedClassName);
594d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
595d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // get the class from the cache and initialize it
596d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls = Caches.obtainClass(qualifiedClassName);
597d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls.initialize(commentText, position,
5986ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                modifiers.isPublic(), modifiers.isProtected(),
5996ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                modifiers.isPackagePrivate(), modifiers.isPrivate(),
6006ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                modifiers.isStatic(), isInterface, modifiers.isAbstract(),
6016ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                isOrdinaryClass, isException, isError, isEnum, isAnnotation,
6026ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                modifiers.isFinal(), isIncluded, qualifiedTypeName, isPrimitive,
6036ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                modifiers.getAnnotations());
604d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
605d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls.setContainingClass(containingClass);
6066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        cls.setContainingPackage(mPackage);
6076ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
6086ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (containingClass == null) {
6096ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            mRootClass = cls;
6106ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
611d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
612d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // create an set a TypeInfo for this class
613d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo type = new TypeInfo(false, null, cls.name(), qualifiedTypeName, cls);
614d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls.setTypeInfo(type);
615d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
616d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return cls;
617d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
618d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
619d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
620d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the body of a class.
621d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. classBody should be the root value.
622d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param cls
623d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
624d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void buildClassBody(ParseTree tree, ClassInfo cls) {
625d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
626d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) o;
627d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
628d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // skip all of the cruft that isn't a declaration
629d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (!"classBodyDeclaration".equals(child.toString())) {
630d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                continue;
631d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
632d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
633d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // get to an actual definition
634d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree member = (ParseTree) child.getChild(0).getChild(0);
635d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
6366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            // ignores static initializers
6376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (member == null) {
6386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                continue;
6396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
6406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
641d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // field
642d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("fieldDeclaration".equals(member.toString())) {
6436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                for (FieldInfo f : buildFields(member, cls)) {
6446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    cls.addField(f);
6456ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
646d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // method and constructor
647d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("methodDeclaration".equals(member.toString())) {
648d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                MethodInfo method = buildMethod(member, cls, false);
649d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
650d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (method.kind().equals("constructor")) {
651d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    cls.addConstructor(method);
652d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else {
653d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    cls.addMethod(method);
654d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
655d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // classes and enums
656d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("classDeclaration".equals(member.toString())) {
657d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                Object tmp = member.getChild(0);
658d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
659d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("normalClassDeclaration".equals(tmp.toString())) {
6606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    cls.addInnerClass(buildClass((ParseTree) tmp, cls));
661d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("enumDeclaration".equals(tmp.toString())) {
6626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    cls.addInnerClass(buildEnum((ParseTree) tmp, cls));
663d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
664d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // interfaces and annotations
665d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("interfaceDeclaration".equals(member.toString())) {
666d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                Object tmp = member.getChild(0);
667d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
668d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("normalInterfaceDeclaration".equals(tmp.toString())) {
6696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    cls.addInnerClass(buildInterface((ParseTree) tmp, cls));
670d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("annotationTypeDeclaration".equals(tmp.toString())) {
6716ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    cls.addInnerClass(buildAnnotationDeclaration((ParseTree) tmp, cls));
672d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
673d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
674d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
675d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
676d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
677d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
6786ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein     * Builds one or more FieldInfos for the field declared in this class.
679d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. fieldDeclaration should be the root value.
680d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass The ClassInfo in which this field is contained.
6816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein     * @return A list of FieldInfos for this field declaration.
682d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
6836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private ArrayList<FieldInfo> buildFields(ParseTree tree, ClassInfo containingClass) {
6846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        ArrayList<FieldInfo> fields = new ArrayList<FieldInfo>();
685d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
686d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
687d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String name = null;
688d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Object constantValue = null;
689d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo type = null;
690d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean hasValue = false;
691d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
692d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
693d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
694d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
695d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
696d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // modifiers
697d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
698d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
699d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
700d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse the type of this field
701d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        type = buildType(child);
702d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
703d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
704d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
705d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse the variable declarators
7066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        boolean firstType = true;
7076ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        while (!";".equals(child.toString())) {
7086ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if ("variableDeclarator".equals(child.toString())) {
7096ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                TypeInfo newType;
7106ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (firstType) {
7116ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    firstType = false;
7126ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType = type;
7136ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else {
7146ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType = new TypeInfo(type.isPrimitive(), type.dimension(),
7156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            type.simpleTypeName(), type.qualifiedTypeName(), type.asClassInfo());
7166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType.setBounds(type.superBounds(), type.extendsBounds());
7176ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType.setIsWildcard(type.isWildcard());
7186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType.setIsTypeVariable(type.isTypeVariable());
7196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    newType.setTypeArguments(type.typeArguments());
7206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
7216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                name = child.getChild(0).toString();
7226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7236ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                // if we have a value for the field and/or dimensions
7246ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (child.getChildCount() > 1) {
7256ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    int j = 1;
7266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    ParseTree tmp = (ParseTree) child.getChild(j++);
7276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    // if we have dimensions in the wrong place
7296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if ("[".equals(tmp.toString())) {
7306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        StringBuilder builder = new StringBuilder();
7316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        do {
7336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            builder.append(tmp.toString());
7346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            tmp = (ParseTree) child.getChild(j++);
7356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        } while (j < child.getChildCount() && !"=".equals(tmp.toString()));
7366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        newType.setDimension(builder.toString());
7386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
7396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    // get value if it exists
7416ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if (j < child.getChildCount()) {
7426ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        // get to variableInitializer
7436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        do {
7446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            tmp = (ParseTree) child.getChild(j++);
7456ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        } while (!"variableInitializer".equals(tmp.toString()));
7466ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7476ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        // get the constantValue
7486ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        constantValue = parseExpression(tmp);
7496ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
7506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7516ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    hasValue = true;
7526ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
7536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                FieldInfo field = new FieldInfo(name, containingClass, containingClass,
7556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        modifiers.isPublic(), modifiers.isProtected(),
7566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        modifiers.isPackagePrivate(), modifiers.isPrivate(),
7576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        modifiers.isFinal(), modifiers.isStatic(), modifiers.isTransient(),
7586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        modifiers.isVolatile(), modifiers.isSynthetic(),
7596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        newType, commentAndPosition.getCommentText(), constantValue,
7606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        commentAndPosition.getPosition(), modifiers.getAnnotations());
7616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                field.setHasValue(hasValue);
7626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                fields.add(field);
763d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
764d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
7656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            child = it.next();
7666ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
767d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
7686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        return fields;
769d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
770d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
771d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
772d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses an expression in the ParseTree to get a constant value.
773d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree the place in the tree to get the constant value.
774d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return the constant value.
775d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
776d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private static Object parseExpression(ParseTree tree) {
777d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Object constantValue = null;
778d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder builder = new StringBuilder();
779d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
780d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        while (!"primary".equals(tree.toString())) {
7816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (tree.getChildCount() > 1) {
7826ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if ("unaryExpression".equals(tree.toString()) ||
7836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        "unaryExpressionNotPlusMinus".equals(tree.toString())) {
7846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if ("selector".equals(tree.getChild(1).toString())) {
7856ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        return constantValue;
7866ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
7876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
7886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    builder.append(tree.getChild(0));
7896ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    tree = (ParseTree) tree.getChild(1);
7906ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else if ("arrayInitializer".equals(tree.toString())) {
7916ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    // TODO - do we wanna parse arrays or just skip it
7926ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    return constantValue;
7936ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                } else {
7946ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    return constantValue;
7956ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
7966ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else if ("castExpression".equals(tree.toString())) {
7976ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                tree = (ParseTree) tree.getChild(tree.getChildCount()-1);
798d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else {
799d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                tree = (ParseTree) tree.getChild(0);
800d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
801d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
802d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
803d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("literal".equals(tree.getChild(0).toString())) {
804d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            constantValue = builder.append(tree.getChild(0).getChild(0).toString()).toString();
805d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if (tree.getChildCount() > 1) {
806d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object o : tree.getChildren()) {
807d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                builder.append(o.toString());
808d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
809d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
810d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            constantValue = builder.toString();
811d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
812d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
813d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return constantValue;
814d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
815d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
816d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
817d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds  TypeInfo. Requires that tree points to "type" in the ParseTree.
818d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. type should be the root value.
819d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return A TypeInfo for this type.
820d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
821d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private TypeInfo buildType(ParseTree tree) {
822d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isPrimitive = false;
823d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String dimension = null;
824d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String simpleTypeName = null;
825d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String qualifiedTypeName = null;
826d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo cl = null;
827d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean addResolution = false;
828d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<TypeInfo> typeArguments = null;
829d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
830d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse primitive types - very easy
831d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("primitiveType".equals(tree.getChild(0).toString())) {
832d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            isPrimitive = true;
833d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
834d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            simpleTypeName = tree.getChild(0).getChild(0).toString();
835d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            qualifiedTypeName = simpleTypeName;
836d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // any non-primitives
837d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else {
838d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            StringBuilder builder = new StringBuilder();
839d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
840d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // get the full name of the type
841d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object namePart : ((ParseTree) tree.getChild(0)).getChildren()) {
842d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // if we get to typeArguments, aka generics, parse that and bale out
843d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // of building the name
844d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("typeArguments".equals(namePart.toString())) {
845d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    typeArguments = buildTypeVariables((ParseTree) namePart);
846d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    break;
847d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
848d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
849d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                builder.append(namePart.toString());
850d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
851d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
852d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // get simple and qualified name
853d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            simpleTypeName = builder.toString();
854d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            StringBuilder qualifiedTypeNameBuilder = new StringBuilder();
855d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            boolean isGeneric = resolveQualifiedName(simpleTypeName,
856d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    qualifiedTypeNameBuilder, this);
857d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            qualifiedTypeName = qualifiedTypeNameBuilder.toString();
858d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
859d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // if we couldn't figure out the qualified name
860d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // tell us we need to resolve this
861d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // can't add the resolution until the TypeInfo has been created
862d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("".equals(qualifiedTypeName)) {
863d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                addResolution = true;
864d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // otherwise, if the name is not a generic, get the class that this Type refers to
865d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if (!isGeneric) {
866d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                cl = Caches.obtainClass(qualifiedTypeName);
867d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
868d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
869d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
870d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // get the dimensions of this type
871d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        dimension = getDimensions(tree);
872d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
873d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo type = new TypeInfo(isPrimitive, dimension, simpleTypeName, qualifiedTypeName, cl);
874d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        type.setTypeArguments(typeArguments);
875d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
876d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (addResolution) {
8776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            addFutureResolution(type, "class", simpleTypeName, this);
878d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
879d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
880d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return type;
881d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
882d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
883d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
884d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Processes the type variables of a class that contains generics.
885d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree Root of the type parameters.
886d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param cls Class in which these type variables are contained.
887d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
888d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ArrayList<TypeInfo> buildTypeVariables(ParseTree tree) {
889d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<TypeInfo> typeVariables = new ArrayList<TypeInfo>();
890d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<TypeInfo> superBounds = new ArrayList<TypeInfo>();
891d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<TypeInfo> extendsBounds = new ArrayList<TypeInfo>();
892d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
893d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
894d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // if we're not dealing with a type, skip
895d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // basically gets rid of commas and lessthan and greater than signs
896d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (!o.toString().equals("typeParameter") &&
8976ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    !o.toString().equals("typeArgument")) {
898d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                continue;
899d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
900d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
901d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree typeParameter = (ParseTree) o;
902d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
903d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            TypeInfo type;
904d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // if we have a typeArgument and it is not a wildcard
905d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("typeArgument".equals(typeParameter.toString()) &&
906d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    !"?".equals(typeParameter.getChild(0).toString())) {
907d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                type = buildType((ParseTree) typeParameter.getChild(0));
908d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else {
909d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // otherwise, we have a wildcard or parameter
910d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // which can be more vague because of generics
911d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                String name = typeParameter.getChild(0).toString();
912d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
913d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                type = new TypeInfo(false, null, name, name, null);
914d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("?".equals(name)) {
915d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    type.setIsWildcard(true);
916d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else {
917d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    // add generic
918d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mClassNames.add(name);
919d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
920d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
921d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
922d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // if we have an extends or super on our type variable
923d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (typeParameter.getChildCount() > 1) {
924d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                ParseTree value = (ParseTree) typeParameter.getChild(1);
925d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
926d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("extends".equals(value.toString())) {
927d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    value = (ParseTree) typeParameter.getChild(2);
928d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
929d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    // wildcard extends
930d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    if ("type".equals(value.toString())) {
931d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        extendsBounds.add(buildType(value));
932d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    // all other extends
933d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    } else {
934d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        // will have to handle stuff with typeBound - multiple types
935d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        for (Object obj : value.getChildren()) {
936d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                            if ("type".equals(obj.toString())) {
937d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                extendsBounds.add(buildType((ParseTree) obj));
938d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                            }
939d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        }
940d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    }
941d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("super".equals(value.toString())) {
942d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    superBounds.add(buildType((ParseTree) typeParameter.getChild(2)));
943d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
944d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
945d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
946d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            type.setIsTypeVariable(true);
947d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            type.setBounds(superBounds, extendsBounds);
948d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            typeVariables.add(type);
949d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
950d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
951d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return typeVariables;
952d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
953d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
954d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
955d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a MethodInfo for methods, constructors and annotation elements.
956d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. methodDeclaration, interfaceMethodDeclaration
957d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * or annotationMethodDeclaration should be the root value.
958d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass the class in which this method exists.
959d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param isAnnotation true if the class is an annotation element
960d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return the MethodInfo
961d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
962d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private MethodInfo buildMethod(ParseTree tree, ClassInfo containingClass,
963d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            boolean isAnnotation) {
964d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
965d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
966d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
967d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String name = null;
968d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder flatSignature = new StringBuilder().append('(');
969d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<TypeInfo> typeParameters = null;
970d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<ParameterInfo> parameters = new ArrayList<ParameterInfo>();
971d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<ClassInfo> thrownExceptions = new ArrayList<ClassInfo>();
972d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo returnType = null;
973d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isAnnotationElement = false;
974d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isVarArg = false;
975d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String kind = "method"; // annotationElement, method, or constructor
976d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        AnnotationValueInfo elementValue = null;
977d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<Resolution> pendingResolutions = new ArrayList<Resolution>();
978d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
979d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
980d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
981d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
982d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
983d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
984d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
985d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
986d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
987d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // generics stuff
988d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("typeParameters".equals(child.toString())) {
989d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            typeParameters = buildTypeVariables(child);
990d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
991d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
992d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
993d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle returnType if we're not in a constructor
994d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("type".equals(child.toString())) {
995d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            returnType = buildType(child);
996d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
997d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if ("void".equals(child.toString())) {
998d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            returnType = new TypeInfo(true, null, "void", "void", null);
999d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1000d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1001d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
10026ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // this is the method name
10036ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        name = child.toString();
1004d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
10056ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (name.equals(containingClass.name())) {
10066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            kind = "constructor";
1007d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1008d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
10096ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // probably don't need this check any longer since I unrolled the loop
10106ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//        if (isConstructorOrMethodName(child)) {
10116ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//            // this is the method name
10126ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//            name = child.toString();
10136ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//
10146ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//            if (name.equals(containingClass.name())) {
10156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//                kind = "constructor";
10166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//            }
10176ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein//        }
10186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1019d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1020d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1021d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // method parameters
1022d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("formalParameters".equals(child.toString())) {
1023d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            isVarArg = buildMethodParameters(child, parameters, flatSignature);
1024d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else {
1025d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1026d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1027d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1028d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1029d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        flatSignature.append(')');
1030d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1031d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle exception throwing
1032d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("throws".equals(child.toString())) {
1033d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1034d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1035d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object o : child.getChildren()) {
1036d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (",".equals(o.toString())) {
1037d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    continue;
1038d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1039d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1040d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // get the name of the exception, resolve it and add it to the list
1041d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // unless we can't, in which case, add a resolution
1042d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                String exceptionName = buildQualifiedName(((ParseTree) o));
1043d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                StringBuilder exceptionQualifiedName = new StringBuilder();
1044d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                boolean isGeneric = resolveQualifiedName(exceptionName,
1045d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        exceptionQualifiedName, this);
1046d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1047d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("".equals(exceptionQualifiedName.toString())) {
10486ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    pendingResolutions.add(new Resolution("thrownException", exceptionName, null));
1049d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if (!isGeneric) {
1050d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    thrownExceptions.add(Caches.obtainClass(exceptionQualifiedName.toString()));
1051d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1052d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1053d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle default values for annotation elements
1054d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if ("default".equals(child.toString())) {
1055d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1056d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1057d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            elementValue = buildElementValue(child, this);
1058d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1059d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1060d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1061d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (isAnnotation) {
1062d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            kind = "annotationElement";
1063d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1064d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1065d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // Here we set signature, overridden method to null because
1066d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // MethodInfo figures these values out later on
1067d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        MethodInfo method =  new MethodInfo(commentAndPosition.getCommentText(), typeParameters,
1068d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                name, null, containingClass, containingClass, modifiers.isPublic(),
1069d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                modifiers.isProtected(), modifiers.isPackagePrivate(),
1070d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                modifiers.isPrivate(), modifiers.isFinal(),
1071d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                modifiers.isStatic(), modifiers.isSynthetic(),
1072d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                modifiers.isAbstract(), modifiers.isSynchronized(),
10732e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller                false, modifiers.isDefault(), isAnnotationElement, kind, flatSignature.toString(),
1074d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                null, returnType, parameters, thrownExceptions,
1075d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getPosition(), modifiers.getAnnotations());
1076d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1077d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        method.setVarargs(isVarArg);
1078d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        method.init(elementValue);
1079d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1080d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Resolution r : pendingResolutions) {
10816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            addFutureResolution(method, r.getVariable(), r.getValue(), this);
1082d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1083d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1084d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return method;
1085d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1086d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1087d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1088d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Build the method parameters.
1089d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. formalParamaters should be the root value.
1090d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param parameters List to put the method ParamaterInfos into.
1091d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param flatSignature Pass in a StringBuilder with "(" in it to build the
1092d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * flatSignature of the MethodInfo
1093d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return true if the Method has a VarArgs parameter. false otherwise.
1094d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1095d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private boolean buildMethodParameters(ParseTree tree,
1096d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                    ArrayList<ParameterInfo> parameters,
1097d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                    StringBuilder flatSignature) {
1098d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        boolean isVarArg = false;
1099d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object obj : tree.getChildren()) {
1100d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) obj;
1101d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1102d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("formalParameterDecls".equals(child.toString())) {
1103d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                for (Object formalParam : child.getChildren()) {
1104d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    ParseTree param = (ParseTree) formalParam;
1105d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    TypeInfo type = null;
1106d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1107d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    if (param.getChildCount() == 0) {
1108d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        continue;
1109d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    }
1110d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
11116ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    @SuppressWarnings("unchecked")
11126ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    Iterator<ParseTree> it = (Iterator<ParseTree>) param.getChildren().iterator();
11136ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11146ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    ParseTree paramPart = it.next();
11156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if ("variableModifiers".equals(paramPart.toString())) {
11176ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        // TODO - handle variable modifiers - final, etc
11186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
11196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    paramPart = it.next();
1121d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
11226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    type = buildType(paramPart);
1123d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
11246ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    buildSignatureForType(flatSignature, type);
1125d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
11266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if (param != child.getChildren().get(child.getChildCount()-1)) {
11276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        flatSignature.append(", ");
11286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
11296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    paramPart = it.next();
11316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if ("...".equals(paramPart.toString())) {
11336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        isVarArg = true;
11346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        // thank you varargs for only being the last parameter
11356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        // you make life so much nicer
11366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        flatSignature.append("...");
11376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        paramPart = it.next();
1138d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    }
11396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    String name = paramPart.toString();
11416ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11426ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    CommentAndPosition commentAndPosition = new CommentAndPosition();
11436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    commentAndPosition.setPosition(paramPart);
11446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
11456ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    parameters.add(new ParameterInfo(name, type.qualifiedTypeName(), type,
11467c80d0e9086eef289d323661977cbfb771d95a2aMorad Abdelrahman                            isVarArg, commentAndPosition.getPosition(),
11477c80d0e9086eef289d323661977cbfb771d95a2aMorad Abdelrahman                            Collections.<AnnotationInstanceInfo>emptyList()));
1148d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1149d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1150d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1151d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1152d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return isVarArg;
1153d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1154d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1155d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1156d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a StringBuilder representing the Type, including type arguments.
1157d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param builder StringBuilder in which the Type will be placed.
1158d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param type the TypeInfo to turn into a String.
1159d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1160d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void buildSignatureForType(StringBuilder builder, TypeInfo type) {
1161d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // simple name
1162d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        builder.append(type.simpleTypeName());
1163d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1164d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // generics
1165d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (type.typeArguments() != null && !type.typeArguments().isEmpty()) {
1166d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            builder.append('<');
1167d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (TypeInfo inner : type.typeArguments()) {
1168d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (inner != type.typeArguments().get(0)) {
1169d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    builder.append(", ");
1170d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1171d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1172d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // recurse
1173d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                buildSignatureForType(builder, inner);
1174d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1175d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            builder.append('>');
1176d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1177d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1178d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1179d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1180d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a ClassInfo for an enum.
1181d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. enumDeclaration should be the root value.
1182d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass ClassInfo that contains the enum declaration.
1183d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * null if the enum is a root class.
1184d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return the enum as a ClassInfo
1185d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1186d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ClassInfo buildEnum(ParseTree tree, ClassInfo containingClass) {
1187d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
1188d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
1189d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo cls = null;
1190d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1191d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
1192d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
1193d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1194d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
1195d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1196d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
1197d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1198d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1199d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1200d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1201d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cls = buildClassName(child, containingClass, modifiers,
1202d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getCommentText(),
1203d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getPosition(), ClassType.ENUM);
1204d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
12056ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        child = it.next();
12066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1207d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // handle implements
1208d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("implements".equals(child.toString())) {
1209d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1210d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1211d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            parseInterfaces(child, cls);
1212d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1213d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1214d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1215d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1216d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        buildEnumBody(child, cls);
1217d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1218d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return cls;
1219d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1220d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1221d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1222d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the body of an enum.
1223d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. enumBody should be the root value.
1224d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass ClassInfo to which this enum body pertains.
1225d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1226d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void buildEnumBody(ParseTree tree, ClassInfo containingClass) {
1227d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
1228d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) o;
1229d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1230d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("enumConstants".equals(child.toString())) {
1231d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                for (Object o2 : child.getChildren()) {
1232d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    ParseTree tmp = (ParseTree) o2;
1233d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1234d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    if ("enumConstant".equals(tmp.toString())) {
1235d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        containingClass.addEnumConstant(buildEnumConstant(tmp, containingClass));
1236d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    }
1237d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1238d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("enumBodyDeclarations".equals(child.toString())) {
1239d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                buildClassBody(child, containingClass);
1240d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1241d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1242d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return;
1243d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1244d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1245d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1246d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds an enum constant.
1247d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. enumConstant should be the root value.
1248d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass ClassInfo to which this enum constant pertains.
1249d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return
1250d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1251d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private FieldInfo buildEnumConstant(ParseTree tree, ClassInfo containingClass) {
12526ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        @SuppressWarnings("unchecked")
12536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
12546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        ParseTree child = it.next();
12556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
12566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        Modifiers modifiers = new Modifiers(this);
12576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if ("annotations".equals(child.toString())) {
12586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            modifiers.parseModifiers(child);
12596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            child = it.next();
12606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
1261d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
12626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        String name = child.toString();
1263d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = new CommentAndPosition();
12646ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        commentAndPosition.setCommentText(child);
12656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        commentAndPosition.setPosition(child);
1266d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Object constantValue = null;
1267d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
12686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // get constantValue if it exists
12696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (it.hasNext()) {
12706ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            child = it.next();
12716ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
12726ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            // if we have an expressionList
12736ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (child.getChildCount() == 3) {
12746ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                StringBuilder builder = new StringBuilder();
12756ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                child = (ParseTree) child.getChild(1); // get the middle child
12766ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
12776ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                for (Object o : child.getChildren()) {
12786ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    if ("expression".equals(o.toString())) {
12796ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        builder.append(parseExpression((ParseTree) o));
12806ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
12816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        if (o != child.getChild(child.getChildCount()-1)) {
12826ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                            builder.append(", ");
12836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        }
12846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    }
12856ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
12866ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
12876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                constantValue = builder.toString();
12886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
12896ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
1290d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1291d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return new FieldInfo(name, containingClass, containingClass, containingClass.isPublic(),
1292d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        containingClass.isProtected(), containingClass.isPackagePrivate(),
1293d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        containingClass.isPrivate(), containingClass.isFinal(),
1294d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        containingClass.isStatic(), false, false, false,
1295d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        containingClass.type(), commentAndPosition.getCommentText(),
1296d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        constantValue, commentAndPosition.getPosition(),
12976ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        modifiers.getAnnotations());
1298d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1299d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1300d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1301d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a ClassInfo for an interface.
1302d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. normalInterfaceDeclaration should be the root value.
1303d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass ClassInfo that contains the interface declaration.
1304d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * null if the interface is a root class.
1305d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return a ClassInfo representing the interface.
1306d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1307d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ClassInfo buildInterface(ParseTree tree, ClassInfo containingClass) {
1308d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
1309d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
1310d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
1311d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1312d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse modifiers and get comment and position
1313d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
1314d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
1315d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
1316d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1317d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
1318d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1319d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1320d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // get class name
1321d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo iface = buildClassName(child, containingClass, modifiers,
1322d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getCommentText(),
1323d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getPosition(), ClassType.INTERFACE);
1324d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1325d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1326d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1327d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse generics if they exist
1328d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("typeParameters".equals(child.toString())) {
1329d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            iface.type().setTypeArguments(buildTypeVariables(child));
1330d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1331d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1332d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1333d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse interfaces implemented by this interface
1334d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("extends".equals(child.toString())) {
1335d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1336d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1337d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            parseInterfaces(child, iface);
1338d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1339d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = it.next();
1340d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1341d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1342d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // finally, build the body of the interface
1343d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        buildInterfaceBody(child, iface);
1344d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1345d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return iface;
1346d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1347d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1348d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1349d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the body of the interface, adding it to iface.
1350d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. interfaceBody should be the root value.
1351d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param iface ClassInfo that will contain all of the interface body.
1352d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1353d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void buildInterfaceBody(ParseTree tree, ClassInfo iface) {
1354d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
1355d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (!o.toString().equals("interfaceBodyDeclaration")) {
1356d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                continue;
1357d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1358d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1359d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) ((ParseTree) o).getChild(0);
1360d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
13616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (";".equals(child.toString())) {
13626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                continue;
13636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
13646ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1365d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // field
1366d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("interfaceFieldDeclaration".equals(child.toString())) {
13676ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                for (FieldInfo f : buildFields(child, iface)) {
13686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    iface.addField(f);
13696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
1370d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // method
1371d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("interfaceMethodDeclaration".equals(child.toString())) {
1372d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                iface.addMethod(buildMethod(child, iface, false));
1373d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner class
1374d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("normalClassDeclaration".equals(child.getChild(0).toString())) {
1375d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                iface.addInnerClass(buildClass((ParseTree) child.getChild(0), iface));
1376d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner enum
1377d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("enumDeclaration".equals(child.getChild(0).toString())) {
1378d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                iface.addInnerClass(buildEnum((ParseTree) child.getChild(0), iface));
1379d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner interface
1380d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("normalInterfaceDeclaration".equals(child.getChild(0).toString())) {
1381d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                iface.addInnerClass(buildInterface((ParseTree) child.getChild(0), iface));
1382d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner annotation
1383d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("annotationTypeDeclaration".equals(child.getChild(0).toString())) {
1384d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                iface.addInnerClass(buildAnnotationDeclaration(
1385d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        (ParseTree) child.getChild(0), iface));
1386d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1387d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1388d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1389d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1390d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1391d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds a ClassInfo of an annotation declaration.
1392d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. annotationTypeDeclaration should be the root value.
1393d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param containingClass The class that contains this annotation.
1394d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * null if this is a root annotation.
1395d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return the ClassInfo of the annotation declaration.
1396d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1397d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private ClassInfo buildAnnotationDeclaration(ParseTree tree, ClassInfo containingClass) {
1398d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
1399d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
1400d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
1401d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1402d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // get comment and position
1403d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition commentAndPosition = parseCommentAndPosition(tree);
1404d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1405d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // modifiers
1406d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Modifiers modifiers = new Modifiers(this);
1407d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        modifiers.parseModifiers(child);
1408d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1409d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // three calls to next to skip over @, interface and then
1410d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // make child = the name of this annotation
1411d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
1412d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
1413d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1414d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1415d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // build class name and initialize the class
1416d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo annotation = buildClassName(child, containingClass, modifiers,
1417d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getCommentText(),
1418d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                commentAndPosition.getPosition(), ClassType.INTERFACE);
1419d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1420d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = it.next();
1421d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1422d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // build annotation body
1423d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        buildAnnotationBody(child, annotation);
1424d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1425d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return annotation;
1426d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1427d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1428d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1429d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the body of the annotation declaration.
1430d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. annotationTypeBody should be the root value.
1431d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param annotation the Classinfo in which the annotation elements should be added.
1432d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1433d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private void buildAnnotationBody(ParseTree tree, ClassInfo annotation) {
1434d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (Object o : tree.getChildren()) {
1435d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (!"annotationTypeElementDeclaration".equals(o.toString())) {
1436d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                continue;
1437d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1438d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1439d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) ((ParseTree) o).getChild(0);
1440d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1441d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // annotation fields
1442d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if ("interfaceFieldDeclaration".equals(child.toString())) {
14436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                for (FieldInfo f : buildFields(child, annotation)) {
14446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    annotation.addField(f);
14456ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
1446d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // annotation methods
1447d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if ("annotationMethodDeclaration".equals(child.toString())) {
1448d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                annotation.addAnnotationElement(buildMethod(child, annotation, true));
1449d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner class
14506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else if ("normalClassDeclaration".equals(child.toString())) {
14516ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                annotation.addInnerClass(buildClass((ParseTree) child, annotation));
1452d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // enum
14536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else if ("enumDeclaration".equals(child.toString())) {
14546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                annotation.addInnerClass(buildEnum((ParseTree) child, annotation));
1455d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner interface
14566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else if ("normalInterfaceDeclaration".equals(child.toString())) {
14576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                annotation.addInnerClass(buildInterface((ParseTree) child, annotation));
1458d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // inner annotation
14596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else if ("annotationTypeDeclaration".equals(child.toString())) {
1460d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                annotation.addInnerClass(buildAnnotationDeclaration(
14616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        (ParseTree) child, annotation));
1462d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1463d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1464d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1465d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1466d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1467d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Build an annotation instance.
1468d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. annotation should be the root value.
1469d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param builder InfoBuilder of this file.
1470d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return The AnnotationInstanceInfo being parsed.
1471d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1472d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private static AnnotationInstanceInfo buildAnnotationInstance(ParseTree tree,
1473d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            InfoBuilder builder) {
1474d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unchecked")
1475d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Iterator<ParseTree> it = (Iterator<ParseTree>) tree.getChildren().iterator();
1476d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1477d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        AnnotationInstanceInfo annotationInstance = new AnnotationInstanceInfo();
1478d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1479d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
1480d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1481d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse the name, get its full version, and then get the ClassInfo of it, if possible.
1482d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String name = InfoBuilder.buildQualifiedName(it.next());
1483d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder qualifiedNameBuilder = new StringBuilder();
1484d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        resolveQualifiedName(name, qualifiedNameBuilder, builder);
1485d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1486d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("".equals(qualifiedNameBuilder.toString())) {
14876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            addFutureResolution(annotationInstance, "annotationTypeName", name, builder);
14886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            annotationInstance.setSimpleAnnotationName(name); // TODO - remove once we've completed the parser
1489d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else { // can't have generics here so we won't do a test
1490d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            annotationInstance.setClass(Caches.obtainClass(qualifiedNameBuilder.toString()));
1491d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1492d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1493d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // at this point, the annotation is either finished or we have more work to do
1494d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (!it.hasNext()) {
1495d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return annotationInstance;
1496d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1497d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1498d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        it.next();
1499d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ParseTree child = it.next();
1500d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1501d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse elementValue pairs
1502d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("elementValuePairs".equals(child.toString())) {
1503d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object o : child.getChildren()) {
1504d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (!"elementValuePair".equals(o.toString())) {
1505d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    continue;
1506d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1507d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1508d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                ParseTree inner = (ParseTree) o;
1509d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                MethodInfo element = null;
1510d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                String methodName = inner.getChild(0).toString();
1511d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1512d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // try and look up the MethodInfo for this annotation, if possible
1513d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (annotationInstance.type() != null) {
15146ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    for (MethodInfo m : annotationInstance.type().annotationElements()) {
15156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        if (methodName.equals(m.name()) ||
15166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                                annotationInstance.type().annotationElements().size() == 1) {
1517d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                            element = m;
1518d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                            break;
1519d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        }
1520d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    }
1521d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1522d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1523d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // go to elementValue
1524d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                AnnotationValueInfo info = buildElementValue(
1525d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                        (ParseTree) inner.getChild(2), builder);
1526d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1527d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (element == null) {
15286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    addFutureResolution(info, "element", methodName, builder);
15296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    info.setAnnotationInstanceName(name);
1530d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else {
1531d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    info.setElement(element);
1532d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1533d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1534d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                annotationInstance.addElementValue(info);
1535d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1536d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse element value
1537d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if ("elementValue".equals(child.toString())) {
1538d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            annotationInstance.addElementValue(buildElementValue(child, builder));
1539d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1540d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1541d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return annotationInstance;
1542d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1543d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1544d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1545d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Builds the value of the annotation element.
1546d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. elementValue should be the root value.
1547d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param builder InfoBuilder of this file.
1548d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return AnnotationValueInfo representing the elementValue.
1549d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1550d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private static AnnotationValueInfo buildElementValue(ParseTree tree, InfoBuilder builder) {
1551d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        AnnotationValueInfo elementValue = new AnnotationValueInfo();
1552d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Object value = null;
1553d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1554d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // parse some stuff
1555d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        String str = tree.getChild(0).toString();
1556d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if ("conditionalExpression".equals(str)) {
1557d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            value = parseExpression((ParseTree) tree.getChild(0));
1558d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if ("annotation".equals(str)) {
1559d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            value = InfoBuilder.buildAnnotationInstance((ParseTree) tree.getChild(0), builder);
1560d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        } else if ("elementValueArrayInitializer".equals(str)) {
1561d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ParseTree child = (ParseTree) tree.getChild(0);
1562d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>();
1563d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object o : child.getChildren()) {
1564d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("elementValue".equals(o.toString())) {
1565d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    values.add(buildElementValue((ParseTree) o, builder));
1566d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1567d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1568d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1569d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            value = values;
1570d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1571d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1572d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        elementValue.init(value);
1573d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1574d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return elementValue;
1575d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1576d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1577d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1578d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Get the dimensions of the type, as a String.
1579d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse. type should be the root value.
1580d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return A String of the dimensions of the type.
1581d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1582d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private String getDimensions(ParseTree tree) {
1583d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // we only have dimensions if the count is not 1
1584d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (tree.getChildCount() == 1) {
1585d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return null;
1586d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1587d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1588d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        StringBuilder builder = new StringBuilder();
1589d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1590d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (int i = 1; i < tree.getChildCount(); i++) {
1591d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            builder.append(((ParseTree) tree.getChild(i)).toString());
1592d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1593d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1594d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return builder.toString();
1595d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1596d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1597d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1598d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * When we have data that we can't yet parse, save it for later.
1599d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param resolvable Resolvable to which the data refers.
1600d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param variable Variable in the document to which the data refers;
1601d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param value Value for the variable
16026ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein     * @param builder The InfoBuilder of this file
1603d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
16046ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static void addFutureResolution(Resolvable resolvable, String variable,
16056ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            String value, InfoBuilder builder) {
16066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        resolvable.addResolution(new Resolution(variable, value, builder));
1607d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1608d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Caches.addResolvableToCache(resolvable);
1609d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1610d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1611d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1612d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Turns a short name of a class into the qualified name of a class.
1613d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * StringBuilder will contain an empty string if not found.
1614d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param name the abbreviated name of the class
1615d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param qualifiedClassName the qualified name that will be set if found.
1616d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Unchanged if not found.
1617d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param builder InfoBuilder with all of the file specific information necessary
1618d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * to properly resolve the name.
1619d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return a boolean is returned that will be true if the type is a generic. false otherwise.
1620d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
16216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public static boolean resolveQualifiedName(String name,
1622d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                                StringBuilder qualifiedClassName,
1623d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                                InfoBuilder builder) {
1624d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // steps to figure out a class's real name
1625d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // check class(es) in this file
16266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
16276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // trying something out. let's see how this works
16286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (name.indexOf('.') != -1) {
16296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            qualifiedClassName.append(name);
16306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            return false;
16316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
16326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1633d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // TODO - search since we're now a HashSet
1634d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (String className : builder.getClassNames()) {
1635d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            int beginIndex = className.lastIndexOf(".") + 1;
1636d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1637d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (className.substring(beginIndex).equals(name)) {
1638d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                qualifiedClassName.append(className);
1639d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return qualifiedClassName.toString().equals(name);
1640d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1641d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1642d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1643d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // check package
1644d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ClassInfo potentialClass = builder.getPackage().getClass(name);
1645d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1646d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (potentialClass != null) {
1647d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            qualifiedClassName.append(potentialClass.qualifiedName());
1648d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return qualifiedClassName.toString().equals(name);
1649d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1650d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1651d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        potentialClass = null;
1652d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
16536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        String potentialName = null;
16546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        // check superclass and interfaces for type
16556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (builder.getRootClass() != null) {
16566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            potentialName = resolveQualifiedNameInInheritedClass(name, builder.getRootClass(),
16576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    builder.getRootClass().containingPackage().name());
16586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
16596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
16606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (potentialName != null) {
16616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            qualifiedClassName.append(potentialName);
16626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            return false;
16636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
16646ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
16656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1666d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // check class imports - ie, java.lang.String;
1667d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        ArrayList<String> packagesToCheck = new ArrayList<String>();
1668d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (String imp : builder.getImports()) {
1669d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            // +1 to get rid of off by 1 error
1670d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            String endOfName = imp.substring(imp.lastIndexOf('.') + 1);
1671d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (endOfName.equals(name) || (name.indexOf('.') != -1 &&
1672d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                           endOfName.equals(
1673d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                                   name.substring(0, name.lastIndexOf('.'))))) {
1674d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                qualifiedClassName.append(imp);
1675d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return qualifiedClassName.toString().equals(name);
1676d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            } else if (endOfName.equals("*")) {
1677d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                // add package to check
1678d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                packagesToCheck.add(imp.substring(0, imp.lastIndexOf('.')));
16796ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            } else {
16806ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                // check inner classes
16816ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                ClassInfo cl = Caches.obtainClass(imp);
16826ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                String possibleName = resolveQualifiedInnerName(cl.qualifiedName() + "." + name,
16836ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                        cl);
16846ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (possibleName != null) {
16856ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    qualifiedClassName.append(possibleName);
16866ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    return false;
16876ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
1688d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1689d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1690d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1691d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // check package imports - ie, java.lang.*;
1692d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (String packageName : packagesToCheck) {
1693d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            PackageInfo pkg = Caches.obtainPackage(packageName);
1694d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1695d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ClassInfo cls = pkg.getClass(name);
1696d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
16976ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (cls != null && name.equals(cls.name())) {
16986ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                qualifiedClassName.append(cls.qualifiedName());
1699d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                return qualifiedClassName.toString().equals(name);
1700d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1701d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1702d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        //     including import's inner classes...
1703d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // check package of imports...
1704d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1705d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // TODO - remove
1706d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // FROM THE JAVADOC VERSION OF THIS FUNCTION
1707d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // Find the specified class or interface within the context of this class doc.
1708d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // Search order: 1) qualified name, 2) nested in this class or interface,
1709d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // 3) in this package, 4) in the class imports, 5) in the package imports.
1710d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // Return the ClassDoc if found, null if not found.
1711d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1712d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return false;
1713d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1714d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
17156ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static String resolveQualifiedNameInInheritedClass(String name, ClassInfo cl,
17166ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            String originalPackage) {
17176ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        ArrayList<ClassInfo> classesToCheck = new ArrayList<ClassInfo>();
17186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (cl != null) {
17196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            // if we're in a new package only, check it
17206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (cl.containingPackage() != null &&
17216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    !originalPackage.equals(cl.containingPackage().name())) {
17226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                // check for new class
17236ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                ClassInfo cls = cl.containingPackage().getClass(name);
17246ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17256ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (cls != null && name.equals(cls.name())) {
17266ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    return cls.name();
17276ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
17286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (cl.realSuperclass() != null) {
17316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                classesToCheck.add(cl.realSuperclass());
17326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (cl.realInterfaces() != null) {
17356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                for (ClassInfo iface : cl.realInterfaces()) {
17366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    classesToCheck.add(iface);
17376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
17386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (ClassInfo cls : classesToCheck) {
17416ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                String potential = resolveQualifiedNameInInheritedClass(name, cls, originalPackage);
17426ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17436ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (potential != null) {
17446ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    return potential;
17456ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
17466ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17476ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
17486ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        return null;
17496ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
17506ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17516ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    private static String resolveQualifiedInnerName(String possibleQualifiedName, ClassInfo cl) {
17526ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        if (cl.innerClasses() == null) {
17536ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            return null;
17546ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
17556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        for (ClassInfo inner : cl.innerClasses()) {
17576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (possibleQualifiedName.equals(inner.qualifiedName())) {
17586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                return possibleQualifiedName;
17596ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17606ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17616ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            String name = resolveQualifiedInnerName(possibleQualifiedName + "." + inner.name(),
17626ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    inner);
17636ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17646ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (name != null) {
17656ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                return name;
17666ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
17676ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
17686ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
17696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        return null;
17706ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
17716ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
1772d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1773d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Parses the tree, looking for the comment and position.
1774d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @param tree The tree to parse.
1775d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * @return a CommentAndPosition object containing the comment and position of the element.
1776d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1777d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private CommentAndPosition parseCommentAndPosition(ParseTree tree) {
1778d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        Tree child = tree.getChild(0).getChild(0);
1779d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1780d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // three options (modifiers with annotations, modifiers w/o annotations, no modifiers)
1781d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // if there are no modifiers, use tree.getChild(1)
1782d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        // otherwise, dive as deep as possible into modifiers to get to the comment and position.
1783d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        child = ("<epsilon>".equals(child.toString())) ? tree.getChild(1) : child;
1784d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1785d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        while (child.getChildCount() > 0) {
1786d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            child = child.getChild(0);
1787d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1788d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1789d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        CommentAndPosition cAndP = new CommentAndPosition();
1790d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cAndP.setCommentText((ParseTree) child);
1791d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        cAndP.setPosition((ParseTree) child);
1792d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return cAndP;
1793d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1794d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1795d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1796d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Private class to facilitate passing the comment and position out of a function.
1797d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1798d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private class CommentAndPosition {
1799d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public String getCommentText() {
1800d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mCommentText;
1801d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1802d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1803d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        /**
1804d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * Parses the tree to get the commentText and set that value.
1805d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * @param tree The tree to parse. Should be pointing to the node containing the comment.
1806d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         */
1807d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public void setCommentText(ParseTree tree) {
1808d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (tree.hiddenTokens != null && !tree.hiddenTokens.isEmpty()) {
1809d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                mCommentText = ((CommonToken) tree.hiddenTokens.get(0)).getText();
1810d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1811d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if (mCommentText != null) {
1812d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    return;
1813d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1814d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1815d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1816d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            mCommentText = "";
1817d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1818d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1819d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public SourcePositionInfo getPosition() {
1820d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mPosition;
1821d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1822d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1823d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        /**
1824d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * Parses the tree to get the SourcePositionInfo of the node.
1825d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * @param tree The tree to parse. Should be pointing to the node containing the position.
1826d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         */
1827d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public void setPosition(ParseTree tree) {
1828d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          CommonToken token = (CommonToken) tree.payload;
1829d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1830d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          int line = token.getLine();
1831d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          int column = token.getCharPositionInLine();
1832d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          String fileName = ((ANTLRFileStream) token.getInputStream()).getSourceName();
1833d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1834d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          mPosition = new SourcePositionInfo(fileName, line, column);
1835d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1836d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1837d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private String mCommentText;
1838d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private SourcePositionInfo mPosition;
1839d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
1840d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1841d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1842d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Private class to handle all the possible modifiers to a class/interface/field/anything else.
1843d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
1844d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    private class Modifiers {
1845d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsPublic = false;
1846d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsProtected = false;
1847d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsPackagePrivate = true;
1848d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsPrivate = false;
1849d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsStatic = false;
1850d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsAbstract = false;
1851d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsFinal = false;
1852d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsTransient = false;
1853d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsVolatile = false;
1854d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsSynthetic = false;
1855d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsSynchronized = false;
1856d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private boolean mIsStrictfp = false;
18572e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller        private boolean mIsDefault = false;
1858d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private InfoBuilder mBuilder;
1859d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private ArrayList<AnnotationInstanceInfo> mAnnotations;
1860d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1861d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public Modifiers(InfoBuilder builder) {
1862d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            mAnnotations = new ArrayList<AnnotationInstanceInfo>();
1863d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            mBuilder = builder;
1864d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1865d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1866d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        /**
1867d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * Parses all of the modifiers of any declaration, including annotations.
1868d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         * @param tree
1869d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein         */
1870d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public void parseModifiers(ParseTree tree) {
1871d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Object child : tree.getChildren()) {
1872d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                String modifier = child.toString();
1873d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1874d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                if ("public".equals(modifier)) {
1875d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsPublic = true;
1876d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsPackagePrivate = false;
1877d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("protected".equals(modifier)) {
1878d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsProtected = true;
1879d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsPackagePrivate = false;
1880d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("private".equals(modifier)) {
1881d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsPrivate = true;
1882d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsPackagePrivate = false;
1883d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("static".equals(modifier)) {
1884d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsStatic = true;
1885d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("abstract".equals(modifier)) {
1886d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsAbstract = true;
1887d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("final".equals(modifier)) {
1888d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsFinal = true;
1889d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("transient".equals(modifier)) {
1890d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsTransient = true;
1891d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("volatile".equals(modifier)) {
1892d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsVolatile = true;
1893d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("synthetic".equals(modifier)) {
1894d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsSynthetic = true;
1895d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("synchronized".equals(modifier)) {
1896d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsSynchronized = true;
1897d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }  else if ("strictfp".equals(modifier)) {
1898d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mIsStrictfp = true;
18992e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller                }  else if ("default".equals(modifier)) {
19002e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller                    mIsDefault = true;
1901d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                } else if ("annotation".equals(modifier)) {
1902d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                    mAnnotations.add(buildAnnotationInstance((ParseTree) child, mBuilder));
1903d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                }
1904d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1905d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1906d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1907d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isPublic() {
1908d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsPublic;
1909d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1910d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1911d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isProtected() {
1912d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsProtected;
1913d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1914d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1915d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isPackagePrivate() {
1916d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsPackagePrivate;
1917d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1918d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1919d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isPrivate() {
1920d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsPrivate;
1921d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1922d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1923d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isStatic() {
1924d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsStatic;
1925d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1926d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1927d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isAbstract() {
1928d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsAbstract;
1929d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1930d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1931d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isFinal() {
1932d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsFinal;
1933d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1934d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1935d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isTransient() {
1936d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsTransient;
1937d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1938d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1939d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isVolatile() {
1940d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsVolatile;
1941d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1942d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1943d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isSynthetic() {
1944d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsSynthetic;
1945d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1946d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1947d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isSynchronized() {
1948d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsSynchronized;
1949d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1950d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1951d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        @SuppressWarnings("unused")
1952d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public boolean isStrictfp() {
1953d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mIsStrictfp;
1954d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1955d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
19562e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller        public boolean isDefault() {
19572e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller            return mIsDefault;
19582e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller        }
19592e954bda0291245d3dc56ea51ec49ef4ff3e610eNeil Fuller
1960d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public ArrayList<AnnotationInstanceInfo> getAnnotations() {
1961d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return mAnnotations;
1962d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1963d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    };
1964d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1965d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1966d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    /**
1967d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     * Singleton class to store all of the global data amongst every InfoBuilder.
1968d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein     */
19696ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public static class Caches {
1970d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private static HashMap<String, PackageInfo> mPackages
1971d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                        = new HashMap<String, PackageInfo>();
1972d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private static HashMap<String, ClassInfo> mClasses
1973d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                        = new HashMap<String, ClassInfo>();
1974d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        private static HashSet<Resolvable> mInfosToResolve
1975d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                                        = new HashSet<Resolvable>();
1976d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1977d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public static PackageInfo obtainPackage(String packageName) {
1978d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            PackageInfo pkg = mPackages.get(packageName);
1979d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1980d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (pkg == null) {
1981d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                pkg = new PackageInfo(packageName);
1982d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                mPackages.put(packageName, pkg);
1983d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
1984d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1985d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return pkg;
1986d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
1987d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
19886ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        /**
19896ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * Gets the ClassInfo from the master list or creates a new one if it does not exist.
19906ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * @param qualifiedClassName Qualified name of the ClassInfo to obtain.
19916ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * @return the ClassInfo
19926ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         */
1993d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public static ClassInfo obtainClass(String qualifiedClassName) {
1994d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            ClassInfo cls = mClasses.get(qualifiedClassName);
1995d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
1996d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            if (cls == null) {
1997d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                cls = new ClassInfo(qualifiedClassName);
1998d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                mClasses.put(cls.qualifiedName(), cls);
1999d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
2000d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2001d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            return cls;
2002d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
2003d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
20046ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        /**
20056ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * Gets the ClassInfo from the master list or returns null if it does not exist.
20066ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * @param qualifiedClassName Qualified name of the ClassInfo to obtain.
20076ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         * @return the ClassInfo or null, if the ClassInfo does not exist.
20086ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein         */
20096ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        public static ClassInfo getClass(String qualifiedClassName) {
20106ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            return mClasses.get(qualifiedClassName);
20116ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
20126ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
2013d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public static void addResolvableToCache(Resolvable resolvable) {
2014d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            mInfosToResolve.add(resolvable);
2015d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
2016d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2017d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        public static void printResolutions() {
20186ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            if (mInfosToResolve.isEmpty()) {
20196ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println("We've resolved everything.");
20206ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                return;
20216ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
20226ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
2023d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            for (Resolvable r : mInfosToResolve) {
2024d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                r.printResolutions();
2025d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein                System.out.println();
2026d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein            }
2027d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        }
20286ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
20296ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        public static void resolve() {
20306ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            HashSet<Resolvable> resolveList = mInfosToResolve;
20316ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            mInfosToResolve = new HashSet<Resolvable>();
20326ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
20336ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            for (Resolvable r : resolveList) {
20346ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                // if we could not resolve everything in this class
20356ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                if (!r.resolveResolutions()) {
20366ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                    mInfosToResolve.add(r);
20376ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                }
20386ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
20396ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein                System.out.println();
20406ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein            }
20416ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        }
2042d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
2043d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2044d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    public PackageInfo getPackage() {
2045d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return mPackage;
2046d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
2047d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2048d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    public ArrayList<String> getImports() {
2049d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return mImports;
2050d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
2051d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein
2052d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    public HashSet<String> getClassNames() {
2053d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        return mClassNames;
2054d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    }
20556ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein
20566ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    public ClassInfo getRootClass() {
20576ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein        return mRootClass;
20586ba612efffba42bec102ac58a1540496158f747eAndrew Sapperstein    }
2059d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein}
2060