1 11 package org.eclipse.jdt.internal.codeassist; 12 13 import java.util.Locale ; 14 import java.util.Map ; 15 16 import org.eclipse.jdt.core.Signature; 17 import org.eclipse.jdt.core.compiler.*; 18 import org.eclipse.jdt.core.search.IJavaSearchConstants; 19 import org.eclipse.jdt.internal.codeassist.impl.*; 20 import org.eclipse.jdt.internal.codeassist.select.*; 21 import org.eclipse.jdt.internal.compiler.*; 22 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 23 import org.eclipse.jdt.internal.compiler.env.*; 24 import org.eclipse.jdt.internal.compiler.ast.*; 25 import org.eclipse.jdt.internal.compiler.lookup.*; 26 import org.eclipse.jdt.internal.compiler.parser.*; 27 import org.eclipse.jdt.internal.compiler.problem.*; 28 import org.eclipse.jdt.internal.core.SearchableEnvironment; 29 import org.eclipse.jdt.internal.core.SelectionRequestor; 30 import org.eclipse.jdt.internal.core.SourceType; 31 import org.eclipse.jdt.internal.core.SourceTypeElementInfo; 32 import org.eclipse.jdt.internal.core.util.ASTNodeFinder; 33 34 43 public final class SelectionEngine extends Engine implements ISearchRequestor { 44 45 public static boolean DEBUG = false; 46 public static boolean PERF = false; 47 48 SelectionParser parser; 49 ISelectionRequestor requestor; 50 51 boolean acceptedAnswer; 52 53 private int actualSelectionStart; 54 private int actualSelectionEnd; 55 private char[] selectedIdentifier; 56 57 private char[][][] acceptedClasses; 58 private int[] acceptedClassesModifiers; 59 private char[][][] acceptedInterfaces; 60 private int[] acceptedInterfacesModifiers; 61 private char[][][] acceptedEnums; 62 private int[] acceptedEnumsModifiers; 63 private char[][][] acceptedAnnotations; 64 private int[] acceptedAnnotationsModifiers; 65 int acceptedClassesCount; 66 int acceptedInterfacesCount; 67 int acceptedEnumsCount; 68 int acceptedAnnotationsCount; 69 70 boolean noProposal = true; 71 CategorizedProblem problem = null; 72 73 90 public SelectionEngine( 91 SearchableEnvironment nameEnvironment, 92 ISelectionRequestor requestor, 93 Map settings) { 94 95 super(settings); 96 97 this.requestor = requestor; 98 this.nameEnvironment = nameEnvironment; 99 100 ProblemReporter problemReporter = 101 new ProblemReporter( 102 DefaultErrorHandlingPolicies.proceedWithAllProblems(), 103 this.compilerOptions, 104 new DefaultProblemFactory(Locale.getDefault())) { 105 106 public CategorizedProblem createProblem( 107 char[] fileName, 108 int problemId, 109 String [] problemArguments, 110 String [] messageArguments, 111 int severity, 112 int problemStartPosition, 113 int problemEndPosition, 114 int lineNumber, 115 int columnNumber) { 116 CategorizedProblem pb = super.createProblem( 117 fileName, 118 problemId, 119 problemArguments, 120 messageArguments, 121 severity, 122 problemStartPosition, 123 problemEndPosition, 124 lineNumber, 125 columnNumber); 126 if(SelectionEngine.this.problem == null && pb.isError() && (pb.getID() & IProblem.Syntax) == 0) { 127 SelectionEngine.this.problem = pb; 128 } 129 130 return pb; 131 } 132 }; 133 this.lookupEnvironment = 134 new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment); 135 this.parser = new SelectionParser(problemReporter); 136 } 137 138 public void acceptType(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, int modifiers, AccessRestriction accessRestriction) { 139 char[] typeName = enclosingTypeNames == null ? 140 simpleTypeName : 141 CharOperation.concat( 142 CharOperation.concatWith(enclosingTypeNames, '.'), 143 simpleTypeName, 144 '.'); 145 146 if (CharOperation.equals(simpleTypeName, this.selectedIdentifier)) { 147 char[] flatEnclosingTypeNames = 148 enclosingTypeNames == null || enclosingTypeNames.length == 0 ? 149 null : 150 CharOperation.concatWith(enclosingTypeNames, '.'); 151 if(mustQualifyType(packageName, simpleTypeName, flatEnclosingTypeNames, modifiers)) { 152 int length = 0; 153 int kind = modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation); 154 switch (kind) { 155 case ClassFileConstants.AccAnnotation: 156 case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface: 157 char[][] acceptedAnnotation = new char[2][]; 158 acceptedAnnotation[0] = packageName; 159 acceptedAnnotation[1] = typeName; 160 161 if(this.acceptedAnnotations == null) { 162 this.acceptedAnnotations = new char[10][][]; 163 this.acceptedAnnotationsModifiers = new int[10]; 164 this.acceptedAnnotationsCount = 0; 165 } 166 length = this.acceptedAnnotations.length; 167 if(length == this.acceptedAnnotationsCount) { 168 int newLength = (length + 1)* 2; 169 System.arraycopy(this.acceptedAnnotations, 0, this.acceptedAnnotations = new char[newLength][][], 0, length); 170 System.arraycopy(this.acceptedAnnotationsModifiers, 0, this.acceptedAnnotationsModifiers = new int[newLength], 0, length); 171 } 172 this.acceptedAnnotationsModifiers[this.acceptedAnnotationsCount] = modifiers; 173 this.acceptedAnnotations[this.acceptedAnnotationsCount++] = acceptedAnnotation; 174 break; 175 case ClassFileConstants.AccEnum: 176 char[][] acceptedEnum = new char[2][]; 177 acceptedEnum[0] = packageName; 178 acceptedEnum[1] = typeName; 179 180 if(this.acceptedEnums == null) { 181 this.acceptedEnums = new char[10][][]; 182 this.acceptedEnumsModifiers = new int[10]; 183 this.acceptedEnumsCount = 0; 184 } 185 length = this.acceptedEnums.length; 186 if(length == this.acceptedEnumsCount) { 187 int newLength = (length + 1)* 2; 188 System.arraycopy(this.acceptedEnums, 0, this.acceptedEnums = new char[newLength][][], 0, length); 189 System.arraycopy(this.acceptedEnumsModifiers, 0, this.acceptedEnumsModifiers = new int[newLength], 0, length); 190 } 191 this.acceptedEnumsModifiers[this.acceptedEnumsCount] = modifiers; 192 this.acceptedEnums[this.acceptedEnumsCount++] = acceptedEnum; 193 break; 194 case ClassFileConstants.AccInterface: 195 char[][] acceptedInterface= new char[2][]; 196 acceptedInterface[0] = packageName; 197 acceptedInterface[1] = typeName; 198 199 if(this.acceptedInterfaces == null) { 200 this.acceptedInterfaces = new char[10][][]; 201 this.acceptedInterfacesModifiers = new int[10]; 202 this.acceptedInterfacesCount = 0; 203 } 204 length = this.acceptedInterfaces.length; 205 if(length == this.acceptedInterfacesCount) { 206 int newLength = (length + 1)* 2; 207 System.arraycopy(this.acceptedInterfaces, 0, this.acceptedInterfaces = new char[newLength][][], 0, length); 208 System.arraycopy(this.acceptedInterfacesModifiers, 0, this.acceptedInterfacesModifiers = new int[newLength], 0, length); 209 } 210 this.acceptedInterfacesModifiers[this.acceptedInterfacesCount] = modifiers; 211 this.acceptedInterfaces[this.acceptedInterfacesCount++] = acceptedInterface; 212 break; 213 default: 214 char[][] acceptedClass = new char[2][]; 215 acceptedClass[0] = packageName; 216 acceptedClass[1] = typeName; 217 218 if(this.acceptedClasses == null) { 219 this.acceptedClasses = new char[10][][]; 220 this.acceptedClassesModifiers = new int[10]; 221 this.acceptedClassesCount = 0; 222 } 223 length = this.acceptedClasses.length; 224 if(length == this.acceptedClassesCount) { 225 int newLength = (length + 1)* 2; 226 System.arraycopy(this.acceptedClasses, 0, this.acceptedClasses = new char[newLength][][], 0, length); 227 System.arraycopy(this.acceptedClassesModifiers, 0, this.acceptedClassesModifiers = new int[newLength], 0, length); 228 } 229 this.acceptedClassesModifiers[this.acceptedClassesCount] = modifiers; 230 this.acceptedClasses[this.acceptedClassesCount++] = acceptedClass; 231 break; 232 } 233 } else { 234 this.noProposal = false; 235 this.requestor.acceptType( 236 packageName, 237 typeName, 238 modifiers, 239 false, 240 null, 241 this.actualSelectionStart, 242 this.actualSelectionEnd); 243 this.acceptedAnswer = true; 244 } 245 } 246 } 247 248 256 public void acceptPackage(char[] packageName) { 257 } 259 260 private void acceptQualifiedTypes() { 261 if(this.acceptedClasses != null){ 262 this.acceptedAnswer = true; 263 for (int i = 0; i < this.acceptedClassesCount; i++) { 264 this.noProposal = false; 265 this.requestor.acceptType( 266 this.acceptedClasses[i][0], 267 this.acceptedClasses[i][1], 268 this.acceptedClassesModifiers[i], 269 false, 270 null, 271 this.actualSelectionStart, 272 this.actualSelectionEnd); 273 } 274 this.acceptedClasses = null; 275 this.acceptedClassesModifiers = null; 276 this.acceptedClassesCount = 0; 277 } 278 if(this.acceptedInterfaces != null){ 279 this.acceptedAnswer = true; 280 for (int i = 0; i < this.acceptedInterfacesCount; i++) { 281 this.noProposal = false; 282 this.requestor.acceptType( 283 this.acceptedInterfaces[i][0], 284 this.acceptedInterfaces[i][1], 285 this.acceptedInterfacesModifiers[i], 286 false, 287 null, 288 this.actualSelectionStart, 289 this.actualSelectionEnd); 290 } 291 this.acceptedInterfaces = null; 292 this.acceptedInterfacesModifiers = null; 293 this.acceptedInterfacesCount = 0; 294 } 295 if(this.acceptedAnnotations != null){ 296 this.acceptedAnswer = true; 297 for (int i = 0; i < this.acceptedAnnotationsCount; i++) { 298 this.noProposal = false; 299 this.requestor.acceptType( 300 this.acceptedAnnotations[i][0], 301 this.acceptedAnnotations[i][1], 302 this.acceptedAnnotationsModifiers[i], 303 false, 304 null, 305 this.actualSelectionStart, 306 this.actualSelectionEnd); 307 } 308 this.acceptedAnnotations = null; 309 this.acceptedAnnotationsModifiers = null; 310 this.acceptedAnnotationsCount = 0; 311 } 312 if(this.acceptedEnums != null){ 313 this.acceptedAnswer = true; 314 for (int i = 0; i < this.acceptedEnumsCount; i++) { 315 this.noProposal = false; 316 this.requestor.acceptType( 317 this.acceptedEnums[i][0], 318 this.acceptedEnums[i][1], 319 this.acceptedEnumsModifiers[i], 320 false, 321 null, 322 this.actualSelectionStart, 323 this.actualSelectionEnd); 324 } 325 this.acceptedEnums = null; 326 this.acceptedEnumsModifiers = null; 327 this.acceptedEnumsCount = 0; 328 } 329 } 330 private boolean checkSelection( 331 char[] source, 332 int selectionStart, 333 int selectionEnd) { 334 335 Scanner scanner = new Scanner(); 336 scanner.setSource(source); 337 338 int lastIdentifierStart = -1; 339 int lastIdentifierEnd = -1; 340 char[] lastIdentifier = null; 341 int token; 342 343 if(selectionStart > selectionEnd){ 344 int end = source.length - 1; 345 346 int currentPosition = selectionStart - 1; 348 int nextCharacterPosition = selectionStart; 349 char currentCharacter = ' '; 350 try { 351 lineLoop: while(currentPosition > 0){ 352 353 if(source[currentPosition] == '\\' && source[currentPosition+1] == 'u') { 354 int pos = currentPosition + 2; 355 int c1 = 0, c2 = 0, c3 = 0, c4 = 0; 356 while (source[pos] == 'u') { 357 pos++; 358 } 359 360 int endOfUnicode = pos + 3; 361 if (end < endOfUnicode) { 362 if (endOfUnicode < source.length) { 363 end = endOfUnicode; 364 } else { 365 return false; } 367 } 368 369 if ((c1 = ScannerHelper.getNumericValue(source[pos++])) > 15 370 || c1 < 0 371 || (c2 = ScannerHelper.getNumericValue(source[pos++])) > 15 372 || c2 < 0 373 || (c3 = ScannerHelper.getNumericValue(source[pos++])) > 15 374 || c3 < 0 375 || (c4 = ScannerHelper.getNumericValue(source[pos++])) > 15 376 || c4 < 0) { 377 return false; 378 } else { 379 currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); 380 nextCharacterPosition = pos; 381 } 382 } else { 383 currentCharacter = source[currentPosition]; 384 nextCharacterPosition = currentPosition+1; 385 } 386 387 switch(currentCharacter) { 388 case '\r': 389 case '\n': 390 case '/': 391 case '"': 392 case '\'': 393 break lineLoop; 394 } 395 currentPosition--; 396 } 397 } catch (ArrayIndexOutOfBoundsException e) { 398 return false; 399 } 400 401 scanner.resetTo(nextCharacterPosition, end); 403 do { 404 try { 405 token = scanner.getNextToken(); 406 } catch (InvalidInputException e) { 407 return false; 408 } 409 switch (token) { 410 case TerminalTokens.TokenNamethis: 411 case TerminalTokens.TokenNamesuper: 412 case TerminalTokens.TokenNameIdentifier: 413 if (scanner.startPosition <= selectionStart && selectionStart <= scanner.currentPosition) { 414 if (scanner.currentPosition == scanner.eofPosition) { 415 int temp = scanner.eofPosition; 416 scanner.eofPosition = scanner.source.length; 417 while(scanner.getNextCharAsJavaIdentifierPart()){} 418 scanner.eofPosition = temp; 419 } 420 lastIdentifierStart = scanner.startPosition; 421 lastIdentifierEnd = scanner.currentPosition - 1; 422 lastIdentifier = scanner.getCurrentTokenSource(); 423 } 424 break; 425 } 426 } while (token != TerminalTokens.TokenNameEOF); 427 } else { 428 scanner.resetTo(selectionStart, selectionEnd); 429 430 boolean expectingIdentifier = true; 431 try { 432 do { 433 token = scanner.getNextToken(); 434 435 switch (token) { 436 case TerminalTokens.TokenNamethis : 437 case TerminalTokens.TokenNamesuper : 438 case TerminalTokens.TokenNameIdentifier : 439 if (!expectingIdentifier) 440 return false; 441 lastIdentifier = scanner.getCurrentTokenSource(); 442 lastIdentifierStart = scanner.startPosition; 443 lastIdentifierEnd = scanner.currentPosition - 1; 444 if(lastIdentifierEnd > selectionEnd) { 445 lastIdentifierEnd = selectionEnd; 446 lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1); 447 } 448 449 expectingIdentifier = false; 450 break; 451 case TerminalTokens.TokenNameDOT : 452 if (expectingIdentifier) 453 return false; 454 expectingIdentifier = true; 455 break; 456 case TerminalTokens.TokenNameEOF : 457 if (expectingIdentifier) 458 return false; 459 break; 460 case TerminalTokens.TokenNameLESS : 461 if(!checkTypeArgument(scanner)) 462 return false; 463 break; 464 case TerminalTokens.TokenNameAT: 465 if(scanner.startPosition != scanner.initialPosition) 466 return false; 467 break; 468 default : 469 return false; 470 } 471 } while (token != TerminalTokens.TokenNameEOF); 472 } catch (InvalidInputException e) { 473 return false; 474 } 475 } 476 if (lastIdentifierStart > 0) { 477 this.actualSelectionStart = lastIdentifierStart; 478 this.actualSelectionEnd = lastIdentifierEnd; 479 this.selectedIdentifier = lastIdentifier; 480 return true; 481 } 482 return false; 483 } 484 private boolean checkTypeArgument(Scanner scanner) throws InvalidInputException { 485 int depth = 1; 486 int token; 487 StringBuffer buffer = new StringBuffer (); 488 do { 489 token = scanner.getNextToken(); 490 491 switch(token) { 492 case TerminalTokens.TokenNameLESS : 493 depth++; 494 buffer.append(scanner.getCurrentTokenSource()); 495 break; 496 case TerminalTokens.TokenNameGREATER : 497 depth--; 498 buffer.append(scanner.getCurrentTokenSource()); 499 break; 500 case TerminalTokens.TokenNameRIGHT_SHIFT : 501 depth-=2; 502 buffer.append(scanner.getCurrentTokenSource()); 503 break; 504 case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT : 505 depth-=3; 506 buffer.append(scanner.getCurrentTokenSource()); 507 break; 508 case TerminalTokens.TokenNameextends : 509 case TerminalTokens.TokenNamesuper : 510 buffer.append(' '); 511 buffer.append(scanner.getCurrentTokenSource()); 512 buffer.append(' '); 513 break; 514 case TerminalTokens.TokenNameCOMMA : 515 if(depth == 1) { 516 int length = buffer.length(); 517 char[] typeRef = new char[length]; 518 buffer.getChars(0, length, typeRef, 0); 519 try { 520 Signature.createTypeSignature(typeRef, true); 521 buffer = new StringBuffer (); 522 } catch(IllegalArgumentException e) { 523 return false; 524 } 525 } 526 break; 527 default : 528 buffer.append(scanner.getCurrentTokenSource()); 529 break; 530 531 } 532 if(depth < 0) { 533 return false; 534 } 535 } while (depth != 0 && token != TerminalTokens.TokenNameEOF); 536 537 if(depth == 0) { 538 int length = buffer.length() - 1; 539 char[] typeRef = new char[length]; 540 buffer.getChars(0, length, typeRef, 0); 541 try { 542 Signature.createTypeSignature(typeRef, true); 543 return true; 544 } catch(IllegalArgumentException e) { 545 return false; 546 } 547 } 548 549 return false; 550 } 551 552 public AssistParser getParser() { 553 return this.parser; 554 } 555 556 560 private boolean isLocal(ReferenceBinding binding) { 561 if(binding instanceof ParameterizedTypeBinding) { 562 return isLocal(((ParameterizedTypeBinding)binding).genericType()); 563 } 564 if (!(binding instanceof SourceTypeBinding)) return false; 565 if (binding instanceof LocalTypeBinding) return true; 566 if (binding instanceof MemberTypeBinding) { 567 return isLocal(((MemberTypeBinding)binding).enclosingType); 568 } 569 return false; 570 } 571 572 583 public void select( 584 ICompilationUnit sourceUnit, 585 int selectionSourceStart, 586 int selectionSourceEnd) { 587 588 char[] source = sourceUnit.getContents(); 589 590 if(DEBUG) { 591 System.out.print("SELECTION IN "); System.out.print(sourceUnit.getFileName()); 593 System.out.print(" FROM "); System.out.print(selectionSourceStart); 595 System.out.print(" TO "); System.out.println(selectionSourceEnd); 597 System.out.println("SELECTION - Source :"); System.out.println(source); 599 } 600 if (!checkSelection(source, selectionSourceStart, selectionSourceEnd)) { 601 return; 602 } 603 if (DEBUG) { 604 System.out.print("SELECTION - Checked : \""); System.out.print(new String (source, actualSelectionStart, actualSelectionEnd-actualSelectionStart+1)); 606 System.out.println('"'); 607 } 608 try { 609 this.acceptedAnswer = false; 610 CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit); 611 CompilationUnitDeclaration parsedUnit = 612 this.parser.dietParse(sourceUnit, result, this.actualSelectionStart, this.actualSelectionEnd); 613 614 if (parsedUnit != null) { 615 if(DEBUG) { 616 System.out.println("SELECTION - Diet AST :"); System.out.println(parsedUnit.toString()); 618 } 619 620 if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) { 622 char[][] tokens = 623 ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens; 624 this.noProposal = false; 625 this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.')); 626 return; 627 } 628 ImportReference[] imports = parsedUnit.imports; 629 if (imports != null) { 630 for (int i = 0, length = imports.length; i < length; i++) { 631 ImportReference importReference = imports[i]; 632 if (importReference instanceof SelectionOnImportReference) { 633 char[][] tokens = ((SelectionOnImportReference) importReference).tokens; 634 this.noProposal = false; 635 this.requestor.acceptPackage(CharOperation.concatWith(tokens, '.')); 636 this.nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), false, false, IJavaSearchConstants.TYPE, this); 637 638 this.lookupEnvironment.buildTypeBindings(parsedUnit, null ); 639 if ((this.unitScope = parsedUnit.scope) != null) { 640 int tokenCount = tokens.length; 641 char[] lastToken = tokens[tokenCount - 1]; 642 char[][] qualifierTokens = CharOperation.subarray(tokens, 0, tokenCount - 1); 643 644 if(qualifierTokens != null && qualifierTokens.length > 0) { 645 Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens); 646 if(binding != null && binding instanceof ReferenceBinding) { 647 ReferenceBinding ref = (ReferenceBinding) binding; 648 selectMemberTypeFromImport(parsedUnit, lastToken, ref, importReference.isStatic()); 649 if(importReference.isStatic()) { 650 selectStaticFieldFromStaticImport(parsedUnit, lastToken, ref); 651 selectStaticMethodFromStaticImport(parsedUnit, lastToken, ref); 652 } 653 } 654 } 655 } 656 657 if(!this.acceptedAnswer) { 659 acceptQualifiedTypes(); 660 if (!this.acceptedAnswer) { 661 this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaSearchConstants.TYPE, this); 662 if(!this.acceptedAnswer) { 664 acceptQualifiedTypes(); 665 } 666 } 667 } 668 if(this.noProposal && this.problem != null) { 669 this.requestor.acceptError(this.problem); 670 } 671 return; 672 } 673 } 674 } 675 if (parsedUnit.types != null || parsedUnit.isPackageInfo()) { 676 if(selectDeclaration(parsedUnit)) 677 return; 678 this.lookupEnvironment.buildTypeBindings(parsedUnit, null ); 679 if ((this.unitScope = parsedUnit.scope) != null) { 680 try { 681 this.lookupEnvironment.completeTypeBindings(parsedUnit, true); 682 parsedUnit.scope.faultInTypes(); 683 ASTNode node = null; 684 if (parsedUnit.types != null) 685 node = parseBlockStatements(parsedUnit, selectionSourceStart); 686 if(DEBUG) { 687 System.out.println("SELECTION - AST :"); System.out.println(parsedUnit.toString()); 689 } 690 parsedUnit.resolve(); 691 if (node != null) { 692 selectLocalDeclaration(node); 693 } 694 } catch (SelectionNodeFound e) { 695 if (e.binding != null) { 696 if(DEBUG) { 697 System.out.println("SELECTION - Selection binding:"); System.out.println(e.binding.toString()); 699 } 700 selectFrom(e.binding, parsedUnit, e.isDeclaration); 702 } 703 } 704 } 705 } 706 } 707 if (!this.acceptedAnswer) { 710 this.nameEnvironment.findTypes(this.selectedIdentifier, false, false, IJavaSearchConstants.TYPE, this); 711 712 if(!this.acceptedAnswer) { 714 acceptQualifiedTypes(); 715 } 716 } 717 if(this.noProposal && this.problem != null) { 718 this.requestor.acceptError(this.problem); 719 } 720 } catch (IndexOutOfBoundsException e) { if(DEBUG) { 722 System.out.println("Exception caught by SelectionEngine:"); e.printStackTrace(System.out); 724 } 725 } catch (AbortCompilation e) { if(DEBUG) { 727 System.out.println("Exception caught by SelectionEngine:"); e.printStackTrace(System.out); 729 } 730 } finally { 731 reset(); 732 } 733 } 734 735 private void selectMemberTypeFromImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref, boolean staticOnly) { 736 int fieldLength = lastToken.length; 737 ReferenceBinding[] memberTypes = ref.memberTypes(); 738 next : for (int j = 0; j < memberTypes.length; j++) { 739 ReferenceBinding memberType = memberTypes[j]; 740 741 if (fieldLength > memberType.sourceName.length) 742 continue next; 743 744 if (staticOnly && !memberType.isStatic()) 745 continue next; 746 747 if (!CharOperation.equals(lastToken, memberType.sourceName, true)) 748 continue next; 749 750 this.selectFrom(memberType, parsedUnit, false); 751 } 752 } 753 754 private void selectStaticFieldFromStaticImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) { 755 int fieldLength = lastToken.length; 756 FieldBinding[] fields = ref.fields(); 757 next : for (int j = 0; j < fields.length; j++) { 758 FieldBinding field = fields[j]; 759 760 if (fieldLength > field.name.length) 761 continue next; 762 763 if (field.isSynthetic()) 764 continue next; 765 766 if (!field.isStatic()) 767 continue next; 768 769 if (!CharOperation.equals(lastToken, field.name, true)) 770 continue next; 771 772 this.selectFrom(field, parsedUnit, false); 773 } 774 } 775 776 private void selectStaticMethodFromStaticImport(CompilationUnitDeclaration parsedUnit, char[] lastToken, ReferenceBinding ref) { 777 int methodLength = lastToken.length; 778 MethodBinding[] methods = ref.methods(); 779 next : for (int j = 0; j < methods.length; j++) { 780 MethodBinding method = methods[j]; 781 782 if (method.isSynthetic()) continue next; 783 784 if (method.isDefaultAbstract()) continue next; 785 786 if (method.isConstructor()) continue next; 787 788 if (!method.isStatic()) continue next; 789 790 if (methodLength > method.selector.length) 791 continue next; 792 793 if (!CharOperation.equals(lastToken, method.selector, true)) 794 continue next; 795 796 this.selectFrom(method, parsedUnit, false); 797 } 798 } 799 800 private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit, boolean isDeclaration) { 801 if(binding instanceof TypeVariableBinding) { 802 TypeVariableBinding typeVariableBinding = (TypeVariableBinding) binding; 803 Binding enclosingElement = typeVariableBinding.declaringElement; 804 this.noProposal = false; 805 806 if(enclosingElement instanceof SourceTypeBinding) { 807 SourceTypeBinding enclosingType = (SourceTypeBinding) enclosingElement; 808 if (isLocal(enclosingType) && this.requestor instanceof SelectionRequestor) { 809 ((SelectionRequestor)this.requestor).acceptLocalTypeParameter(typeVariableBinding); 810 } else { 811 this.requestor.acceptTypeParameter( 812 enclosingType.qualifiedPackageName(), 813 enclosingType.qualifiedSourceName(), 814 typeVariableBinding.sourceName(), 815 false, 816 this.actualSelectionStart, 817 this.actualSelectionEnd); 818 } 819 } else if(enclosingElement instanceof MethodBinding) { 820 MethodBinding enclosingMethod = (MethodBinding) enclosingElement; 821 if (isLocal(enclosingMethod.declaringClass) && this.requestor instanceof SelectionRequestor) { 822 ((SelectionRequestor)this.requestor).acceptLocalMethodTypeParameter(typeVariableBinding); 823 } else { 824 this.requestor.acceptMethodTypeParameter( 825 enclosingMethod.declaringClass.qualifiedPackageName(), 826 enclosingMethod.declaringClass.qualifiedSourceName(), 827 enclosingMethod.isConstructor() 828 ? enclosingMethod.declaringClass.sourceName() 829 : enclosingMethod.selector, 830 enclosingMethod.sourceStart(), 831 enclosingMethod.sourceEnd(), 832 typeVariableBinding.sourceName(), 833 false, 834 this.actualSelectionStart, 835 this.actualSelectionEnd); 836 } 837 } 838 this.acceptedAnswer = true; 839 } else if (binding instanceof ReferenceBinding) { 840 ReferenceBinding typeBinding = (ReferenceBinding) binding; 841 if(typeBinding instanceof ProblemReferenceBinding) { 842 typeBinding = typeBinding.closestMatch(); 843 } 844 if (typeBinding == null) return; 845 if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) { 846 this.noProposal = false; 847 ((SelectionRequestor)this.requestor).acceptLocalType(typeBinding); 848 } else { 849 this.noProposal = false; 850 851 this.requestor.acceptType( 852 typeBinding.qualifiedPackageName(), 853 typeBinding.qualifiedSourceName(), 854 typeBinding.modifiers, 855 false, 856 typeBinding.computeUniqueKey(), 857 this.actualSelectionStart, 858 this.actualSelectionEnd); 859 } 860 this.acceptedAnswer = true; 861 } else 862 if (binding instanceof MethodBinding) { 863 MethodBinding methodBinding = (MethodBinding) binding; 864 this.noProposal = false; 865 866 boolean isValuesOrValueOf = false; 867 if(binding instanceof SyntheticMethodBinding) { 868 SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) binding; 869 if(syntheticMethodBinding.kind == SyntheticMethodBinding.EnumValues 870 || syntheticMethodBinding.kind == SyntheticMethodBinding.EnumValueOf) { 871 isValuesOrValueOf = true; 872 } 873 } 874 875 if(!isValuesOrValueOf && !methodBinding.isSynthetic()) { 876 TypeBinding[] parameterTypes = methodBinding.original().parameters; 877 int length = parameterTypes.length; 878 char[][] parameterPackageNames = new char[length][]; 879 char[][] parameterTypeNames = new char[length][]; 880 String [] parameterSignatures = new String [length]; 881 for (int i = 0; i < length; i++) { 882 parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName(); 883 parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName(); 884 parameterSignatures[i] = new String (getSignature(parameterTypes[i])).replace('/', '.'); 885 } 886 887 TypeVariableBinding[] typeVariables = methodBinding.original().typeVariables; 888 length = typeVariables == null ? 0 : typeVariables.length; 889 char[][] typeParameterNames = new char[length][]; 890 char[][][] typeParameterBoundNames = new char[length][][]; 891 for (int i = 0; i < length; i++) { 892 TypeVariableBinding typeVariable = typeVariables[i]; 893 typeParameterNames[i] = typeVariable.sourceName; 894 if (typeVariable.firstBound == null) { 895 typeParameterBoundNames[i] = new char[0][]; 896 } else if (typeVariable.firstBound == typeVariable.superclass) { 897 int boundCount = 1 + (typeVariable.superInterfaces == null ? 0 : typeVariable.superInterfaces.length); 898 typeParameterBoundNames[i] = new char[boundCount][]; 899 typeParameterBoundNames[i][0] = typeVariable.superclass.sourceName; 900 for (int j = 1; j < boundCount; j++) { 901 typeParameterBoundNames[i][j] = typeVariables[i].superInterfaces[j - 1].sourceName; 902 } 903 } else { 904 int boundCount = typeVariable.superInterfaces == null ? 0 : typeVariable.superInterfaces.length; 905 typeParameterBoundNames[i] = new char[boundCount][]; 906 for (int j = 0; j < boundCount; j++) { 907 typeParameterBoundNames[i][j] = typeVariables[i].superInterfaces[j].sourceName; 908 } 909 } 910 } 911 912 ReferenceBinding declaringClass = methodBinding.declaringClass; 913 if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) { 914 ((SelectionRequestor)this.requestor).acceptLocalMethod(methodBinding); 915 } else { 916 this.requestor.acceptMethod( 917 declaringClass.qualifiedPackageName(), 918 declaringClass.qualifiedSourceName(), 919 declaringClass.enclosingType() == null ? null : new String (getSignature(declaringClass.enclosingType())), 920 methodBinding.isConstructor() 921 ? declaringClass.sourceName() 922 : methodBinding.selector, 923 parameterPackageNames, 924 parameterTypeNames, 925 parameterSignatures, 926 typeParameterNames, 927 typeParameterBoundNames, 928 methodBinding.isConstructor(), 929 isDeclaration, 930 methodBinding.computeUniqueKey(), 931 this.actualSelectionStart, 932 this.actualSelectionEnd); 933 } 934 } 935 this.acceptedAnswer = true; 936 } else 937 if (binding instanceof FieldBinding) { 938 FieldBinding fieldBinding = (FieldBinding) binding; 939 ReferenceBinding declaringClass = fieldBinding.declaringClass; 940 if (declaringClass != null) { this.noProposal = false; 942 if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) { 943 ((SelectionRequestor)this.requestor).acceptLocalField(fieldBinding); 944 } else { 945 this.requestor.acceptField( 946 declaringClass.qualifiedPackageName(), 947 declaringClass.qualifiedSourceName(), 948 fieldBinding.name, 949 false, 950 fieldBinding.computeUniqueKey(), 951 this.actualSelectionStart, 952 this.actualSelectionEnd); 953 } 954 this.acceptedAnswer = true; 955 } 956 } else 957 if (binding instanceof LocalVariableBinding) { 958 if (this.requestor instanceof SelectionRequestor) { 959 ((SelectionRequestor)this.requestor).acceptLocalVariable((LocalVariableBinding)binding); 960 this.acceptedAnswer = true; 961 } else { 962 selectFrom(((LocalVariableBinding) binding).type, parsedUnit, false); 964 } 965 } else 966 if (binding instanceof ArrayBinding) { 967 selectFrom(((ArrayBinding) binding).leafComponentType, parsedUnit, false); 968 } else 970 if (binding instanceof PackageBinding) { 971 PackageBinding packageBinding = (PackageBinding) binding; 972 this.noProposal = false; 973 this.requestor.acceptPackage(packageBinding.readableName()); 974 this.acceptedAnswer = true; 975 } else 976 if(binding instanceof BaseTypeBinding) { 977 this.acceptedAnswer = true; 978 } 979 } 980 981 984 private void selectLocalDeclaration(ASTNode node) { 985 final char[] assistIdentifier = this.getParser().assistIdentifier(); 988 if (assistIdentifier == null) return; 989 990 class Visitor extends ASTVisitor { 991 public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { 992 if (constructorDeclaration.selector == assistIdentifier){ 993 if (constructorDeclaration.binding != null) { 994 throw new SelectionNodeFound(constructorDeclaration.binding); 995 } else { 996 if (constructorDeclaration.scope != null) { 997 throw new SelectionNodeFound(new MethodBinding(constructorDeclaration.modifiers, constructorDeclaration.selector, null, null, null, constructorDeclaration.scope.referenceType().binding)); 998 } 999 } 1000 } 1001 return true; 1002 } 1003 public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { 1004 if (fieldDeclaration.name == assistIdentifier){ 1005 throw new SelectionNodeFound(fieldDeclaration.binding); 1006 } 1007 return true; 1008 } 1009 public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) { 1010 if (localTypeDeclaration.name == assistIdentifier) { 1011 throw new SelectionNodeFound(localTypeDeclaration.binding); 1012 } 1013 return true; 1014 } 1015 public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) { 1016 if (memberTypeDeclaration.name == assistIdentifier) { 1017 throw new SelectionNodeFound(memberTypeDeclaration.binding); 1018 } 1019 return true; 1020 } 1021 public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { 1022 if (methodDeclaration.selector == assistIdentifier){ 1023 if (methodDeclaration.binding != null) { 1024 throw new SelectionNodeFound(methodDeclaration.binding); 1025 } else { 1026 if (methodDeclaration.scope != null) { 1027 throw new SelectionNodeFound(new MethodBinding(methodDeclaration.modifiers, methodDeclaration.selector, null, null, null, methodDeclaration.scope.referenceType().binding)); 1028 } 1029 } 1030 } 1031 return true; 1032 } 1033 public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { 1034 if (typeDeclaration.name == assistIdentifier) { 1035 throw new SelectionNodeFound(typeDeclaration.binding); 1036 } 1037 return true; 1038 } 1039 public boolean visit(TypeParameter typeParameter, BlockScope scope) { 1040 if (typeParameter.name == assistIdentifier) { 1041 throw new SelectionNodeFound(typeParameter.binding); 1042 } 1043 return true; 1044 } 1045 public boolean visit(TypeParameter typeParameter, ClassScope scope) { 1046 if (typeParameter.name == assistIdentifier) { 1047 throw new SelectionNodeFound(typeParameter.binding); 1048 } 1049 return true; 1050 } 1051 } 1052 1053 if (node instanceof AbstractMethodDeclaration) { 1054 ((AbstractMethodDeclaration)node).traverse(new Visitor(), (ClassScope)null); 1055 } else { 1056 ((FieldDeclaration)node).traverse(new Visitor(), (MethodScope)null); 1057 } 1058 } 1059 1060 1077 public void selectType(ISourceType sourceType, char[] typeName, SourceTypeElementInfo[] topLevelTypes, boolean searchInEnvironment) { 1078 try { 1079 this.acceptedAnswer = false; 1080 1081 if (CharOperation.indexOf('<', typeName) != -1) { 1083 char[] typeSig = Signature.createCharArrayTypeSignature(typeName, false); 1084 typeSig = Signature.getTypeErasure(typeSig); 1085 typeName = Signature.toCharArray(typeSig); 1086 } 1087 1088 ISourceType outerType = sourceType; 1090 ISourceType parent = sourceType.getEnclosingType(); 1091 while (parent != null) { 1092 outerType = parent; 1093 parent = parent.getEnclosingType(); 1094 } 1095 CompilationResult result = new CompilationResult(outerType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit); 1097 if (!(sourceType instanceof SourceTypeElementInfo)) return; 1098 SourceType typeHandle = (SourceType) ((SourceTypeElementInfo)sourceType).getHandle(); 1099 int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE; 1100 if (typeHandle.isAnonymous() || typeHandle.isLocal()) 1101 flags |= SourceTypeConverter.LOCAL_TYPE; 1102 CompilationUnitDeclaration parsedUnit = 1103 SourceTypeConverter.buildCompilationUnit( 1104 topLevelTypes, 1105 flags, 1106 this.parser.problemReporter(), 1107 result); 1108 1109 if (parsedUnit != null && parsedUnit.types != null) { 1110 if(DEBUG) { 1111 System.out.println("SELECTION - Diet AST :"); System.out.println(parsedUnit.toString()); 1113 } 1114 TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(typeHandle); 1116 1117 if (typeDecl != null) { 1118 1119 FieldDeclaration field = new FieldDeclaration(); 1122 int dot; 1123 if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) { 1124 this.selectedIdentifier = typeName; 1125 field.type = new SelectionOnSingleTypeReference(typeName, -1); 1126 } else { 1128 char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot); 1129 char[] selectionIdentifier = 1130 CharOperation.subarray(typeName, dot + 1, typeName.length); 1131 this.selectedIdentifier = selectionIdentifier; 1132 field.type = 1133 new SelectionOnQualifiedTypeReference( 1134 previousIdentifiers, 1135 selectionIdentifier, 1136 new long[previousIdentifiers.length + 1]); 1137 } 1138 field.name = "<fakeField>".toCharArray(); typeDecl.fields = new FieldDeclaration[] { field }; 1140 1141 this.lookupEnvironment.buildTypeBindings(parsedUnit, null ); 1143 if ((this.unitScope = parsedUnit.scope) != null) { 1144 try { 1145 this.lookupEnvironment.completeTypeBindings(parsedUnit, true); 1148 1149 parsedUnit.scope.faultInTypes(); 1151 parsedUnit.resolve(); 1152 } catch (SelectionNodeFound e) { 1153 if (e.binding != null) { 1154 if(DEBUG) { 1155 System.out.println("SELECTION - Selection binding :"); System.out.println(e.binding.toString()); 1157 } 1158 selectFrom(e.binding, parsedUnit, e.isDeclaration); 1160 } 1161 } 1162 } 1163 } 1164 } 1165 if (!this.acceptedAnswer && searchInEnvironment) { 1168 if (this.selectedIdentifier != null) { 1169 this.nameEnvironment.findTypes(typeName, false, false, IJavaSearchConstants.TYPE, this); 1170 1171 if(!this.acceptedAnswer) { 1173 acceptQualifiedTypes(); 1174 } 1175 } 1176 } 1177 if(this.noProposal && this.problem != null) { 1178 this.requestor.acceptError(this.problem); 1179 } 1180 } catch (AbortCompilation e) { } finally { 1182 reset(); 1183 } 1184 } 1185 1186 private boolean selectDeclaration(CompilationUnitDeclaration compilationUnit){ 1188 1189 char[] assistIdentifier = this.getParser().assistIdentifier(); 1192 if (assistIdentifier == null) return false; 1193 1194 ImportReference currentPackage = compilationUnit.currentPackage; 1195 char[] packageName = currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(currentPackage.tokens, '.'); 1196 TypeDeclaration[] types = compilationUnit.types; 1198 for (int i = 0, length = types == null ? 0 : types.length; i < length; i++){ 1199 if(selectDeclaration(types[i], assistIdentifier, packageName)) 1200 return true; 1201 } 1202 return false; 1203 } 1204 1205 private boolean selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier, char[] packageName){ 1207 1208 if (typeDeclaration.name == assistIdentifier){ 1209 char[] qualifiedSourceName = null; 1210 1211 TypeDeclaration enclosingType = typeDeclaration; 1212 while(enclosingType != null) { 1213 qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.'); 1214 enclosingType = enclosingType.enclosingType; 1215 } 1216 char[] uniqueKey = typeDeclaration.binding != null ? typeDeclaration.binding.computeUniqueKey() : null; 1217 1218 this.requestor.acceptType( 1219 packageName, 1220 qualifiedSourceName, 1221 typeDeclaration.modifiers, 1222 true, 1223 uniqueKey, 1224 this.actualSelectionStart, 1225 this.actualSelectionEnd); 1226 1227 this.noProposal = false; 1228 return true; 1229 } 1230 TypeDeclaration[] memberTypes = typeDeclaration.memberTypes; 1231 for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++){ 1232 if(selectDeclaration(memberTypes[i], assistIdentifier, packageName)) 1233 return true; 1234 } 1235 FieldDeclaration[] fields = typeDeclaration.fields; 1236 for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++){ 1237 if (fields[i].name == assistIdentifier){ 1238 char[] qualifiedSourceName = null; 1239 1240 TypeDeclaration enclosingType = typeDeclaration; 1241 while(enclosingType != null) { 1242 qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.'); 1243 enclosingType = enclosingType.enclosingType; 1244 } 1245 FieldDeclaration field = fields[i]; 1246 this.requestor.acceptField( 1247 packageName, 1248 qualifiedSourceName, 1249 field.name, 1250 true, 1251 field.binding != null ? field.binding.computeUniqueKey() : null, 1252 this.actualSelectionStart, 1253 this.actualSelectionEnd); 1254 1255 this.noProposal = false; 1256 return true; 1257 } 1258 } 1259 AbstractMethodDeclaration[] methods = typeDeclaration.methods; 1260 for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){ 1261 AbstractMethodDeclaration method = methods[i]; 1262 1263 if (method.selector == assistIdentifier){ 1264 char[] qualifiedSourceName = null; 1265 1266 TypeDeclaration enclosingType = typeDeclaration; 1267 while(enclosingType != null) { 1268 qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.'); 1269 enclosingType = enclosingType.enclosingType; 1270 } 1271 1272 this.requestor.acceptMethod( 1273 packageName, 1274 qualifiedSourceName, 1275 null, method.selector, 1277 null, null, null, null, null, method.isConstructor(), 1283 true, 1284 method.binding != null ? method.binding.computeUniqueKey() : null, 1285 this.actualSelectionStart, 1286 this.actualSelectionEnd); 1287 1288 this.noProposal = false; 1289 return true; 1290 } 1291 1292 TypeParameter[] methodTypeParameters = method.typeParameters(); 1293 for (int j = 0, length2 = methodTypeParameters == null ? 0 : methodTypeParameters.length; j < length2; j++){ 1294 TypeParameter methodTypeParameter = methodTypeParameters[j]; 1295 1296 if(methodTypeParameter.name == assistIdentifier) { 1297 char[] qualifiedSourceName = null; 1298 1299 TypeDeclaration enclosingType = typeDeclaration; 1300 while(enclosingType != null) { 1301 qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.'); 1302 enclosingType = enclosingType.enclosingType; 1303 } 1304 1305 this.requestor.acceptMethodTypeParameter( 1306 packageName, 1307 qualifiedSourceName, 1308 method.selector, 1309 method.sourceStart, 1310 method.sourceEnd, 1311 methodTypeParameter.name, 1312 true, 1313 this.actualSelectionStart, 1314 this.actualSelectionEnd); 1315 1316 this.noProposal = false; 1317 return true; 1318 } 1319 } 1320 } 1321 1322 TypeParameter[] typeParameters = typeDeclaration.typeParameters; 1323 for (int i = 0, length = typeParameters == null ? 0 : typeParameters.length; i < length; i++){ 1324 TypeParameter typeParameter = typeParameters[i]; 1325 if(typeParameter.name == assistIdentifier) { 1326 char[] qualifiedSourceName = null; 1327 1328 TypeDeclaration enclosingType = typeDeclaration; 1329 while(enclosingType != null) { 1330 qualifiedSourceName = CharOperation.concat(enclosingType.name, qualifiedSourceName, '.'); 1331 enclosingType = enclosingType.enclosingType; 1332 } 1333 1334 this.requestor.acceptTypeParameter( 1335 packageName, 1336 qualifiedSourceName, 1337 typeParameter.name, 1338 true, 1339 this.actualSelectionStart, 1340 this.actualSelectionEnd); 1341 1342 this.noProposal = false; 1343 return true; 1344 } 1345 } 1346 1347 return false; 1348 } 1349} 1350 | Popular Tags |