1 11 package org.eclipse.jdt.internal.core.dom.rewrite; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.List ; 17 import java.util.Set ; 18 19 import org.eclipse.core.runtime.IProgressMonitor; 20 import org.eclipse.core.runtime.NullProgressMonitor; 21 import org.eclipse.jdt.core.IBuffer; 22 import org.eclipse.jdt.core.ICompilationUnit; 23 import org.eclipse.jdt.core.IJavaElement; 24 import org.eclipse.jdt.core.JavaCore; 25 import org.eclipse.jdt.core.JavaModelException; 26 import org.eclipse.jdt.core.Signature; 27 import org.eclipse.jdt.core.dom.ASTNode; 28 import org.eclipse.jdt.core.dom.CompilationUnit; 29 import org.eclipse.jdt.core.dom.ImportDeclaration; 30 import org.eclipse.jdt.core.dom.PackageDeclaration; 31 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; 32 import org.eclipse.jdt.core.search.IJavaSearchConstants; 33 import org.eclipse.jdt.core.search.IJavaSearchScope; 34 import org.eclipse.jdt.core.search.SearchEngine; 35 import org.eclipse.jdt.core.search.TypeNameRequestor; 36 import org.eclipse.jface.text.IRegion; 37 import org.eclipse.jface.text.Region; 38 import org.eclipse.text.edits.DeleteEdit; 39 import org.eclipse.text.edits.InsertEdit; 40 import org.eclipse.text.edits.MultiTextEdit; 41 42 public final class ImportRewriteAnalyzer { 43 44 private final ICompilationUnit compilationUnit; 45 private final ArrayList packageEntries; 46 47 private final List importsCreated; 48 private final List staticImportsCreated; 49 50 private final IRegion replaceRange; 51 52 private final int importOnDemandThreshold; 53 private final int staticImportOnDemandThreshold; 54 55 private boolean filterImplicitImports; 56 private boolean findAmbiguousImports; 57 58 private int flags= 0; 59 60 private static final int F_NEEDS_LEADING_DELIM= 2; 61 private static final int F_NEEDS_TRAILING_DELIM= 4; 62 63 private static final String JAVA_LANG= "java.lang"; 65 public ImportRewriteAnalyzer(ICompilationUnit cu, CompilationUnit root, String [] importOrder, int threshold, int staticThreshold, boolean restoreExistingImports) { 66 this.compilationUnit= cu; 67 this.importOnDemandThreshold= threshold; 68 this.staticImportOnDemandThreshold= staticThreshold; 69 70 this.filterImplicitImports= true; 71 this.findAmbiguousImports= true; 73 this.packageEntries= new ArrayList (20); 74 this.importsCreated= new ArrayList (); 75 this.staticImportsCreated= new ArrayList (); 76 this.flags= 0; 77 78 this.replaceRange= evaluateReplaceRange(root); 79 if (restoreExistingImports) { 80 addExistingImports(root); 81 } 82 83 PackageEntry[] order= new PackageEntry[importOrder.length]; 84 for (int i= 0; i < order.length; i++) { 85 String curr= importOrder[i]; 86 if (curr.length() > 0 && curr.charAt(0) == '#') { 87 curr= curr.substring(1); 88 order[i]= new PackageEntry(curr, curr, true); } else { 90 order[i]= new PackageEntry(curr, curr, false); } 92 } 93 94 addPreferenceOrderHolders(order); 95 } 96 97 private int getSpacesBetweenImportGroups() { 98 try { 99 int num= Integer.parseInt(this.compilationUnit.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS, true)); 100 if (num >= 0) 101 return num; 102 } catch (NumberFormatException e) { 103 } 105 return 1; 106 } 107 108 private void addPreferenceOrderHolders(PackageEntry[] preferenceOrder) { 109 if (this.packageEntries.isEmpty()) { 110 for (int i= 0; i < preferenceOrder.length; i++) { 112 this.packageEntries.add(preferenceOrder[i]); 113 } 114 } else { 115 118 PackageEntry[] lastAssigned= new PackageEntry[preferenceOrder.length]; 119 120 for (int k= 0; k < this.packageEntries.size(); k++) { 122 PackageEntry entry= (PackageEntry) this.packageEntries.get(k); 123 if (!entry.isComment()) { 124 String currName= entry.getName(); 125 int currNameLen= currName.length(); 126 int bestGroupIndex= -1; 127 int bestGroupLen= -1; 128 for (int i= 0; i < preferenceOrder.length; i++) { 129 boolean currPrevStatic= preferenceOrder[i].isStatic(); 130 if (currPrevStatic == entry.isStatic()) { 131 String currPrefEntry= preferenceOrder[i].getName(); 132 int currPrefLen= currPrefEntry.length(); 133 if (currName.startsWith(currPrefEntry) && currPrefLen >= bestGroupLen) { 134 if (currPrefLen == currNameLen || currName.charAt(currPrefLen) == '.') { 135 if (bestGroupIndex == -1 || currPrefLen > bestGroupLen) { 136 bestGroupLen= currPrefLen; 137 bestGroupIndex= i; 138 } 139 } 140 } 141 } 142 } 143 if (bestGroupIndex != -1) { 144 entry.setGroupID(preferenceOrder[bestGroupIndex].getName()); 145 lastAssigned[bestGroupIndex]= entry; } 147 } 148 } 149 int currAppendIndex= 0; 151 for (int i= 0; i < lastAssigned.length; i++) { 152 PackageEntry entry= lastAssigned[i]; 153 if (entry == null) { 154 PackageEntry newEntry= preferenceOrder[i]; 155 if (currAppendIndex == 0 && !newEntry.isStatic()) { 156 currAppendIndex= getIndexAfterStatics(); 157 } 158 this.packageEntries.add(currAppendIndex, newEntry); 159 currAppendIndex++; 160 } else { 161 currAppendIndex= this.packageEntries.indexOf(entry) + 1; 162 } 163 } 164 } 165 } 166 167 private static String getQualifier(ImportDeclaration decl) { 168 String name= decl.getName().getFullyQualifiedName(); 169 return decl.isOnDemand() ? name : Signature.getQualifier(name); 170 } 171 172 private static String getFullName(ImportDeclaration decl) { 173 String name= decl.getName().getFullyQualifiedName(); 174 return decl.isOnDemand() ? name + ".*": name; } 176 177 private void addExistingImports(CompilationUnit root) { 178 List decls= root.imports(); 179 if (decls.isEmpty()) { 180 return; 181 } 182 PackageEntry currPackage= null; 183 184 ImportDeclaration curr= (ImportDeclaration) decls.get(0); 185 int currOffset= curr.getStartPosition(); 186 int currLength= curr.getLength(); 187 int currEndLine= root.getLineNumber(currOffset + currLength); 188 189 for (int i= 1; i < decls.size(); i++) { 190 boolean isStatic= curr.isStatic(); 191 String name= getFullName(curr); 192 String packName= getQualifier(curr); 193 if (currPackage == null || currPackage.compareTo(packName, isStatic) != 0) { 194 currPackage= new PackageEntry(packName, null, isStatic); 195 this.packageEntries.add(currPackage); 196 } 197 198 ImportDeclaration next= (ImportDeclaration) decls.get(i); 199 int nextOffset= next.getStartPosition(); 200 int nextLength= next.getLength(); 201 int nextOffsetLine= root.getLineNumber(nextOffset); 202 203 if (currEndLine < nextOffsetLine) { 205 currEndLine++; 206 nextOffset= root.getPosition(currEndLine, 0); 207 } 208 currPackage.add(new ImportDeclEntry(name, isStatic, new Region(currOffset, nextOffset - currOffset))); 209 currOffset= nextOffset; 210 curr= next; 211 212 if (currEndLine < nextOffsetLine) { 214 nextOffset= root.getPosition(nextOffsetLine, 0); 215 216 currPackage= new PackageEntry(); this.packageEntries.add(currPackage); 218 currPackage.add(new ImportDeclEntry(null, false, new Region(currOffset, nextOffset - currOffset))); 219 220 currOffset= nextOffset; 221 } 222 currEndLine= root.getLineNumber(nextOffset + nextLength); 223 } 224 225 boolean isStatic= curr.isStatic(); 226 String name= getFullName(curr); 227 String packName= getQualifier(curr); 228 if (currPackage == null || currPackage.compareTo(packName, isStatic) != 0) { 229 currPackage= new PackageEntry(packName, null, isStatic); 230 this.packageEntries.add(currPackage); 231 } 232 int length= this.replaceRange.getOffset() + this.replaceRange.getLength() - curr.getStartPosition(); 233 currPackage.add(new ImportDeclEntry(name, isStatic, new Region(curr.getStartPosition(), length))); 234 } 235 236 244 public void setFilterImplicitImports(boolean filterImplicitImports) { 245 this.filterImplicitImports= filterImplicitImports; 246 } 247 248 253 public void setFindAmbiguousImports(boolean findAmbiguousImports) { 254 this.findAmbiguousImports= findAmbiguousImports; 255 } 256 257 private static class PackageMatcher { 258 private String newName; 259 private String bestName; 260 private int bestMatchLen; 261 262 public PackageMatcher() { 263 } 265 266 public void initialize(String newImportName, String bestImportName) { 267 this.newName= newImportName; 268 this.bestName= bestImportName; 269 this.bestMatchLen= getCommonPrefixLength(bestImportName, newImportName); 270 } 271 272 public boolean isBetterMatch(String currName, boolean preferCurr) { 273 boolean isBetter; 274 int currMatchLen= getCommonPrefixLength(currName, this.newName); 275 int matchDiff= currMatchLen - this.bestMatchLen; 276 if (matchDiff == 0) { 277 if (currMatchLen == this.newName.length() && currMatchLen == currName.length() && currMatchLen == this.bestName.length()) { 278 isBetter= preferCurr; 280 } else { 281 isBetter= sameMatchLenTest(currName); 282 } 283 } else { 284 isBetter= (matchDiff > 0); } 286 if (isBetter) { 287 this.bestName= currName; 288 this.bestMatchLen= currMatchLen; 289 } 290 return isBetter; 291 } 292 293 private boolean sameMatchLenTest(String currName) { 294 int matchLen= this.bestMatchLen; 295 298 char newChar= getCharAt(this.newName, matchLen); 300 char currChar= getCharAt(currName, matchLen); 301 char bestChar= getCharAt(this.bestName, matchLen); 302 303 if (newChar < currChar) { 304 if (bestChar < newChar) { return (currChar - newChar) < (newChar - bestChar); } else { if (currChar == bestChar) { return false; } else { 310 return currChar < bestChar; } 312 } 313 } else { 314 if (bestChar > newChar) { return (newChar - currChar) < (bestChar - newChar); } else { if (currChar == bestChar) { return true; } else { 320 return currChar > bestChar; } 322 } 323 } 324 } 325 } 326 327 static int getCommonPrefixLength(String s, String t) { 328 int len= Math.min(s.length(), t.length()); 329 for (int i= 0; i < len; i++) { 330 if (s.charAt(i) != t.charAt(i)) { 331 return i; 332 } 333 } 334 return len; 335 } 336 337 static char getCharAt(String str, int index) { 338 if (str.length() > index) { 339 return str.charAt(index); 340 } 341 return 0; 342 } 343 344 private PackageEntry findBestMatch(String newName, boolean isStatic) { 345 if (this.packageEntries.isEmpty()) { 346 return null; 347 } 348 String groupId= null; 349 int longestPrefix= -1; 350 for (int i= 0; i < this.packageEntries.size(); i++) { 352 PackageEntry curr= (PackageEntry) this.packageEntries.get(i); 353 if (isStatic == curr.isStatic()) { 354 String currGroup= curr.getGroupID(); 355 if (currGroup != null && newName.startsWith(currGroup)) { 356 int prefixLen= currGroup.length(); 357 if (prefixLen == newName.length()) { 358 return curr; } 360 if ((newName.charAt(prefixLen) == '.') && prefixLen > longestPrefix) { 361 longestPrefix= prefixLen; 362 groupId= currGroup; 363 } 364 } 365 } 366 } 367 PackageEntry bestMatch= null; 368 PackageMatcher matcher= new PackageMatcher(); 369 matcher.initialize(newName, ""); for (int i= 0; i < this.packageEntries.size(); i++) { PackageEntry curr= (PackageEntry) this.packageEntries.get(i); 372 if (!curr.isComment() && curr.isStatic() == isStatic) { 373 if (groupId == null || groupId.equals(curr.getGroupID())) { 374 boolean preferrCurr= (bestMatch == null) || (curr.getNumberOfImports() > bestMatch.getNumberOfImports()); 375 if (matcher.isBetterMatch(curr.getName(), preferrCurr)) { 376 bestMatch= curr; 377 } 378 } 379 } 380 } 381 return bestMatch; 382 } 383 384 private static boolean isImplicitImport(String qualifier, ICompilationUnit cu) { 385 if (JAVA_LANG.equals(qualifier)) { 386 return true; 387 } 388 String packageName= cu.getParent().getElementName(); 389 if (qualifier.equals(packageName)) { 390 return true; 391 } 392 String mainTypeName= JavaCore.removeJavaLikeExtension(cu.getElementName()); 393 if (packageName.length() == 0) { 394 return qualifier.equals(mainTypeName); 395 } 396 return qualifier.equals(packageName +'.' + mainTypeName); 397 } 398 399 public void addImport(String fullTypeName, boolean isStatic) { 400 String typeContainerName= Signature.getQualifier(fullTypeName); 401 ImportDeclEntry decl= new ImportDeclEntry(fullTypeName, isStatic, null); 402 sortIn(typeContainerName, decl, isStatic); 403 } 404 405 public boolean removeImport(String qualifiedName, boolean isStatic) { 406 String containerName= Signature.getQualifier(qualifiedName); 407 408 int nPackages= this.packageEntries.size(); 409 for (int i= 0; i < nPackages; i++) { 410 PackageEntry entry= (PackageEntry) this.packageEntries.get(i); 411 if (entry.compareTo(containerName, isStatic) == 0) { 412 if (entry.remove(qualifiedName, isStatic)) { 413 return true; 414 } 415 } 416 } 417 return false; 418 } 419 420 private int getIndexAfterStatics() { 421 for (int i= 0; i < this.packageEntries.size(); i++) { 422 if (!((PackageEntry) this.packageEntries.get(i)).isStatic()) { 423 return i; 424 } 425 } 426 return this.packageEntries.size(); 427 } 428 429 430 private void sortIn(String typeContainerName, ImportDeclEntry decl, boolean isStatic) { 431 PackageEntry bestMatch= findBestMatch(typeContainerName, isStatic); 432 if (bestMatch == null) { 433 PackageEntry packEntry= new PackageEntry(typeContainerName, null, isStatic); 434 packEntry.add(decl); 435 int insertPos= packEntry.isStatic() ? 0 : getIndexAfterStatics(); 436 this.packageEntries.add(insertPos, packEntry); 437 } else { 438 int cmp= typeContainerName.compareTo(bestMatch.getName()); 439 if (cmp == 0) { 440 bestMatch.sortIn(decl); 441 } else { 442 String group= bestMatch.getGroupID(); 444 if (group != null) { 445 if (!typeContainerName.startsWith(group)) { 446 group= null; 447 } 448 } 449 PackageEntry packEntry= new PackageEntry(typeContainerName, group, isStatic); 450 packEntry.add(decl); 451 int index= this.packageEntries.indexOf(bestMatch); 452 if (cmp < 0) { this.packageEntries.add(index, packEntry); 454 } else { this.packageEntries.add(index + 1, packEntry); 456 } 457 } 458 } 459 } 460 461 private IRegion evaluateReplaceRange(CompilationUnit root) { 462 List imports= root.imports(); 463 if (!imports.isEmpty()) { 464 ImportDeclaration first= (ImportDeclaration) imports.get(0); 465 ImportDeclaration last= (ImportDeclaration) imports.get(imports.size() - 1); 466 467 int startPos= first.getStartPosition(); int endPos= root.getExtendedStartPosition(last) + root.getExtendedLength(last); 469 int endLine= root.getLineNumber(endPos); 470 if (endLine > 0) { 471 int nextLinePos= root.getPosition(endLine + 1, 0); 472 if (nextLinePos >= 0) { 473 int firstTypePos= getFirstTypeBeginPos(root); 474 if (firstTypePos != -1 && firstTypePos < nextLinePos) { 475 endPos= firstTypePos; 476 } else { 477 endPos= nextLinePos; 478 } 479 } 480 } 481 return new Region(startPos, endPos - startPos); 482 } else { 483 int start= getPackageStatementEndPos(root); 484 return new Region(start, 0); 485 } 486 } 487 488 public MultiTextEdit getResultingEdits(IProgressMonitor monitor) throws JavaModelException { 489 if (monitor == null) { 490 monitor= new NullProgressMonitor(); 491 } 492 try { 493 int importsStart= this.replaceRange.getOffset(); 494 int importsLen= this.replaceRange.getLength(); 495 496 String lineDelim= this.compilationUnit.findRecommendedLineSeparator(); 497 IBuffer buffer= this.compilationUnit.getBuffer(); 498 499 int currPos= importsStart; 500 MultiTextEdit resEdit= new MultiTextEdit(); 501 502 if ((this.flags & F_NEEDS_LEADING_DELIM) != 0) { 503 resEdit.addChild(new InsertEdit(currPos, lineDelim)); 505 } 506 507 PackageEntry lastPackage= null; 508 509 Set onDemandConflicts= null; 510 if (this.findAmbiguousImports) { 511 onDemandConflicts= evaluateStarImportConflicts(monitor); 512 } 513 514 int spacesBetweenGroups= getSpacesBetweenImportGroups(); 515 516 ArrayList stringsToInsert= new ArrayList (); 517 518 int nPackageEntries= this.packageEntries.size(); 519 for (int i= 0; i < nPackageEntries; i++) { 520 PackageEntry pack= (PackageEntry) this.packageEntries.get(i); 521 int nImports= pack.getNumberOfImports(); 522 523 if (this.filterImplicitImports && !pack.isStatic() && isImplicitImport(pack.getName(), this.compilationUnit)) { 524 pack.removeAllNew(onDemandConflicts); 525 nImports= pack.getNumberOfImports(); 526 } 527 if (nImports == 0) { 528 continue; 529 } 530 531 532 if (spacesBetweenGroups > 0) { 533 if (lastPackage != null && !pack.isComment() && !pack.isSameGroup(lastPackage)) { 535 ImportDeclEntry last= lastPackage.getImportAt(lastPackage.getNumberOfImports() - 1); 536 ImportDeclEntry first= pack.getImportAt(0); 537 if (!lastPackage.isComment() && (last.isNew() || first.isNew())) { 538 for (int k= spacesBetweenGroups; k > 0; k--) { 539 stringsToInsert.add(lineDelim); 540 } 541 } 542 } 543 } 544 lastPackage= pack; 545 546 boolean isStatic= pack.isStatic(); 547 int threshold= isStatic ? staticImportOnDemandThreshold : importOnDemandThreshold; 548 549 boolean doStarImport= pack.hasStarImport(threshold, onDemandConflicts); 550 if (doStarImport && (pack.find("*") == null)) { String starImportString= pack.getName() + ".*"; String str= getNewImportString(starImportString, isStatic, lineDelim); 553 stringsToInsert.add(str); 554 } 555 556 for (int k= 0; k < nImports; k++) { 557 ImportDeclEntry currDecl= pack.getImportAt(k); 558 IRegion region= currDecl.getSourceRange(); 559 560 if (region == null) { if (!doStarImport || currDecl.isOnDemand() || (onDemandConflicts != null && onDemandConflicts.contains(currDecl.getSimpleName()))) { 562 String str= getNewImportString(currDecl.getElementName(), isStatic, lineDelim); 563 stringsToInsert.add(str); 564 } 565 } else { 566 if (!doStarImport || currDecl.isOnDemand() || onDemandConflicts == null || onDemandConflicts.contains(currDecl.getSimpleName())) { 567 int offset= region.getOffset(); 568 removeAndInsertNew(buffer, currPos, offset, stringsToInsert, resEdit); 569 stringsToInsert.clear(); 570 currPos= offset + region.getLength(); 571 } 572 } 573 } 574 } 575 576 int end= importsStart + importsLen; 577 removeAndInsertNew(buffer, currPos, end, stringsToInsert, resEdit); 578 579 if (importsLen == 0) { 580 if (!this.importsCreated.isEmpty() || !this.staticImportsCreated.isEmpty()) { if ((this.flags & F_NEEDS_TRAILING_DELIM) != 0) { 582 resEdit.addChild(new InsertEdit(currPos, lineDelim)); 583 } 584 } else { 585 return new MultiTextEdit(); } 587 } 588 return resEdit; 589 } finally { 590 monitor.done(); 591 } 592 } 593 594 private void removeAndInsertNew(IBuffer buffer, int contentOffset, int contentEnd, ArrayList stringsToInsert, MultiTextEdit resEdit) { 595 int pos= contentOffset; 596 for (int i= 0; i < stringsToInsert.size(); i++) { 597 String curr= (String ) stringsToInsert.get(i); 598 int idx= findInBuffer(buffer, curr, pos, contentEnd); 599 if (idx != -1) { 600 if (idx != pos) { 601 resEdit.addChild(new DeleteEdit(pos, idx - pos)); 602 } 603 pos= idx + curr.length(); 604 } else { 605 resEdit.addChild(new InsertEdit(pos, curr)); 606 } 607 } 608 if (pos < contentEnd) { 609 resEdit.addChild(new DeleteEdit(pos, contentEnd - pos)); 610 } 611 } 612 613 private int findInBuffer(IBuffer buffer, String str, int start, int end) { 614 int pos= start; 615 int len= str.length(); 616 if (pos + len > end || str.length() == 0) { 617 return -1; 618 } 619 char first= str.charAt(0); 620 int step= str.indexOf(first, 1); 621 if (step == -1) { 622 step= len; 623 } 624 while (pos + len <= end) { 625 if (buffer.getChar(pos) == first) { 626 int k= 1; 627 while (k < len && buffer.getChar(pos + k) == str.charAt(k)) { 628 k++; 629 } 630 if (k == len) { 631 return pos; } 633 if (k < step) { 634 pos+= k; 635 } else { 636 pos+= step; 637 } 638 } else { 639 pos++; 640 } 641 } 642 return -1; 643 } 644 645 private Set evaluateStarImportConflicts(IProgressMonitor monitor) throws JavaModelException { 646 648 final HashSet onDemandConflicts= new HashSet (); 649 650 IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { this.compilationUnit.getJavaProject() }); 651 652 ArrayList starImportPackages= new ArrayList (); 653 ArrayList simpleTypeNames= new ArrayList (); 654 int nPackageEntries= this.packageEntries.size(); 655 for (int i= 0; i < nPackageEntries; i++) { 656 PackageEntry pack= (PackageEntry) this.packageEntries.get(i); 657 if (!pack.isStatic() && pack.hasStarImport(importOnDemandThreshold, null)) { 658 starImportPackages.add(pack.getName().toCharArray()); 659 for (int k= 0; k < pack.getNumberOfImports(); k++) { 660 ImportDeclEntry curr= pack.getImportAt(k); 661 if (!curr.isOnDemand() && !curr.isComment()) { 662 simpleTypeNames.add(curr.getSimpleName().toCharArray()); 663 } 664 } 665 } 666 } 667 if (starImportPackages.isEmpty()) { 668 return null; 669 } 670 671 starImportPackages.add(this.compilationUnit.getParent().getElementName().toCharArray()); 672 starImportPackages.add(JAVA_LANG.toCharArray()); 673 674 char[][] allPackages= (char[][]) starImportPackages.toArray(new char[starImportPackages.size()][]); 675 char[][] allTypes= (char[][]) simpleTypeNames.toArray(new char[simpleTypeNames.size()][]); 676 677 TypeNameRequestor requestor= new TypeNameRequestor() { 678 HashMap foundTypes= new HashMap (); 679 680 private String getTypeContainerName(char[] packageName, char[][] enclosingTypeNames) { 681 StringBuffer buf= new StringBuffer (); 682 buf.append(packageName); 683 for (int i= 0; i < enclosingTypeNames.length; i++) { 684 if (buf.length() > 0) 685 buf.append('.'); 686 buf.append(enclosingTypeNames[i]); 687 } 688 return buf.toString(); 689 } 690 691 public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) { 692 String name= new String (simpleTypeName); 693 String containerName= getTypeContainerName(packageName, enclosingTypeNames); 694 695 String oldContainer= (String ) this.foundTypes.put(name, containerName); 696 if (oldContainer != null && !oldContainer.equals(containerName)) { 697 onDemandConflicts.add(name); 698 } 699 } 700 }; 701 new SearchEngine().searchAllTypeNames(allPackages, allTypes, scope, requestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); 702 return onDemandConflicts; 703 } 704 705 private String getNewImportString(String importName, boolean isStatic, String lineDelim) { 706 StringBuffer buf= new StringBuffer (); 707 buf.append("import "); if (isStatic) { 709 buf.append("static "); } 711 buf.append(importName); 712 buf.append(';'); 713 buf.append(lineDelim); 714 715 if (isStatic) { 716 this.staticImportsCreated.add(importName); 717 } else { 718 this.importsCreated.add(importName); 719 } 720 return buf.toString(); 721 } 722 723 private static int getFirstTypeBeginPos(CompilationUnit root) { 724 List types= root.types(); 725 if (!types.isEmpty()) { 726 return root.getExtendedStartPosition(((ASTNode) types.get(0))); 727 } 728 return -1; 729 } 730 731 private int getPackageStatementEndPos(CompilationUnit root) { 732 PackageDeclaration packDecl= root.getPackage(); 733 if (packDecl != null) { 734 int lineAfterPackage= root.getLineNumber(packDecl.getStartPosition() + packDecl.getLength()) + 1; 735 int afterPackageStatementPos= root.getPosition(lineAfterPackage, 0); 736 if (afterPackageStatementPos >= 0) { 737 int firstTypePos= getFirstTypeBeginPos(root); 738 if (firstTypePos != -1 && firstTypePos <= afterPackageStatementPos) { 739 if (firstTypePos <= afterPackageStatementPos) { 740 this.flags |= F_NEEDS_TRAILING_DELIM; 741 if (firstTypePos == afterPackageStatementPos) { 742 this.flags |= F_NEEDS_LEADING_DELIM; 743 } 744 return firstTypePos; 745 } 746 } 747 this.flags |= F_NEEDS_LEADING_DELIM; 748 return afterPackageStatementPos; } 750 } 751 this.flags |= F_NEEDS_TRAILING_DELIM; 752 return 0; 753 } 754 755 public String toString() { 756 int nPackages= this.packageEntries.size(); 757 StringBuffer buf= new StringBuffer ("\n-----------------------\n"); for (int i= 0; i < nPackages; i++) { 759 PackageEntry entry= (PackageEntry) this.packageEntries.get(i); 760 if (entry.isStatic()) { 761 buf.append("static "); } 763 buf.append(entry.toString()); 764 } 765 return buf.toString(); 766 } 767 768 private static final class ImportDeclEntry { 769 770 private String elementName; 771 private IRegion sourceRange; 772 private final boolean isStatic; 773 774 public ImportDeclEntry(String elementName, boolean isStatic, IRegion sourceRange) { 775 this.elementName= elementName; 776 this.sourceRange= sourceRange; 777 this.isStatic= isStatic; 778 } 779 780 public String getElementName() { 781 return this.elementName; 782 } 783 784 public int compareTo(String fullName, boolean isStaticImport) { 785 int cmp= this.elementName.compareTo(fullName); 786 if (cmp == 0) { 787 if (this.isStatic == isStaticImport) { 788 return 0; 789 } 790 return this.isStatic ? -1 : 1; 791 } 792 return cmp; 793 } 794 795 public String getSimpleName() { 796 return Signature.getSimpleName(this.elementName); 797 } 798 799 public boolean isOnDemand() { 800 return this.elementName != null && this.elementName.endsWith(".*"); } 802 803 public boolean isStatic() { 804 return this.isStatic; 805 } 806 807 public boolean isNew() { 808 return this.sourceRange == null; 809 } 810 811 public boolean isComment() { 812 return this.elementName == null; 813 } 814 815 public IRegion getSourceRange() { 816 return this.sourceRange; 817 } 818 819 } 820 821 825 private final static class PackageEntry { 826 827 public static PackageEntry createOnPlaceholderEntry(String preferenceOrder) { 828 if (preferenceOrder.length() > 0 && preferenceOrder.charAt(0) == '#') { 829 String curr= preferenceOrder.substring(1); 830 return new PackageEntry(curr, curr, true); 831 } 832 return new PackageEntry(preferenceOrder, preferenceOrder, false); 833 } 834 835 private String name; 836 private ArrayList importEntries; 837 private String group; 838 private boolean isStatic; 839 840 843 public PackageEntry() { 844 this("!", null, false); } 846 847 853 public PackageEntry(String name, String group, boolean isStatic) { 854 this.name= name; 855 this.importEntries= new ArrayList (5); 856 this.group= group; 857 this.isStatic= isStatic; 858 } 859 860 public boolean isStatic() { 861 return this.isStatic; 862 } 863 864 public int compareTo(String otherName, boolean isOtherStatic) { 865 int cmp= this.name.compareTo(otherName); 866 if (cmp == 0) { 867 if (this.isStatic == isOtherStatic) { 868 return 0; 869 } 870 return this.isStatic ? -1 : 1; 871 } 872 return cmp; 873 } 874 875 public void sortIn(ImportDeclEntry imp) { 876 String fullImportName= imp.getElementName(); 877 int insertPosition= -1; 878 int nInports= this.importEntries.size(); 879 for (int i= 0; i < nInports; i++) { 880 ImportDeclEntry curr= getImportAt(i); 881 if (!curr.isComment()) { 882 int cmp= curr.compareTo(fullImportName, imp.isStatic()); 883 if (cmp == 0) { 884 return; } else if (cmp > 0 && insertPosition == -1) { 886 insertPosition= i; 887 } 888 } 889 } 890 if (insertPosition == -1) { 891 this.importEntries.add(imp); 892 } else { 893 this.importEntries.add(insertPosition, imp); 894 } 895 } 896 897 898 public void add(ImportDeclEntry imp) { 899 this.importEntries.add(imp); 900 } 901 902 public ImportDeclEntry find(String simpleName) { 903 int nInports= this.importEntries.size(); 904 for (int i= 0; i < nInports; i++) { 905 ImportDeclEntry curr= getImportAt(i); 906 if (!curr.isComment()) { 907 String currName= curr.getElementName(); 908 if (currName.endsWith(simpleName)) { 909 int dotPos= currName.length() - simpleName.length() - 1; 910 if ((dotPos == -1) || (dotPos > 0 && currName.charAt(dotPos) == '.')) { 911 return curr; 912 } 913 } 914 } 915 } 916 return null; 917 } 918 919 public boolean remove(String fullName, boolean isStaticImport) { 920 int nInports= this.importEntries.size(); 921 for (int i= 0; i < nInports; i++) { 922 ImportDeclEntry curr= getImportAt(i); 923 if (!curr.isComment() && curr.compareTo(fullName, isStaticImport) == 0) { 924 this.importEntries.remove(i); 925 return true; 926 } 927 } 928 return false; 929 } 930 931 public void removeAllNew(Set onDemandConflicts) { 932 int nInports= this.importEntries.size(); 933 for (int i= nInports - 1; i >= 0; i--) { 934 ImportDeclEntry curr= getImportAt(i); 935 if (curr.isNew() ) { 936 this.importEntries.remove(i); 937 } 938 } 939 } 940 941 public ImportDeclEntry getImportAt(int index) { 942 return (ImportDeclEntry) this.importEntries.get(index); 943 } 944 945 public boolean hasStarImport(int threshold, Set explicitImports) { 946 if (isComment() || isDefaultPackage()) { return false; 948 } 949 int nImports= getNumberOfImports(); 950 int count= 0; 951 boolean containsNew= false; 952 for (int i= 0; i < nImports; i++) { 953 ImportDeclEntry curr= getImportAt(i); 954 if (curr.isOnDemand()) { 955 return true; 956 } 957 if (!curr.isComment()) { 958 count++; 959 boolean isExplicit= !curr.isStatic() && (explicitImports != null) && explicitImports.contains(curr.getSimpleName()); 960 containsNew |= curr.isNew() && !isExplicit; 961 } 962 } 963 return (count >= threshold) && containsNew; 964 } 965 966 public int getNumberOfImports() { 967 return this.importEntries.size(); 968 } 969 970 public String getName() { 971 return this.name; 972 } 973 974 public String getGroupID() { 975 return this.group; 976 } 977 978 public void setGroupID(String groupID) { 979 this.group= groupID; 980 } 981 982 public boolean isSameGroup(PackageEntry other) { 983 if (this.group == null) { 984 return other.getGroupID() == null; 985 } else { 986 return this.group.equals(other.getGroupID()) && (this.isStatic == other.isStatic()); 987 } 988 } 989 990 public ImportDeclEntry getLast() { 991 int nImports= getNumberOfImports(); 992 if (nImports > 0) { 993 return getImportAt(nImports - 1); 994 } 995 return null; 996 } 997 998 public boolean isComment() { 999 return "!".equals(this.name); } 1001 1002 public boolean isDefaultPackage() { 1003 return this.name.length() == 0; 1004 } 1005 1006 public String toString() { 1007 StringBuffer buf= new StringBuffer (); 1008 if (isComment()) { 1009 buf.append("comment\n"); } else { 1011 buf.append(this.name); buf.append(", groupId: "); buf.append(this.group); buf.append("\n"); int nImports= getNumberOfImports(); 1013 for (int i= 0; i < nImports; i++) { 1014 ImportDeclEntry curr= getImportAt(i); 1015 buf.append(" "); if (curr.isStatic()) { 1017 buf.append("static "); } 1019 buf.append(curr.getSimpleName()); 1020 if (curr.isNew()) { 1021 buf.append(" (new)"); } 1023 buf.append("\n"); } 1025 } 1026 return buf.toString(); 1027 } 1028 } 1029 1030 public String [] getCreatedImports() { 1031 return (String []) this.importsCreated.toArray(new String [this.importsCreated.size()]); 1032 } 1033 1034 public String [] getCreatedStaticImports() { 1035 return (String []) this.staticImportsCreated.toArray(new String [this.staticImportsCreated.size()]); 1036 } 1037 1038} 1039 | Popular Tags |