1 package polyglot.types; 2 3 import polyglot.util.*; 4 import polyglot.main.Report; 5 6 import java.util.*; 7 8 9 16 public class ImportTable extends ClassResolver 17 { 18 protected TypeSystem ts; 19 20 21 protected Resolver resolver; 22 23 protected List packageImports; 24 25 protected Map map; 26 28 protected List lazyImports; 29 31 protected List classImports; 32 33 protected String sourceName; 34 35 protected Position sourcePos; 36 37 protected Package pkg; 38 39 private static final Object NOT_FOUND = "NOT FOUND"; 40 41 47 public ImportTable(TypeSystem ts, Resolver base, Package pkg) { 48 this(ts, base, pkg, null); 49 } 50 51 58 public ImportTable(TypeSystem ts, Resolver base, Package pkg, String src) { 59 this.resolver = base; 60 this.ts = ts; 61 this.sourceName = src; 62 this.sourcePos = src != null ? new Position(src) : null; 63 this.pkg = pkg; 64 65 this.map = new HashMap(); 66 this.packageImports = new ArrayList(); 67 this.lazyImports = new ArrayList(); 68 this.classImports = new ArrayList(); 69 } 70 71 74 public Package package_() { 75 return pkg; 76 } 77 78 81 public void addClassImport(String className) { 82 if (Report.should_report(TOPICS, 2)) 83 Report.report(2, this + ": lazy import " + className); 84 85 lazyImports.add(className); 86 classImports.add(className); 87 } 88 89 92 public void addPackageImport(String pkgName) { 93 if ((pkg != null && pkg.fullName().equals(pkgName)) || 96 ts.defaultPackageImports().contains(pkgName) || 97 packageImports.contains(pkgName)) { 98 return; 99 } 100 101 packageImports.add(pkgName); 102 } 103 104 107 public List packageImports() { 108 return packageImports; 109 } 110 111 114 public List classImports() { 115 return classImports; 116 } 117 118 121 public String sourceName() { 122 return sourceName; 123 } 124 125 129 protected Named cachedFind(String name) throws SemanticException { 130 Object res = map.get(name); 131 132 if (res != null) { 133 return (Named) res; 134 } 135 136 Named t = resolver.find(name); 137 map.put(name, t); 138 return t; 139 } 140 141 144 public Named find(String name) throws SemanticException { 145 if (Report.should_report(TOPICS, 2)) 146 Report.report(2, this + ".find(" + name + ")"); 147 148 149 lazyImport(); 150 151 if (!StringUtil.isNameShort(name)) { 152 return resolver.find(name); 154 } 155 156 Object res = map.get(name); 159 160 if (res != null) { 161 if (res == NOT_FOUND) { 162 throw new NoClassException(name, sourcePos); 163 } 164 return (Named) res; 165 } 166 167 try { 168 if (pkg != null) { 169 Named n = findInPkg(name, pkg.fullName()); 175 if (n != null) { 176 if (Report.should_report(TOPICS, 3)) 177 Report.report(3, this + ".find(" + name + "): found in current package"); 178 179 map.put(name, n); 181 return n; 182 } 183 } 184 185 List imports = new ArrayList(packageImports.size() + 5); 186 187 imports.addAll(ts.defaultPackageImports()); 188 imports.addAll(packageImports); 189 190 Named resolved = null; 192 for (Iterator iter = imports.iterator(); iter.hasNext(); ) { 193 String pkgName = (String ) iter.next(); 194 Named n = findInPkg(name, pkgName); 195 if (n != null) { 196 if (resolved == null) { 197 resolved = n; 202 } 203 else { 204 throw new SemanticException("Reference to \"" + 208 name + "\" is ambiguous; both " + 209 resolved.fullName() + " and " + n.fullName() + 210 " match."); 211 } 212 } 213 } 214 215 if (resolved == null) { 216 resolved = resolver.find(name); 220 if (!isVisibleFrom(resolved, "")) { 221 throw new NoClassException(name, sourcePos); 223 } 224 } 225 226 if (Report.should_report(TOPICS, 3)) 228 Report.report(3, this + ".find(" + name + "): found as " + resolved.fullName()); 229 map.put(name, resolved); 230 return resolved; 231 } 232 catch (NoClassException e) { 233 if (Report.should_report(TOPICS, 3)) 235 Report.report(3, this + ".find(" + name + "): didn't find it"); 236 map.put(name, NOT_FOUND); 237 throw e; 238 } 239 } 240 241 protected Named findInPkg(String name, String pkgName) throws SemanticException { 242 String fullName = pkgName + "." + name; 243 244 try { 245 Named n = resolver.find(pkgName); 246 247 if (n instanceof ClassType) { 248 n = ts.classContextResolver((ClassType) n).find(name); 249 return n; 250 } 251 } 252 catch (NoClassException ex) { 253 } 255 256 try { 257 Named n = resolver.find(fullName); 258 259 if (isVisibleFrom(n, pkgName)) { 261 return n; 262 } 263 } 264 catch (NoClassException ex) { 265 } 267 268 return null; 269 } 270 271 276 protected boolean isVisibleFrom(Named n, String pkgName) { 277 boolean isVisible = false; 278 boolean inSamePackage = this.pkg != null 279 && this.pkg.fullName().equals(pkgName) 280 || this.pkg == null 281 && pkgName.equals(""); 282 if (n instanceof Type) { 283 Type t = (Type) n; 284 isVisible = !t.isClass() 286 || t.toClass().flags().isPublic() 287 || inSamePackage; 288 } else { 289 isVisible = true; 291 } 292 return isVisible; 293 } 294 295 298 protected void lazyImport() throws SemanticException { 299 if (lazyImports.isEmpty()) { 300 return; 301 } 302 303 for (int i = 0; i < lazyImports.size(); i++) { 304 String longName = (String ) lazyImports.get(i); 305 306 if (Report.should_report(TOPICS, 2)) 307 Report.report(2, this + ": import " + longName); 308 309 try { 310 StringTokenizer st = new StringTokenizer(longName, "."); 314 StringBuffer name = new StringBuffer (); 315 Named t = null; 316 317 while (st.hasMoreTokens()) { 318 String s = st.nextToken(); 319 name.append(s); 320 321 try { 322 t = cachedFind(name.toString()); 323 324 if (! st.hasMoreTokens()) { 325 break; 327 } 328 329 if (t instanceof ClassType) { 330 ClassType ct = (ClassType) t; 333 334 while (st.hasMoreTokens()) { 335 String n = st.nextToken(); 336 t = ct = ts.findMemberClass(ct, n); 337 338 map.put(n, ct); 340 } 341 } 342 else { 343 throw new InternalCompilerError("Qualified type \"" + t + "\" is not a class type.", sourcePos); 346 } 347 } 348 catch (SemanticException e) { 349 if (! st.hasMoreTokens()) { 350 throw e; 351 } 352 353 name.append("."); 355 } 356 } 357 358 String shortName = StringUtil.getShortNameComponent(longName); 359 360 if (Report.should_report(TOPICS, 2)) 361 Report.report(2, this + ": import " + shortName + " as " + t); 362 363 if (map.containsKey(shortName)) { 364 Named s = (Named) map.get(shortName); 365 366 if (! ts.equals(s, t)) { 367 throw new SemanticException("Class " + shortName + 368 " already defined as " + map.get(shortName), 369 sourcePos); 370 } 371 } 372 373 map.put(shortName, t); 375 } 376 catch (SemanticException e) { 377 if (e.position == null) { 378 e.position = sourcePos; 379 } 380 381 throw e; 382 } 383 } 384 385 lazyImports = new ArrayList(); 386 } 387 388 public String toString() { 389 if (sourceName != null) { 390 return "(import " + sourceName + ")"; 391 } 392 else { 393 return "(import)"; 394 } 395 } 396 397 private static final Collection TOPICS = 398 CollectionUtil.list(Report.types, Report.resolver, Report.imports); 399 400 } 401 | Popular Tags |