KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > pretty > ImportAnalysis2


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.source.pretty;
21
22 import com.sun.source.tree.ClassTree;
23 import com.sun.source.tree.ExpressionTree;
24 import com.sun.source.tree.IdentifierTree;
25 import com.sun.source.tree.ImportTree;
26 import com.sun.source.tree.MemberSelectTree;
27 import com.sun.source.tree.Tree;
28 import com.sun.source.tree.Tree.Kind;
29 import com.sun.source.util.TreeScanner;
30 import com.sun.source.util.Trees;
31 import com.sun.tools.javac.code.Symtab;
32 import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
33 import com.sun.tools.javac.tree.JCTree.JCIdent;
34 import java.util.ArrayList JavaDoc;
35 import java.util.Collections JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.List JavaDoc;
39 import java.util.Map JavaDoc;
40 import java.util.Set JavaDoc;
41 import java.util.Stack JavaDoc;
42 import javax.lang.model.element.Element;
43 import javax.lang.model.element.ElementKind;
44 import javax.lang.model.element.Modifier;
45 import javax.lang.model.element.PackageElement;
46 import javax.lang.model.element.PackageElement;
47 import javax.lang.model.element.TypeElement;
48 import javax.lang.model.util.ElementFilter;
49 import javax.lang.model.util.Elements;
50 import javax.lang.model.util.Types;
51 import org.netbeans.api.java.source.WorkingCopy;
52 import org.netbeans.api.java.source.query.QueryEnvironment;
53 import org.netbeans.modules.java.source.engine.ASTModel;
54 import org.netbeans.modules.java.source.engine.EngineEnvironment;
55 import org.netbeans.api.java.source.transform.ChangeSet;
56 import org.netbeans.modules.java.source.engine.TreeMakerInt;
57
58 /**
59  *
60  * @author Jan Lahoda
61  */

62 public class ImportAnalysis2 {
63     
64     private Elements elements;
65     private Types types;
66     private Trees trees;
67     private ASTModel model;
68     private TreeMakerInt make;
69     private List JavaDoc<ImportTree> imports;
70     private Set JavaDoc<Element> imported;
71     private Stack JavaDoc<Set JavaDoc<Element>> visibleThroughClasses;
72     private Map JavaDoc<String JavaDoc, Element> simpleNames2Elements;
73     private PackageElement unnamedPackage;
74     private PackageElement pack;
75     
76     private ChangeSet changes;
77     private WorkingCopy copy;
78     
79     public ImportAnalysis2(QueryEnvironment env) {
80         elements = env.getElements();
81         types = env.getTypes();
82         model = ((EngineEnvironment)env).getModel();
83         make = env.getTreeMaker();
84         trees = env.getTrees();
85         
86         unnamedPackage = Symtab.instance(((EngineEnvironment) env).getContext()).unnamedPackage;
87     }
88     
89     public void setPackage(ExpressionTree packageNameTree) {
90         if (packageNameTree == null) {
91             //if there is no package declaration in the code, unnamedPackage should be used:
92
this.pack = unnamedPackage;
93             return ;
94         }
95         
96         String JavaDoc packageName = getFQN(packageNameTree);
97         
98         this.pack = elements.getPackageElement(packageName);
99     }
100     
101     public void setImports(List JavaDoc<? extends ImportTree> importsToAdd) {
102         imports = new ArrayList JavaDoc<ImportTree>();
103         imported = new HashSet JavaDoc<Element>();
104         simpleNames2Elements = new HashMap JavaDoc<String JavaDoc, Element>();
105         visibleThroughClasses = new Stack JavaDoc<Set JavaDoc<Element>>();
106         
107         for (ImportTree imp : importsToAdd) {
108             addImport(imp, false);
109         }
110     }
111     
112     public List JavaDoc<? extends ImportTree> getImports() {
113         return imports;
114     }
115     
116     public void classEntered(ClassTree clazz) {
117         Set JavaDoc<Element> visible = new HashSet JavaDoc<Element>();
118         
119         addAll(clazz.getExtendsClause(), visible);
120         
121         for (Tree t : clazz.getImplementsClause()) {
122             addAll(t, visible);
123         }
124         
125         visibleThroughClasses.push(visible);
126     }
127     
128     public void classLeft() {
129         visibleThroughClasses.pop();
130     }
131     
132     private String JavaDoc getFQN(ImportTree imp) {
133         return getFQN(imp.getQualifiedIdentifier());
134     }
135     
136     private String JavaDoc getFQN(Tree expression) {
137         final StringBuffer JavaDoc result = new StringBuffer JavaDoc();
138         
139         new TreeScanner<Void JavaDoc, Void JavaDoc>() {
140             public Void JavaDoc visitMemberSelect(MemberSelectTree tree, Void JavaDoc p) {
141                 super.visitMemberSelect(tree, p);
142                 result.append('.');
143                 result.append(tree.getIdentifier().toString());
144                 return null;
145             }
146             public Void JavaDoc visitIdentifier(IdentifierTree tree, Void JavaDoc p) {
147                 result.append(tree.getName().toString());
148                 return null;
149             }
150         }.scan(expression, null);
151         
152         return result.toString();
153     }
154     
155     private void addImport(ImportTree imp, boolean sort) {
156         String JavaDoc fqn = getFQN(imp);
157         
158         if (!imp.isStatic()) {
159             TypeElement resolve = elements.getTypeElement(fqn);
160             
161             if (resolve != null) {
162                 imported.add(resolve);
163                 simpleNames2Elements.put(resolve.getSimpleName().toString(), resolve);
164             } else {
165                 //.*?:
166
if (fqn.endsWith(".*")) {
167                     fqn = fqn.substring(0, fqn.length() - 2);
168                     
169                     List JavaDoc<TypeElement> classes = Collections.<TypeElement>emptyList();
170                     TypeElement clazz = elements.getTypeElement(fqn);
171                     
172                     if (clazz != null) {
173                         classes = ElementFilter.typesIn(clazz.getEnclosedElements());
174                     } else {
175                         PackageElement pack = elements.getPackageElement(fqn);
176                         
177                         if (pack != null) {
178                             classes = ElementFilter.typesIn(pack.getEnclosedElements());
179                         } else {
180                             //cannot resolve - the imports will probably not work correctly...
181
}
182                     }
183                     
184                     for (TypeElement te : classes) {
185                         imported.add(te);
186                         simpleNames2Elements.put(te.getSimpleName().toString(), te);
187                     }
188                 } else {
189                     //cannot resolve - the imports will probably not work correctly...
190
}
191             }
192         } else {
193             int dot = fqn.lastIndexOf('.');
194             
195             if (dot != (-1)) {
196                 String JavaDoc className = fqn.substring(0, dot);
197                 String JavaDoc memberName = fqn.substring(dot + 1);
198                 boolean isStarred = "*".equals(memberName);
199                 TypeElement resolved = elements.getTypeElement(className);
200                 
201                 if (resolved != null) {
202                     for (Element e : resolved.getEnclosedElements()) {
203                         if (!e.getModifiers().contains(Modifier.STATIC))
204                             continue;
205                         
206                         if (isStarred || memberName.contains(e.getSimpleName().toString())) {
207                             imported.add(e);
208                             simpleNames2Elements.put(e.getSimpleName().toString(), e);
209                         }
210                     }
211                 } else {
212                     //cannot resolve - the imports will probably not work correctly...
213
}
214             } else {
215                 //no dot?
216
}
217         }
218         
219         if (!sort) {
220             imports.add(imp);
221         } else {
222             //not very efficient to compute FQNs again and again:
223
int point = -1;
224             
225             for (int cntr = 0; cntr < imports.size(); cntr++) {
226                 String JavaDoc currentFQN = getFQN(imports.get(cntr));
227                 
228                 if (currentFQN.compareTo(fqn) < 0) {
229                     point = cntr;
230                 } else {
231                     //== 0 should never happen
232
break;
233                 }
234             }
235             
236             imports.add(point + 1, imp);
237         }
238     }
239     
240     //Note: this method should return either "orig" or a IdentifierTree or MemberSelectTree
241
//no other tree type is not allowed - see ImmutableTreeTranslator.translateStable(Tree)
242
public ExpressionTree resolveImport(MemberSelectTree orig, Element element) {
243         if (visibleThroughClasses == null) {
244             //may happen for package clause
245
return orig;
246         }
247         //if type is already accessible, do not import:
248
for (Set JavaDoc<Element> els : visibleThroughClasses) {
249             if (els.contains(element))
250                 return make.Identifier(element.getSimpleName());
251         }
252         
253         //in the same package:
254
if (element.getKind().isClass() || element.getKind().isInterface()) {
255             Element parent = element.getEnclosingElement();
256             
257             if (pack != null && pack.equals(parent)) {
258                 //in the same package:
259
return make.Identifier(element.getSimpleName());
260             }
261         }
262         
263         if (imported.contains(element)) {
264             return make.Identifier(element.getSimpleName());
265         }
266         
267         Element alreadyImported = simpleNames2Elements.get(element.getSimpleName().toString());
268         
269         if (alreadyImported != null && !element.equals(alreadyImported)) {
270             //clashing import, use FQN:
271
model.setElement(orig, null);
272             model.setType(orig, null);
273             return orig;
274         }
275         
276         //no creation of static imports yet, import class for fields and methods:
277
if (!element.getKind().isClass() && !element.getKind().isInterface()) {
278             ExpressionTree clazz = orig.getExpression();
279             
280             if (clazz.getKind() == Kind.MEMBER_SELECT)
281                 clazz = resolveImport((MemberSelectTree) clazz, element.getEnclosingElement());
282             
283             return make.MemberSelect(clazz, orig.getIdentifier());
284         }
285         
286         TypeElement type = (TypeElement) element;
287         
288         //check for java.lang:
289
Element parent = type.getEnclosingElement();
290         
291         if (parent.getKind() == ElementKind.PACKAGE) {
292             if ("java.lang".equals(((PackageElement) parent).getQualifiedName().toString())) {
293                 return make.Identifier(element.getSimpleName());
294             }
295         }
296         
297         Tree imp = make.QualIdentImpl(element);
298         addImport(make.Import(imp, false), true);
299         
300         return make.Identifier(element.getSimpleName());
301     }
302     
303     private void addAll(Tree t, Set JavaDoc<Element> visible) {
304         if (t == null)
305             return;
306         
307         Element e = null;
308         
309         if (t.getKind() == Kind.MEMBER_SELECT) {
310             e = ((JCFieldAccess) t).sym;
311         } else {
312             if (t.getKind() == Kind.IDENTIFIER) {
313                 e = ((JCIdent) t).sym;
314             }
315         }
316         
317         if (e == null)
318             return;
319         
320         visible.addAll(e.getEnclosedElements());
321     }
322     
323 }
324
Popular Tags