Thu, 12 Oct 2017 19:44:07 +0800
merge
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. Oracle designates this |
aoqi@0 | 8 | * particular file as subject to the "Classpath" exception as provided |
aoqi@0 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
aoqi@0 | 10 | * |
aoqi@0 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 15 | * accompanied this code). |
aoqi@0 | 16 | * |
aoqi@0 | 17 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 20 | * |
aoqi@0 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 22 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 23 | * questions. |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | package com.sun.codemodel.internal; |
aoqi@0 | 27 | |
aoqi@0 | 28 | import java.io.PrintWriter; |
aoqi@0 | 29 | import java.io.Writer; |
aoqi@0 | 30 | import java.util.ArrayList; |
aoqi@0 | 31 | import java.util.Arrays; |
aoqi@0 | 32 | import java.util.Collection; |
aoqi@0 | 33 | import java.util.HashMap; |
aoqi@0 | 34 | import java.util.HashSet; |
aoqi@0 | 35 | import java.util.Iterator; |
aoqi@0 | 36 | import java.util.List; |
aoqi@0 | 37 | |
aoqi@0 | 38 | |
aoqi@0 | 39 | /** |
aoqi@0 | 40 | * This is a utility class for managing indentation and other basic |
aoqi@0 | 41 | * formatting for PrintWriter. |
aoqi@0 | 42 | */ |
aoqi@0 | 43 | public final class JFormatter { |
aoqi@0 | 44 | /** all classes and ids encountered during the collection mode **/ |
aoqi@0 | 45 | /** map from short type name to ReferenceList (list of JClass and ids sharing that name) **/ |
aoqi@0 | 46 | private HashMap<String,ReferenceList> collectedReferences; |
aoqi@0 | 47 | |
aoqi@0 | 48 | /** set of imported types (including package java types, eventhough we won't generate imports for them) */ |
aoqi@0 | 49 | private HashSet<JClass> importedClasses; |
aoqi@0 | 50 | |
aoqi@0 | 51 | private static enum Mode { |
aoqi@0 | 52 | /** |
aoqi@0 | 53 | * Collect all the type names and identifiers. |
aoqi@0 | 54 | * In this mode we don't actually generate anything. |
aoqi@0 | 55 | */ |
aoqi@0 | 56 | COLLECTING, |
aoqi@0 | 57 | /** |
aoqi@0 | 58 | * Print the actual source code. |
aoqi@0 | 59 | */ |
aoqi@0 | 60 | PRINTING |
aoqi@0 | 61 | } |
aoqi@0 | 62 | |
aoqi@0 | 63 | /** |
aoqi@0 | 64 | * The current running mode. |
aoqi@0 | 65 | * Set to PRINTING so that a casual client can use a formatter just like before. |
aoqi@0 | 66 | */ |
aoqi@0 | 67 | private Mode mode = Mode.PRINTING; |
aoqi@0 | 68 | |
aoqi@0 | 69 | /** |
aoqi@0 | 70 | * Current number of indentation strings to print |
aoqi@0 | 71 | */ |
aoqi@0 | 72 | private int indentLevel; |
aoqi@0 | 73 | |
aoqi@0 | 74 | /** |
aoqi@0 | 75 | * String to be used for each indentation. |
aoqi@0 | 76 | * Defaults to four spaces. |
aoqi@0 | 77 | */ |
aoqi@0 | 78 | private final String indentSpace; |
aoqi@0 | 79 | |
aoqi@0 | 80 | /** |
aoqi@0 | 81 | * Stream associated with this JFormatter |
aoqi@0 | 82 | */ |
aoqi@0 | 83 | private final PrintWriter pw; |
aoqi@0 | 84 | |
aoqi@0 | 85 | /** |
aoqi@0 | 86 | * Creates a JFormatter. |
aoqi@0 | 87 | * |
aoqi@0 | 88 | * @param s |
aoqi@0 | 89 | * PrintWriter to JFormatter to use. |
aoqi@0 | 90 | * |
aoqi@0 | 91 | * @param space |
aoqi@0 | 92 | * Incremental indentation string, similar to tab value. |
aoqi@0 | 93 | */ |
aoqi@0 | 94 | public JFormatter(PrintWriter s, String space) { |
aoqi@0 | 95 | pw = s; |
aoqi@0 | 96 | indentSpace = space; |
aoqi@0 | 97 | collectedReferences = new HashMap<String,ReferenceList>(); |
aoqi@0 | 98 | //ids = new HashSet<String>(); |
aoqi@0 | 99 | importedClasses = new HashSet<JClass>(); |
aoqi@0 | 100 | } |
aoqi@0 | 101 | |
aoqi@0 | 102 | /** |
aoqi@0 | 103 | * Creates a formatter with default incremental indentations of |
aoqi@0 | 104 | * four spaces. |
aoqi@0 | 105 | */ |
aoqi@0 | 106 | public JFormatter(PrintWriter s) { |
aoqi@0 | 107 | this(s, " "); |
aoqi@0 | 108 | } |
aoqi@0 | 109 | |
aoqi@0 | 110 | /** |
aoqi@0 | 111 | * Creates a formatter with default incremental indentations of |
aoqi@0 | 112 | * four spaces. |
aoqi@0 | 113 | */ |
aoqi@0 | 114 | public JFormatter(Writer w) { |
aoqi@0 | 115 | this(new PrintWriter(w)); |
aoqi@0 | 116 | } |
aoqi@0 | 117 | |
aoqi@0 | 118 | /** |
aoqi@0 | 119 | * Closes this formatter. |
aoqi@0 | 120 | */ |
aoqi@0 | 121 | public void close() { |
aoqi@0 | 122 | pw.close(); |
aoqi@0 | 123 | } |
aoqi@0 | 124 | |
aoqi@0 | 125 | /** |
aoqi@0 | 126 | * Returns true if we are in the printing mode, |
aoqi@0 | 127 | * where we actually produce text. |
aoqi@0 | 128 | * |
aoqi@0 | 129 | * The other mode is the "collecting mode' |
aoqi@0 | 130 | */ |
aoqi@0 | 131 | public boolean isPrinting() { |
aoqi@0 | 132 | return mode == Mode.PRINTING; |
aoqi@0 | 133 | } |
aoqi@0 | 134 | |
aoqi@0 | 135 | /** |
aoqi@0 | 136 | * Decrement the indentation level. |
aoqi@0 | 137 | */ |
aoqi@0 | 138 | public JFormatter o() { |
aoqi@0 | 139 | indentLevel--; |
aoqi@0 | 140 | return this; |
aoqi@0 | 141 | } |
aoqi@0 | 142 | |
aoqi@0 | 143 | /** |
aoqi@0 | 144 | * Increment the indentation level. |
aoqi@0 | 145 | */ |
aoqi@0 | 146 | public JFormatter i() { |
aoqi@0 | 147 | indentLevel++; |
aoqi@0 | 148 | return this; |
aoqi@0 | 149 | } |
aoqi@0 | 150 | |
aoqi@0 | 151 | private boolean needSpace(char c1, char c2) { |
aoqi@0 | 152 | if ((c1 == ']') && (c2 == '{')) return true; |
aoqi@0 | 153 | if (c1 == ';') return true; |
aoqi@0 | 154 | if (c1 == CLOSE_TYPE_ARGS) { |
aoqi@0 | 155 | // e.g., "public Foo<Bar> test;" |
aoqi@0 | 156 | if(c2=='(') // but not "new Foo<Bar>()" |
aoqi@0 | 157 | return false; |
aoqi@0 | 158 | return true; |
aoqi@0 | 159 | } |
aoqi@0 | 160 | if ((c1 == ')') && (c2 == '{')) return true; |
aoqi@0 | 161 | if ((c1 == ',') || (c1 == '=')) return true; |
aoqi@0 | 162 | if (c2 == '=') return true; |
aoqi@0 | 163 | if (Character.isDigit(c1)) { |
aoqi@0 | 164 | if ((c2 == '(') || (c2 == ')') || (c2 == ';') || (c2 == ',')) |
aoqi@0 | 165 | return false; |
aoqi@0 | 166 | return true; |
aoqi@0 | 167 | } |
aoqi@0 | 168 | if (Character.isJavaIdentifierPart(c1)) { |
aoqi@0 | 169 | switch (c2) { |
aoqi@0 | 170 | case '{': |
aoqi@0 | 171 | case '}': |
aoqi@0 | 172 | case '+': |
aoqi@0 | 173 | case '>': |
aoqi@0 | 174 | case '@': |
aoqi@0 | 175 | return true; |
aoqi@0 | 176 | default: |
aoqi@0 | 177 | return Character.isJavaIdentifierStart(c2); |
aoqi@0 | 178 | } |
aoqi@0 | 179 | } |
aoqi@0 | 180 | if (Character.isJavaIdentifierStart(c2)) { |
aoqi@0 | 181 | switch (c1) { |
aoqi@0 | 182 | case ']': |
aoqi@0 | 183 | case ')': |
aoqi@0 | 184 | case '}': |
aoqi@0 | 185 | case '+': |
aoqi@0 | 186 | return true; |
aoqi@0 | 187 | default: |
aoqi@0 | 188 | return false; |
aoqi@0 | 189 | } |
aoqi@0 | 190 | } |
aoqi@0 | 191 | if (Character.isDigit(c2)) { |
aoqi@0 | 192 | if (c1 == '(') return false; |
aoqi@0 | 193 | return true; |
aoqi@0 | 194 | } |
aoqi@0 | 195 | return false; |
aoqi@0 | 196 | } |
aoqi@0 | 197 | |
aoqi@0 | 198 | private char lastChar = 0; |
aoqi@0 | 199 | private boolean atBeginningOfLine = true; |
aoqi@0 | 200 | |
aoqi@0 | 201 | private void spaceIfNeeded(char c) { |
aoqi@0 | 202 | if (atBeginningOfLine) { |
aoqi@0 | 203 | for (int i = 0; i < indentLevel; i++) |
aoqi@0 | 204 | pw.print(indentSpace); |
aoqi@0 | 205 | atBeginningOfLine = false; |
aoqi@0 | 206 | } else if ((lastChar != 0) && needSpace(lastChar, c)) |
aoqi@0 | 207 | pw.print(' '); |
aoqi@0 | 208 | } |
aoqi@0 | 209 | |
aoqi@0 | 210 | /** |
aoqi@0 | 211 | * Print a char into the stream |
aoqi@0 | 212 | * |
aoqi@0 | 213 | * @param c the char |
aoqi@0 | 214 | */ |
aoqi@0 | 215 | public JFormatter p(char c) { |
aoqi@0 | 216 | if(mode==Mode.PRINTING) { |
aoqi@0 | 217 | if(c==CLOSE_TYPE_ARGS) { |
aoqi@0 | 218 | pw.print('>'); |
aoqi@0 | 219 | } else { |
aoqi@0 | 220 | spaceIfNeeded(c); |
aoqi@0 | 221 | pw.print(c); |
aoqi@0 | 222 | } |
aoqi@0 | 223 | lastChar = c; |
aoqi@0 | 224 | } |
aoqi@0 | 225 | return this; |
aoqi@0 | 226 | } |
aoqi@0 | 227 | |
aoqi@0 | 228 | /** |
aoqi@0 | 229 | * Print a String into the stream |
aoqi@0 | 230 | * |
aoqi@0 | 231 | * @param s the String |
aoqi@0 | 232 | */ |
aoqi@0 | 233 | public JFormatter p(String s) { |
aoqi@0 | 234 | if(mode==Mode.PRINTING) { |
aoqi@0 | 235 | spaceIfNeeded(s.charAt(0)); |
aoqi@0 | 236 | pw.print(s); |
aoqi@0 | 237 | lastChar = s.charAt(s.length() - 1); |
aoqi@0 | 238 | } |
aoqi@0 | 239 | return this; |
aoqi@0 | 240 | } |
aoqi@0 | 241 | |
aoqi@0 | 242 | public JFormatter t(JType type) { |
aoqi@0 | 243 | if(type.isReference()) { |
aoqi@0 | 244 | return t((JClass)type); |
aoqi@0 | 245 | } else { |
aoqi@0 | 246 | return g(type); |
aoqi@0 | 247 | } |
aoqi@0 | 248 | } |
aoqi@0 | 249 | |
aoqi@0 | 250 | /** |
aoqi@0 | 251 | * Print a type name. |
aoqi@0 | 252 | * |
aoqi@0 | 253 | * <p> |
aoqi@0 | 254 | * In the collecting mode we use this information to |
aoqi@0 | 255 | * decide what types to import and what not to. |
aoqi@0 | 256 | */ |
aoqi@0 | 257 | public JFormatter t(JClass type) { |
aoqi@0 | 258 | switch(mode) { |
aoqi@0 | 259 | case PRINTING: |
aoqi@0 | 260 | // many of the JTypes in this list are either primitive or belong to package java |
aoqi@0 | 261 | // so we don't need a FQCN |
aoqi@0 | 262 | if(importedClasses.contains(type)) { |
aoqi@0 | 263 | p(type.name()); // FQCN imported or not necessary, so generate short name |
aoqi@0 | 264 | } else { |
aoqi@0 | 265 | if(type.outer()!=null) |
aoqi@0 | 266 | t(type.outer()).p('.').p(type.name()); |
aoqi@0 | 267 | else |
aoqi@0 | 268 | p(type.fullName()); // collision was detected, so generate FQCN |
aoqi@0 | 269 | } |
aoqi@0 | 270 | break; |
aoqi@0 | 271 | case COLLECTING: |
aoqi@0 | 272 | final String shortName = type.name(); |
aoqi@0 | 273 | if(collectedReferences.containsKey(shortName)) { |
aoqi@0 | 274 | collectedReferences.get(shortName).add(type); |
aoqi@0 | 275 | } else { |
aoqi@0 | 276 | ReferenceList tl = new ReferenceList(); |
aoqi@0 | 277 | tl.add(type); |
aoqi@0 | 278 | collectedReferences.put(shortName, tl); |
aoqi@0 | 279 | } |
aoqi@0 | 280 | break; |
aoqi@0 | 281 | } |
aoqi@0 | 282 | return this; |
aoqi@0 | 283 | } |
aoqi@0 | 284 | |
aoqi@0 | 285 | /** |
aoqi@0 | 286 | * Print an identifier |
aoqi@0 | 287 | */ |
aoqi@0 | 288 | public JFormatter id(String id) { |
aoqi@0 | 289 | switch(mode) { |
aoqi@0 | 290 | case PRINTING: |
aoqi@0 | 291 | p(id); |
aoqi@0 | 292 | break; |
aoqi@0 | 293 | case COLLECTING: |
aoqi@0 | 294 | // see if there is a type name that collides with this id |
aoqi@0 | 295 | if(collectedReferences.containsKey(id)) { |
aoqi@0 | 296 | if( !collectedReferences.get(id).getClasses().isEmpty() ) { |
aoqi@0 | 297 | for( JClass type : collectedReferences.get(id).getClasses() ) { |
aoqi@0 | 298 | if (type.outer()!=null) { |
aoqi@0 | 299 | collectedReferences.get(id).setId(false); |
aoqi@0 | 300 | return this; |
aoqi@0 | 301 | } |
aoqi@0 | 302 | } |
aoqi@0 | 303 | } |
aoqi@0 | 304 | collectedReferences.get(id).setId(true); |
aoqi@0 | 305 | } else { |
aoqi@0 | 306 | // not a type, but we need to create a place holder to |
aoqi@0 | 307 | // see if there might be a collision with a type |
aoqi@0 | 308 | ReferenceList tl = new ReferenceList(); |
aoqi@0 | 309 | tl.setId(true); |
aoqi@0 | 310 | collectedReferences.put(id, tl); |
aoqi@0 | 311 | } |
aoqi@0 | 312 | break; |
aoqi@0 | 313 | } |
aoqi@0 | 314 | return this; |
aoqi@0 | 315 | } |
aoqi@0 | 316 | |
aoqi@0 | 317 | /** |
aoqi@0 | 318 | * Print a new line into the stream |
aoqi@0 | 319 | */ |
aoqi@0 | 320 | public JFormatter nl() { |
aoqi@0 | 321 | if(mode==Mode.PRINTING) { |
aoqi@0 | 322 | pw.println(); |
aoqi@0 | 323 | lastChar = 0; |
aoqi@0 | 324 | atBeginningOfLine = true; |
aoqi@0 | 325 | } |
aoqi@0 | 326 | return this; |
aoqi@0 | 327 | } |
aoqi@0 | 328 | |
aoqi@0 | 329 | /** |
aoqi@0 | 330 | * Cause the JGenerable object to generate source for iteself |
aoqi@0 | 331 | * |
aoqi@0 | 332 | * @param g the JGenerable object |
aoqi@0 | 333 | */ |
aoqi@0 | 334 | public JFormatter g(JGenerable g) { |
aoqi@0 | 335 | g.generate(this); |
aoqi@0 | 336 | return this; |
aoqi@0 | 337 | } |
aoqi@0 | 338 | |
aoqi@0 | 339 | /** |
aoqi@0 | 340 | * Produces {@link JGenerable}s separated by ',' |
aoqi@0 | 341 | */ |
aoqi@0 | 342 | public JFormatter g(Collection<? extends JGenerable> list) { |
aoqi@0 | 343 | boolean first = true; |
aoqi@0 | 344 | if(!list.isEmpty()) { |
aoqi@0 | 345 | for (JGenerable item : list) { |
aoqi@0 | 346 | if (!first) |
aoqi@0 | 347 | p(','); |
aoqi@0 | 348 | g(item); |
aoqi@0 | 349 | first = false; |
aoqi@0 | 350 | } |
aoqi@0 | 351 | } |
aoqi@0 | 352 | return this; |
aoqi@0 | 353 | } |
aoqi@0 | 354 | |
aoqi@0 | 355 | /** |
aoqi@0 | 356 | * Cause the JDeclaration to generate source for itself |
aoqi@0 | 357 | * |
aoqi@0 | 358 | * @param d the JDeclaration object |
aoqi@0 | 359 | */ |
aoqi@0 | 360 | public JFormatter d(JDeclaration d) { |
aoqi@0 | 361 | d.declare(this); |
aoqi@0 | 362 | return this; |
aoqi@0 | 363 | } |
aoqi@0 | 364 | |
aoqi@0 | 365 | /** |
aoqi@0 | 366 | * Cause the JStatement to generate source for itself |
aoqi@0 | 367 | * |
aoqi@0 | 368 | * @param s the JStatement object |
aoqi@0 | 369 | */ |
aoqi@0 | 370 | public JFormatter s(JStatement s) { |
aoqi@0 | 371 | s.state(this); |
aoqi@0 | 372 | return this; |
aoqi@0 | 373 | } |
aoqi@0 | 374 | |
aoqi@0 | 375 | /** |
aoqi@0 | 376 | * Cause the JVar to generate source for itself |
aoqi@0 | 377 | * |
aoqi@0 | 378 | * @param v the JVar object |
aoqi@0 | 379 | */ |
aoqi@0 | 380 | public JFormatter b(JVar v) { |
aoqi@0 | 381 | v.bind(this); |
aoqi@0 | 382 | return this; |
aoqi@0 | 383 | } |
aoqi@0 | 384 | |
aoqi@0 | 385 | /** |
aoqi@0 | 386 | * Generates the whole source code out of the specified class. |
aoqi@0 | 387 | */ |
aoqi@0 | 388 | void write(JDefinedClass c) { |
aoqi@0 | 389 | // first collect all the types and identifiers |
aoqi@0 | 390 | mode = Mode.COLLECTING; |
aoqi@0 | 391 | d(c); |
aoqi@0 | 392 | |
aoqi@0 | 393 | javaLang = c.owner()._package("java.lang"); |
aoqi@0 | 394 | |
aoqi@0 | 395 | // collate type names and identifiers to determine which types can be imported |
aoqi@0 | 396 | for( ReferenceList tl : collectedReferences.values() ) { |
aoqi@0 | 397 | if(!tl.collisions(c) && !tl.isId()) { |
aoqi@0 | 398 | assert tl.getClasses().size() == 1; |
aoqi@0 | 399 | |
aoqi@0 | 400 | // add to list of collected types |
aoqi@0 | 401 | importedClasses.add(tl.getClasses().get(0)); |
aoqi@0 | 402 | } |
aoqi@0 | 403 | } |
aoqi@0 | 404 | |
aoqi@0 | 405 | // the class itself that we will be generating is always accessible |
aoqi@0 | 406 | importedClasses.add(c); |
aoqi@0 | 407 | |
aoqi@0 | 408 | // then print the declaration |
aoqi@0 | 409 | mode = Mode.PRINTING; |
aoqi@0 | 410 | |
aoqi@0 | 411 | assert c.parentContainer().isPackage() : "this method is only for a pacakge-level class"; |
aoqi@0 | 412 | JPackage pkg = (JPackage) c.parentContainer(); |
aoqi@0 | 413 | if (!pkg.isUnnamed()) { |
aoqi@0 | 414 | nl().d(pkg); |
aoqi@0 | 415 | nl(); |
aoqi@0 | 416 | } |
aoqi@0 | 417 | |
aoqi@0 | 418 | // generate import statements |
aoqi@0 | 419 | JClass[] imports = importedClasses.toArray(new JClass[importedClasses.size()]); |
aoqi@0 | 420 | Arrays.sort(imports); |
aoqi@0 | 421 | for (JClass clazz : imports) { |
aoqi@0 | 422 | // suppress import statements for primitive types, built-in types, |
aoqi@0 | 423 | // types in the root package, and types in |
aoqi@0 | 424 | // the same package as the current type |
aoqi@0 | 425 | if(!supressImport(clazz, c)) { |
aoqi@0 | 426 | if (clazz instanceof JNarrowedClass) { |
aoqi@0 | 427 | clazz = clazz.erasure(); |
aoqi@0 | 428 | } |
aoqi@0 | 429 | |
aoqi@0 | 430 | p("import").p(clazz.fullName()).p(';').nl(); |
aoqi@0 | 431 | } |
aoqi@0 | 432 | } |
aoqi@0 | 433 | nl(); |
aoqi@0 | 434 | |
aoqi@0 | 435 | d(c); |
aoqi@0 | 436 | } |
aoqi@0 | 437 | |
aoqi@0 | 438 | /** |
aoqi@0 | 439 | * determine if an import statement should be supressed |
aoqi@0 | 440 | * |
aoqi@0 | 441 | * @param clazz JType that may or may not have an import |
aoqi@0 | 442 | * @param c JType that is the current class being processed |
aoqi@0 | 443 | * @return true if an import statement should be suppressed, false otherwise |
aoqi@0 | 444 | */ |
aoqi@0 | 445 | private boolean supressImport(JClass clazz, JClass c) { |
aoqi@0 | 446 | if (clazz instanceof JNarrowedClass) { |
aoqi@0 | 447 | clazz = clazz.erasure(); |
aoqi@0 | 448 | } |
aoqi@0 | 449 | if (clazz instanceof JAnonymousClass) { |
aoqi@0 | 450 | clazz = clazz._extends(); |
aoqi@0 | 451 | } |
aoqi@0 | 452 | |
aoqi@0 | 453 | if(clazz._package().isUnnamed()) |
aoqi@0 | 454 | return true; |
aoqi@0 | 455 | |
aoqi@0 | 456 | final String packageName = clazz._package().name(); |
aoqi@0 | 457 | if(packageName.equals("java.lang")) |
aoqi@0 | 458 | return true; // no need to explicitly import java.lang classes |
aoqi@0 | 459 | |
aoqi@0 | 460 | if (clazz._package() == c._package()){ |
aoqi@0 | 461 | // inner classes require an import stmt. |
aoqi@0 | 462 | // All other pkg local classes do not need an |
aoqi@0 | 463 | // import stmt for ref. |
aoqi@0 | 464 | if(clazz.outer()==null) { |
aoqi@0 | 465 | return true; // no need to explicitly import a class into itself |
aoqi@0 | 466 | } |
aoqi@0 | 467 | } |
aoqi@0 | 468 | return false; |
aoqi@0 | 469 | } |
aoqi@0 | 470 | |
aoqi@0 | 471 | private JPackage javaLang; |
aoqi@0 | 472 | |
aoqi@0 | 473 | |
aoqi@0 | 474 | |
aoqi@0 | 475 | /** |
aoqi@0 | 476 | * Special character token we use to differenciate '>' as an operator and |
aoqi@0 | 477 | * '>' as the end of the type arguments. The former uses '>' and it requires |
aoqi@0 | 478 | * a preceding whitespace. The latter uses this, and it does not have a preceding |
aoqi@0 | 479 | * whitespace. |
aoqi@0 | 480 | */ |
aoqi@0 | 481 | /*package*/ static final char CLOSE_TYPE_ARGS = '\uFFFF'; |
aoqi@0 | 482 | |
aoqi@0 | 483 | /** |
aoqi@0 | 484 | * Used during the optimization of class imports. |
aoqi@0 | 485 | * |
aoqi@0 | 486 | * List of {@link JClass}es whose short name is the same. |
aoqi@0 | 487 | * |
aoqi@0 | 488 | * @author Ryan.Shoemaker@Sun.COM |
aoqi@0 | 489 | */ |
aoqi@0 | 490 | final class ReferenceList { |
aoqi@0 | 491 | private final ArrayList<JClass> classes = new ArrayList<JClass>(); |
aoqi@0 | 492 | |
aoqi@0 | 493 | /** true if this name is used as an identifier (like a variable name.) **/ |
aoqi@0 | 494 | private boolean id; |
aoqi@0 | 495 | |
aoqi@0 | 496 | /** |
aoqi@0 | 497 | * Returns true if the symbol represented by the short name |
aoqi@0 | 498 | * is "importable". |
aoqi@0 | 499 | */ |
aoqi@0 | 500 | public boolean collisions(JDefinedClass enclosingClass) { |
aoqi@0 | 501 | // special case where a generated type collides with a type in package java |
aoqi@0 | 502 | |
aoqi@0 | 503 | // more than one type with the same name |
aoqi@0 | 504 | if(classes.size() > 1) |
aoqi@0 | 505 | return true; |
aoqi@0 | 506 | |
aoqi@0 | 507 | // an id and (at least one) type with the same name |
aoqi@0 | 508 | if(id && classes.size() != 0) |
aoqi@0 | 509 | return true; |
aoqi@0 | 510 | |
aoqi@0 | 511 | for(JClass c : classes) { |
aoqi@0 | 512 | if (c instanceof JAnonymousClass) { |
aoqi@0 | 513 | c = c._extends(); |
aoqi@0 | 514 | } |
aoqi@0 | 515 | if(c._package()==javaLang) { |
aoqi@0 | 516 | // make sure that there's no other class with this name within the same package |
aoqi@0 | 517 | Iterator<JDefinedClass> itr = enclosingClass._package().classes(); |
aoqi@0 | 518 | while(itr.hasNext()) { |
aoqi@0 | 519 | // even if this is the only "String" class we use, |
aoqi@0 | 520 | // if the class called "String" is in the same package, |
aoqi@0 | 521 | // we still need to import it. |
aoqi@0 | 522 | JDefinedClass n = itr.next(); |
aoqi@0 | 523 | if(n.name().equals(c.name())) |
aoqi@0 | 524 | return true; //collision |
aoqi@0 | 525 | } |
aoqi@0 | 526 | } |
aoqi@0 | 527 | if(c.outer()!=null) |
aoqi@0 | 528 | return true; // avoid importing inner class to work around 6431987. Also see jaxb issue 166 |
aoqi@0 | 529 | } |
aoqi@0 | 530 | |
aoqi@0 | 531 | return false; |
aoqi@0 | 532 | } |
aoqi@0 | 533 | |
aoqi@0 | 534 | public void add(JClass clazz) { |
aoqi@0 | 535 | if(!classes.contains(clazz)) |
aoqi@0 | 536 | classes.add(clazz); |
aoqi@0 | 537 | } |
aoqi@0 | 538 | |
aoqi@0 | 539 | public List<JClass> getClasses() { |
aoqi@0 | 540 | return classes; |
aoqi@0 | 541 | } |
aoqi@0 | 542 | |
aoqi@0 | 543 | public void setId(boolean value) { |
aoqi@0 | 544 | id = value; |
aoqi@0 | 545 | } |
aoqi@0 | 546 | |
aoqi@0 | 547 | /** |
aoqi@0 | 548 | * Return true iff this is strictly an id, meaning that there |
aoqi@0 | 549 | * are no collisions with type names. |
aoqi@0 | 550 | */ |
aoqi@0 | 551 | public boolean isId() { |
aoqi@0 | 552 | return id && classes.size() == 0; |
aoqi@0 | 553 | } |
aoqi@0 | 554 | } |
aoqi@0 | 555 | } |