Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/puppycrawl/tools/checkstyle/checks/usage/transmogrify/ASTManager.java


1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2003  Oliver Burn
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  package com.puppycrawl.tools.checkstyle.checks.usage.transmogrify;
20  
21  import java.io.File;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.IdentityHashMap;
25  import java.util.Iterator;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import antlr.collections.AST;
30  
31  import com.puppycrawl.tools.checkstyle.checks.usage.AbstractUsageCheck;
32  
33  /**
34   * Manages AST trees and nodes. Capable of managing multiple parse trees, which
35   * is useful for inter-file checks.
36   * @author Rick Giles
37   */
38  public final class ASTManager
39  {
40      /** singleton */
41      private static final ASTManager INSTANCE = new ASTManager();
42  
43      /** maps DetailASTs to SymTabASTs. */
44      private Map mMap = new IdentityHashMap();
45  
46      /** root with subtrees for a set of files */
47      private SymTabAST mCompleteTree = null;
48  
49      /** Map for parse trees, keyed on File name */
50      private Map mTrees = new HashMap();
51  
52      /** Set of checks and their nodes to check */
53      private Map mCheckNodes = new HashMap();
54  
55      /** prevent client creation */
56      private ASTManager()
57      {
58      }
59  
60      /**
61       * Returns the singleon ASTManager.
62       * @return the singleon ASTManager.
63       */
64      public static ASTManager getInstance()
65      {
66          return INSTANCE;
67      }
68  
69      /**
70       * Add the parse tree for a file to the set of parse trees.
71       * @param aFileName the name of the file.
72       * @param aRoot the root of the AST.
73       */
74      public void addTree(String aFileName, AST aRoot)
75      {
76          mTrees.put(aFileName, aRoot);
77      }
78  
79      /**
80       * Builds the complete tree for all added parse trees.
81       * @throws SymbolTableException if there is an error.
82       */
83      private void buildTree()
84          throws SymbolTableException
85      {
86          mCompleteTree = SymTabASTFactory.create(0, "AST Root");
87          final Set keys = mTrees.keySet();
88          final Iterator it = keys.iterator();
89          while (it.hasNext()) {
90              final String fileName = (String) it.next();
91              final File file = new File(fileName);
92              final AST rootAST = (AST) mTrees.get(fileName);
93              addToCompleteTree(file, rootAST);
94          }
95  
96          // Walk of the complete tree.
97          // TODO: This is a hack. Find a better way.
98          final SymbolTable table = new TableMaker(mCompleteTree).getTable();
99      }
100 
101     /**
102      * Adds a file and a DetailAST to the root SymTabAST tree. Normally, the
103      * DetailAST will be the parse tree for the file.
104      * @param aFile the file to add.
105      * @param aAST the DetailAST to add.
106     */
107     private void addToCompleteTree(File aFile, AST aAST)
108     {
109         // add aFile to the root
110         final SymTabAST fileNode =
111             SymTabASTFactory.create(0, aFile.getAbsolutePath());
112         fileNode.setFile(aFile);
113         mCompleteTree.addChild(fileNode);
114         fileNode.setParent(mCompleteTree);
115 
116         // add aAST to aFile
117         final SymTabAST child = SymTabASTFactory.create(aAST);
118         child.setFile(aFile);
119         fileNode.addChild(child);
120         child.setParent(fileNode);
121         fileNode.finishDefinition(aFile, mCompleteTree);
122     }
123 
124     /**
125      * Registers a node for checking.
126      * @param aCheck the check to apply.
127      * @param aNode the node to check.
128      */
129     public void registerCheckNode(AbstractUsageCheck aCheck, AST aNode)
130     {
131         Set nodeSet = (Set) mCheckNodes.get(aCheck);
132         if (nodeSet == null) {
133             nodeSet = new HashSet();
134             nodeSet.add(aNode);
135             mCheckNodes.put(aCheck, nodeSet);
136         }
137         else {
138             nodeSet.add(aNode);
139         }
140     }
141 
142     /**
143      * Gets the nodes to check with a usage check.
144      * @param aCheck the usage check.
145      * @return the nodes to check with aCheck.
146      * @throws SymbolTableException if there is an error.
147      */
148     public Set getCheckNodes(AbstractUsageCheck aCheck)
149         throws SymbolTableException
150     {
151         // lazy initialization
152         if (mCompleteTree == null) {
153             buildTree();
154         }
155         Set result = (Set) mCheckNodes.get(aCheck);
156         if (result == null) {
157             result = new HashSet();
158         }
159         return result;
160     }
161 
162     /**
163      * Maps a AST to its associated SymTabAST.
164      * @param aAST the AST.
165      * @param aSymTabAST the SymTabAST associated with aAST.
166      */
167     public void put(AST aAST, SymTabAST aSymTabAST)
168     {
169         mMap.put(aAST, aSymTabAST);
170     }
171 
172     /**
173      * Gets the SymTabAST associated with a AST.
174      * @param aAST the AST.
175      * @return the the SymTabAST associated with aAST.
176      */
177     public SymTabAST get(AST aAST)
178     {
179         return (SymTabAST) mMap.get(aAST);
180     }
181 
182     /**
183      * Clears all associations from DetailsASTs to SymTabASTs.
184      */
185     public void clearDetailsMap()
186     {
187         mMap.clear();
188     }
189 
190     /**
191      * Determines whether the map from DetailsASTs to SymTabASTs is empty.
192      * @return true if the map is empty.
193      */
194     public boolean isEmptyDetailsMap()
195     {
196         return mMap.isEmpty();
197     }
198 
199     /**
200      * Removes a check and its check nodes. Clears all managed elements if
201      * last check removed.
202      * @param aCheck the check to remove.
203      */
204     public void removeCheck(AbstractUsageCheck aCheck)
205     {
206         mCheckNodes.remove(aCheck);
207         if (mCheckNodes.isEmpty()) {
208             mCompleteTree = null;
209             mMap.clear();
210             mTrees.clear();
211         }
212     }
213 }