1 19 package org.netbeans.modules.java.source.pretty; 20 21 import com.sun.tools.javac.code.*; 22 import com.sun.tools.javac.code.Symbol.*; 23 import com.sun.tools.javac.tree.JCTree.*; 24 import com.sun.tools.javac.tree.JCTree; 25 import com.sun.tools.javac.tree.TreeInfo; 26 import com.sun.tools.javac.tree.TreeScanner; 27 import com.sun.tools.javac.util.List; 28 29 import java.util.Set ; 30 import java.util.HashSet ; 31 import java.util.logging.Logger ; 32 33 public class ImportAnalysis extends TreeScanner { 34 int starThreshhold; 35 int useThreshhold; 36 private static final int implicitImport = 9999; 37 SymRefStats usedClasses, usedClassOwners; 38 public PackageSymbol containingPackage; 39 public ClassSymbol containingClass; 40 Symtab syms; 41 boolean includeExplicit; 42 43 public ImportAnalysis (int st, int ut, JCCompilationUnit t, Symtab syms, Types types) { 44 this(st, ut, t, syms, types, true); 45 } 46 47 public ImportAnalysis (int st, int ut, JCCompilationUnit t, Symtab syms, Types types, boolean explicit) { 48 starThreshhold = st; 49 useThreshhold = ut; 50 this.syms = syms; 51 includeExplicit = explicit; 52 containingPackage = t.packge; 53 if (containingPackage == null) 54 Logger.getLogger("org.netbeans.modules.java.source").warning( 55 "null package element in " + t.getSourceFile().toUri().getPath()); 56 usedClassOwners = setImplicit(usedClassOwners, containingPackage); 57 usedClassOwners = setImplicit(usedClassOwners, syms.objectType.tsym.owner); if(t!=null) t.accept(this); 59 } 60 public boolean starred(Symbol s) { 61 for (SymRefStats p = usedClassOwners; p != null; p = p.next) 62 if (p.clazz == s) 63 return p.imported; 64 return false; 65 } 66 public boolean imported(Symbol s) { 67 for (SymRefStats p = usedClasses; p != null; p = p.next) 68 if (p.clazz == s) 69 return p.imported; 70 if(starred(s.owner)) return true; 71 return false; 72 } 73 74 78 public Set <Symbol> neededImports(List<JCImport> imports) { 79 Set <Symbol> starred = new HashSet <Symbol>(8); 81 Set <Symbol> explicit = new HashSet <Symbol>(8); 82 while (imports.nonEmpty()) { 83 JCTree qualid = imports.head.qualid; 84 if (qualid.tag == JCTree.SELECT) { 85 JCFieldAccess s = (JCFieldAccess)qualid; 86 Symbol sym = s.sym; 87 if (sym == null) { 88 JCTree selected = s.selected; 89 sym = selected.tag == JCTree.SELECT ? 90 ((JCFieldAccess)selected).sym : ((JCIdent)selected).sym; 91 if (sym != null) { 93 starred.add(sym); 94 } 95 } else 96 explicit.add(sym); 97 } 98 else if (qualid.tag == JCTree.IDENT) 99 explicit.add(((JCIdent)qualid).sym); 100 else 101 throw new AssertionError ("unknown qualid tree type"); 102 imports = imports.tail; 103 } 104 105 starred.add(containingPackage); 107 starred.add(syms.objectType.tsym.owner); 109 Set <Symbol> missing = new HashSet <Symbol>(); 110 for (SymRefStats p = usedClasses; p != null; p = p.next) { 111 boolean alreadyImported = p.implicitlyImported() || 112 explicit.contains(p.clazz) || starred.contains(p.clazz.owner); 113 p.imported = alreadyImported || p.used >= useThreshhold; 114 if (!alreadyImported) { 115 if (p.imported) 116 for (SymRefStats q = usedClasses; q != null; q = q.next) 117 if (q != p && q.clazz.name == p.clazz.name) { 118 p.imported = false; 119 break; 120 } 121 if (p.imported && otherPackageHasClassName(p)) 122 p.imported = false; 123 if (p.imported && !alreadyImported) 124 missing.add(p.clazz); 125 } 126 } 127 return missing; 128 } 129 130 public void decideImports() { 131 for (SymRefStats p = usedClassOwners; p != null; p = p.next) 132 p.imported = p.used >= starThreshhold; 133 for (SymRefStats p = usedClasses; p != null; p = p.next) { 134 boolean imported = false; 135 if (p.used >= useThreshhold || starred(p.clazz.owner)) { 136 imported = true; 137 for (SymRefStats q = usedClasses; q != p; q = q.next) 138 if (q.clazz.name == p.clazz.name) { 139 141 if (p.implicitlyImported()) 142 q.imported = false; 143 else imported = false; 144 break; 145 } 146 if (otherPackageHasClassName(p)) 147 imported = false; 148 } 149 p.imported = imported; 150 } 151 } 152 153 private boolean otherPackageHasClassName(SymRefStats p) { 154 for(SymRefStats r = usedClassOwners; r!=null; r=r.next) 155 if(r.imported && r.clazz != p.clazz.owner) { 156 Scope sc = r.clazz.members(); 157 if(sc==null) continue; 158 Scope.Entry alt = sc.lookup(p.clazz.name); 159 if(alt.scope==sc && alt.sym.kind==Kinds.TYP) 160 return false; 161 } 162 return true; 163 } 164 165 private void found2(Symbol s) { 166 if (s instanceof ClassSymbol 167 && (s.owner instanceof PackageSymbol 168 || s.owner instanceof ClassSymbol) 169 && s.owner != syms.rootPackage 170 && s.owner != syms.unnamedPackage) { 171 SymRefStats ns = incref(usedClasses, s); 172 if (ns != usedClasses && s.owner != null) 173 usedClassOwners = incref(usedClassOwners, s.owner); 174 usedClasses = ns; 175 } 176 } 177 private void found(Type t) { 178 while (t instanceof Type.ArrayType) 179 t = ((Type.ArrayType) t).elemtype; 180 if (t != null && t.tag == TypeTags.CLASS) 181 found2(t.tsym); 182 if (t instanceof Type.ClassType) { 183 List < Type > typarams = ((Type.ClassType) t).typarams_field; 184 if (typarams != null) 185 for (; typarams.nonEmpty(); typarams = typarams.tail) 186 found(typarams.head); 187 } 188 } 189 private SymRefStats setImplicit(SymRefStats set, Symbol cs) { 190 for (SymRefStats p = set; p != null; p = p.next) 191 if (p.clazz == cs) { 192 p.setImplicit(); 193 return set; 194 } 195 set = new SymRefStats(cs, set); 196 set.setImplicit(); 197 return set; 198 } 199 private SymRefStats incref(SymRefStats set, Symbol cs) { 200 for (SymRefStats p = set; p != null; p = p.next) 201 if (p.clazz == cs) { 202 if(!p.implicitlyImported()) 203 p.used++; 204 return set; 205 } 206 return new SymRefStats(cs, set); 207 } 208 public int used(SymRefStats set, Symbol cs) { 209 for (SymRefStats p = set; p != null; p = p.next) 210 if (p.clazz == cs) 211 return p.used; 212 return 0; 213 } 214 215 @Override 216 public void visitTopLevel(JCCompilationUnit tree) { 217 scan(tree.defs); 218 } 219 @Override 220 public void visitImport(JCImport tree) { 221 } 223 @Override 224 public void visitClassDef(JCClassDecl tree) { 225 if (tree.sym == null) return; usedClasses = setImplicit(usedClasses, tree.sym); 227 usedClassOwners = setImplicit(usedClassOwners, tree.sym); 228 if ((tree.mods.flags & Flags.PUBLIC) != 0 || containingClass == null) 230 containingClass = tree.sym; 231 super.visitClassDef(tree); 232 } 233 @Override 234 public void visitSelect(JCFieldAccess tree) { 235 Symbol ssym = TreeInfo.symbol(tree.selected); 236 if (ssym != null && ssym.kind == Kinds.TYP && !explicitReference(tree)) { 237 found(tree.selected.type); 238 } else if (includeExplicit || !explicitReference(tree)) 239 super.visitSelect(tree); 240 } 241 @Override 242 public void visitIdent(JCIdent tree) { 243 if (tree.sym instanceof ClassSymbol) 244 found(tree.type); 245 } 246 @Override 247 public void visitErroneous(JCErroneous tree) { 248 scan(tree.errs); 249 } 250 251 252 private boolean explicitReference(JCFieldAccess tree) { 253 Symbol ssym = TreeInfo.symbol(tree.selected); 254 if (ssym != null && ssym.kind == Kinds.PCK) 255 return true; 256 return ssym != null && tree.selected.tag == JCTree.SELECT 257 ? explicitReference((JCFieldAccess)tree.selected) : false; 258 } 259 260 261 static class SymRefStats { 262 int used = 1; 263 boolean imported = false; 264 final Symbol clazz; 265 final SymRefStats next; 266 public final void setImplicit() { 267 used = implicitImport; 268 } 269 public final boolean implicitlyImported() { 270 return used == implicitImport; 271 } 272 SymRefStats (Symbol cs, SymRefStats n) { 273 clazz = cs; 274 next = n; 275 } 276 } 277 } 278 | Popular Tags |