1 11 package org.eclipse.jdt.internal.compiler.lookup; 12 13 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; 14 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 16 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 17 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; 18 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; 19 import org.eclipse.jdt.internal.compiler.util.SimpleSet; 20 21 public class MethodVerifier { 22 SourceTypeBinding type; 23 HashtableOfObject inheritedMethods; 24 HashtableOfObject currentMethods; 25 LookupEnvironment environment; 26 private boolean allowCompatibleReturnTypes; 27 44 MethodVerifier(LookupEnvironment environment) { 45 this.type = null; this.inheritedMethods = null; 47 this.currentMethods = null; 48 this.environment = environment; 49 this.allowCompatibleReturnTypes = 50 environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5 51 && environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5; 52 } 53 boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { 54 return doesMethodOverride(one, two) && areReturnTypesCompatible(one, two); 55 } 56 boolean areParametersEqual(MethodBinding one, MethodBinding two) { 57 TypeBinding[] oneArgs = one.parameters; 58 TypeBinding[] twoArgs = two.parameters; 59 if (oneArgs == twoArgs) return true; 60 61 int length = oneArgs.length; 62 if (length != twoArgs.length) return false; 63 64 for (int i = 0; i < length; i++) 65 if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false; 66 return true; 67 } 68 boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { 69 if (one.returnType == two.returnType) return true; 70 71 if (areTypesEqual(one.returnType, two.returnType)) return true; 72 73 if (this.allowCompatibleReturnTypes && 75 one.declaringClass instanceof BinaryTypeBinding && 76 two.declaringClass instanceof BinaryTypeBinding) { 77 return areReturnTypesCompatible0(one, two); 78 } 79 return false; 80 } 81 boolean areReturnTypesCompatible0(MethodBinding one, MethodBinding two) { 82 if (one.returnType.isBaseType()) return false; 84 85 if (!one.declaringClass.isInterface()) { 86 if (one.declaringClass.id == TypeIds.T_JavaLangObject) 87 return two.returnType.isCompatibleWith(one.returnType); return one.returnType.isCompatibleWith(two.returnType); 89 } 90 91 if (two.declaringClass.id == TypeIds.T_JavaLangObject) 93 return one.returnType.isCompatibleWith(two.returnType); 94 95 if (one.declaringClass.implementsInterface(two.declaringClass, true)) 97 return one.returnType.isCompatibleWith(two.returnType); 98 if (two.declaringClass.implementsInterface(one.declaringClass, true)) 99 return two.returnType.isCompatibleWith(one.returnType); 100 101 return one.returnType.isCompatibleWith(two.returnType) 103 || two.returnType.isCompatibleWith(one.returnType); 104 } 105 boolean areTypesEqual(TypeBinding one, TypeBinding two) { 106 if (one == two) return true; 107 108 if (one instanceof UnresolvedReferenceBinding) 113 return ((UnresolvedReferenceBinding) one).resolvedType == two; 114 if (two instanceof UnresolvedReferenceBinding) 115 return ((UnresolvedReferenceBinding) two).resolvedType == one; 116 return false; } 118 boolean canSkipInheritedMethods() { 119 if (this.type.superclass() != null && this.type.superclass().isAbstract()) 120 return false; 121 return this.type.superInterfaces() == Binding.NO_SUPERINTERFACES; 122 } 123 boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) { 124 return two == null || one.declaringClass == two.declaringClass; 126 } 127 void checkAbstractMethod(MethodBinding abstractMethod) { 128 if (mustImplementAbstractMethod(abstractMethod.declaringClass)) { 129 TypeDeclaration typeDeclaration = this.type.scope.referenceContext; 130 if (typeDeclaration != null) { 131 MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(abstractMethod); 132 missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod); 133 } else { 134 problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod); 135 } 136 } 137 } 138 void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length, MethodBinding[] allInheritedMethods) { 139 if (this.type.isAnnotationType()) { problemReporter().annotationCannotOverrideMethod(currentMethod, methods[length - 1]); 141 return; } 143 CompilerOptions options = type.scope.compilerOptions(); 144 int[] overriddenInheritedMethods = length > 1 ? findOverriddenInheritedMethods(methods, length) : null; 147 nextMethod : for (int i = length; --i >= 0;) { 148 MethodBinding inheritedMethod = methods[i]; 149 if (overriddenInheritedMethods == null || overriddenInheritedMethods[i] == 0) { 150 if (currentMethod.isStatic() != inheritedMethod.isStatic()) { problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod); 152 continue nextMethod; 153 } 154 155 if (inheritedMethod.isAbstract()) { 157 if (inheritedMethod.declaringClass.isInterface()) { 158 currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing; 159 } else { 160 currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding; 161 } 162 } else { 167 currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; 168 } 169 170 if (!areReturnTypesCompatible(currentMethod, inheritedMethod)) 171 if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) 172 continue nextMethod; 173 174 if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS) 175 checkExceptions(currentMethod, inheritedMethod); 176 if (inheritedMethod.isFinal()) 177 problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod); 178 if (!isAsVisible(currentMethod, inheritedMethod)) 179 problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod); 180 if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) { 181 if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) { 182 ReferenceBinding declaringClass = inheritedMethod.declaringClass; 184 if (declaringClass.isInterface()) 185 for (int j = length; --j >= 0;) 186 if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false)) 187 continue nextMethod; 188 189 problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod); 190 } 191 } 192 } 193 checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods); 194 } 195 } 196 void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] abstractMethods) { 197 if (concreteMethod.isStatic()) 199 problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods); 201 if (!concreteMethod.isPublic()) { 202 int index = 0, length = abstractMethods.length; 203 if (concreteMethod.isProtected()) { 204 for (; index < length; index++) 205 if (abstractMethods[index].isPublic()) break; 206 } else if (concreteMethod.isDefault()) { 207 for (; index < length; index++) 208 if (!abstractMethods[index].isDefault()) break; 209 } 210 if (index < length) 211 problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods); 212 } 213 if (concreteMethod.thrownExceptions != Binding.NO_EXCEPTIONS) 214 for (int i = abstractMethods.length; --i >= 0;) 215 checkExceptions(concreteMethod, abstractMethods[i]); 216 } 217 223 void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) { 224 ReferenceBinding[] newExceptions = resolvedExceptionTypesFor(newMethod); 225 ReferenceBinding[] inheritedExceptions = resolvedExceptionTypesFor(inheritedMethod); 226 for (int i = newExceptions.length; --i >= 0;) { 227 ReferenceBinding newException = newExceptions[i]; 228 int j = inheritedExceptions.length; 229 while (--j > -1 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){} 230 if (j == -1) 231 if (!newException.isUncheckedException(false)) 232 problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException); 233 } 234 } 235 void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) { 236 } 238 void checkInheritedMethods(MethodBinding[] methods, int length) { 239 if (length > 1) { 240 int[] overriddenInheritedMethods = findOverriddenInheritedMethods(methods, length); 241 if (overriddenInheritedMethods != null) { 242 int index = 0; 245 MethodBinding[] closestMethods = new MethodBinding[length]; 246 for (int i = 0; i < length; i++) 247 if (overriddenInheritedMethods[i] == 0) 248 closestMethods[index++] = methods[i]; 249 if (index > 1 && !checkInheritedReturnTypes(closestMethods, index)) 250 return; 251 } else if (!checkInheritedReturnTypes(methods, length)) { 252 return; 253 } 254 } 255 256 MethodBinding concreteMethod = null; 257 if (!type.isInterface()) { for (int i = length; --i >= 0;) { if (!methods[i].isAbstract()) { 260 concreteMethod = methods[i]; 261 break; 262 } 263 } 264 } 265 if (concreteMethod == null) { 266 if (!this.type.isAbstract()) { 267 for (int i = length; --i >= 0;) { 268 if (mustImplementAbstractMethod(methods[i].declaringClass)) { 269 TypeDeclaration typeDeclaration = this.type.scope.referenceContext; 270 if (typeDeclaration != null) { 271 MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]); 272 missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]); 273 } else { 274 problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]); 275 } 276 return; 277 } 278 } 279 } 280 return; 281 } 282 283 if (length > 1) { 284 MethodBinding[] abstractMethods = new MethodBinding[length - 1]; 285 int index = 0; 286 for (int i = length; --i >= 0;) 287 if (methods[i] != concreteMethod) 288 abstractMethods[index++] = methods[i]; 289 checkConcreteInheritedMethod(concreteMethod, abstractMethods); 290 } 291 } 292 boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { 293 MethodBinding first = methods[0]; 294 int index = length; 295 while (--index > 0 && areReturnTypesCompatible(first, methods[index])){} 296 if (index == 0) 297 return true; 298 299 if (this.type.isInterface()) 301 for (int i = length; --i >= 0;) 302 if (methods[i].declaringClass.id == TypeIds.T_JavaLangObject) 303 return false; problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length); 305 return false; 306 } 307 325 void checkMethods() { 326 boolean mustImplementAbstractMethods = mustImplementAbstractMethods(); 327 boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); char[][] methodSelectors = this.inheritedMethods.keyTable; 329 nextSelector : for (int s = methodSelectors.length; --s >= 0;) { 330 if (methodSelectors[s] == null) continue nextSelector; 331 332 MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]); 333 if (current == null && skipInheritedMethods) 334 continue nextSelector; 335 336 MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s]; 337 if (inherited.length == 1 && current == null) { if (mustImplementAbstractMethods && inherited[0].isAbstract()) 339 checkAbstractMethod(inherited[0]); 340 continue nextSelector; 341 } 342 343 int index = -1; 344 MethodBinding[] matchingInherited = new MethodBinding[inherited.length]; 345 if (current != null) { 346 for (int i = 0, length1 = current.length; i < length1; i++) { 347 MethodBinding currentMethod = current[i]; 348 for (int j = 0, length2 = inherited.length; j < length2; j++) { 349 MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod); 350 if (inheritedMethod != null) { 351 if (doesMethodOverride(currentMethod, inheritedMethod)) { 352 matchingInherited[++index] = inheritedMethod; 353 inherited[j] = null; } 355 } 356 } 357 if (index >= 0) { 358 checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1, inherited); while (index >= 0) matchingInherited[index--] = null; } 361 } 362 } 363 364 for (int i = 0, length = inherited.length; i < length; i++) { 365 MethodBinding inheritedMethod = inherited[i]; 366 if (inheritedMethod == null) continue; 367 368 matchingInherited[++index] = inheritedMethod; 369 for (int j = i + 1; j < length; j++) { 370 MethodBinding otherInheritedMethod = inherited[j]; 371 if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod)) 372 continue; 373 otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod); 374 if (otherInheritedMethod != null) { 375 if (doesMethodOverride(inheritedMethod, otherInheritedMethod)) { 376 matchingInherited[++index] = otherInheritedMethod; 377 inherited[j] = null; } 379 } 380 } 381 if (index == -1) continue; 382 if (index > 0) 383 checkInheritedMethods(matchingInherited, index + 1); else if (mustImplementAbstractMethods && matchingInherited[0].isAbstract()) 385 checkAbstractMethod(matchingInherited[0]); 386 while (index >= 0) matchingInherited[index--] = null; } 388 } 389 } 390 void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) { 391 PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage; 393 if (necessaryPackage == this.type.fPackage) return; 395 ReferenceBinding superType = this.type.superclass(); 396 char[] selector = abstractMethod.selector; 397 do { 398 if (!superType.isValidBinding()) return; 399 if (!superType.isAbstract()) return; 401 if (necessaryPackage == superType.fPackage) { 402 MethodBinding[] methods = superType.getMethods(selector); 403 nextMethod : for (int m = methods.length; --m >= 0;) { 404 MethodBinding method = methods[m]; 405 if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract()) 406 continue nextMethod; 407 if (areMethodsCompatible(method, abstractMethod)) 408 return; } 410 } 411 } while ((superType = superType.superclass()) != abstractMethod.declaringClass); 412 413 problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod); 415 } 416 void computeInheritedMethods() { 417 ReferenceBinding superclass = this.type.isInterface() 418 ? this.type.scope.getJavaLangObject() : this.type.superclass(); computeInheritedMethods(superclass, type.superInterfaces()); 421 } 422 434 void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { 435 438 this.inheritedMethods = new HashtableOfObject(51); ReferenceBinding[] interfacesToVisit = null; 440 int nextPosition = 0; 441 ReferenceBinding[] itsInterfaces = superInterfaces; 442 if (itsInterfaces != Binding.NO_SUPERINTERFACES) { 443 nextPosition = itsInterfaces.length; 444 interfacesToVisit = itsInterfaces; 445 } 446 447 ReferenceBinding superType = superclass; 448 HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); boolean allSuperclassesAreAbstract = true; 450 451 while (superType != null && superType.isValidBinding()) { 452 if (allSuperclassesAreAbstract) { 453 if (superType.isAbstract()) { 454 if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { 456 if (interfacesToVisit == null) { 457 interfacesToVisit = itsInterfaces; 458 nextPosition = interfacesToVisit.length; 459 } else { 460 int itsLength = itsInterfaces.length; 461 if (nextPosition + itsLength >= interfacesToVisit.length) 462 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); 463 nextInterface : for (int a = 0; a < itsLength; a++) { 464 ReferenceBinding next = itsInterfaces[a]; 465 for (int b = 0; b < nextPosition; b++) 466 if (next == interfacesToVisit[b]) continue nextInterface; 467 interfacesToVisit[nextPosition++] = next; 468 } 469 } 470 } 471 } else { 472 allSuperclassesAreAbstract = false; 473 } 474 } 475 476 MethodBinding[] methods = superType.unResolvedMethods(); 477 nextMethod : for (int m = methods.length; --m >= 0;) { 478 MethodBinding inheritedMethod = methods[m]; 479 if (inheritedMethod.isPrivate() || inheritedMethod.isConstructor() || inheritedMethod.isDefaultAbstract()) 480 continue nextMethod; 481 MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector); 482 if (existingMethods != null) { 483 for (int i = 0, length = existingMethods.length; i < length; i++) { 484 if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && areMethodsCompatible(existingMethods[i], inheritedMethod)) { 485 if (inheritedMethod.isDefault() && inheritedMethod.isAbstract()) 486 checkPackagePrivateAbstractMethod(inheritedMethod); 487 continue nextMethod; 488 } 489 } 490 } 491 MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector); 492 if (nonVisible != null) 493 for (int i = 0, l = nonVisible.length; i < l; i++) 494 if (areMethodsCompatible(nonVisible[i], inheritedMethod)) 495 continue nextMethod; 496 497 if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) { 498 if (existingMethods == null) { 499 existingMethods = new MethodBinding[] {inheritedMethod}; 500 } else { 501 int length = existingMethods.length; 502 System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length); 503 existingMethods[length] = inheritedMethod; 504 } 505 this.inheritedMethods.put(inheritedMethod.selector, existingMethods); 506 } else { 507 if (nonVisible == null) { 508 nonVisible = new MethodBinding[] {inheritedMethod}; 509 } else { 510 int length = nonVisible.length; 511 System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length); 512 nonVisible[length] = inheritedMethod; 513 } 514 nonVisibleDefaultMethods.put(inheritedMethod.selector, nonVisible); 515 516 if (inheritedMethod.isAbstract() && !this.type.isAbstract()) problemReporter().abstractMethodCannotBeOverridden(this.type, inheritedMethod); 518 519 MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector); 520 if (current != null) { foundMatch : for (int i = 0, length = current.length; i < length; i++) { 522 if (areMethodsCompatible(current[i], inheritedMethod)) { 523 problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod); 524 break foundMatch; 525 } 526 } 527 } 528 } 529 } 530 superType = superType.superclass(); 531 } 532 if (nextPosition == 0) return; 533 534 SimpleSet skip = findSuperinterfaceCollisions(superclass, superInterfaces); 535 for (int i = 0; i < nextPosition; i++) { 536 superType = interfacesToVisit[i]; 537 if (superType.isValidBinding()) { 538 if (skip != null && skip.includes(superType)) continue; 539 if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { 540 int itsLength = itsInterfaces.length; 541 if (nextPosition + itsLength >= interfacesToVisit.length) 542 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); 543 nextInterface : for (int a = 0; a < itsLength; a++) { 544 ReferenceBinding next = itsInterfaces[a]; 545 for (int b = 0; b < nextPosition; b++) 546 if (next == interfacesToVisit[b]) continue nextInterface; 547 interfacesToVisit[nextPosition++] = next; 548 } 549 } 550 551 MethodBinding[] methods = superType.unResolvedMethods(); 552 nextMethod : for (int m = methods.length; --m >= 0;) { MethodBinding inheritedMethod = methods[m]; 554 MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector); 555 if (existingMethods == null) { 556 existingMethods = new MethodBinding[] {inheritedMethod}; 557 } else { 558 int length = existingMethods.length; 559 for (int e = 0; e < length; e++) 561 if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType)) 562 continue nextMethod; System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length); 564 existingMethods[length] = inheritedMethod; 565 } 566 this.inheritedMethods.put(inheritedMethod.selector, existingMethods); 567 } 568 } 569 } 570 } 571 void computeMethods() { 572 MethodBinding[] methods = type.methods(); 573 int size = methods.length; 574 this.currentMethods = new HashtableOfObject(size == 0 ? 1 : size); for (int m = size; --m >= 0;) { 576 MethodBinding method = methods[m]; 577 if (!(method.isConstructor() || method.isDefaultAbstract())) { MethodBinding[] existingMethods = (MethodBinding[]) this.currentMethods.get(method.selector); 579 if (existingMethods == null) 580 existingMethods = new MethodBinding[1]; 581 else 582 System.arraycopy(existingMethods, 0, 583 (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1); 584 existingMethods[existingMethods.length - 1] = method; 585 this.currentMethods.put(method.selector, existingMethods); 586 } 587 } 588 } 589 MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { 590 if (inheritedMethod == null) return null; 591 if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; return inheritedMethod; 593 } 594 public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { 595 return areParametersEqual(method, inheritedMethod); 596 } 597 SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { 598 return null; } 600 int[] findOverriddenInheritedMethods(MethodBinding[] methods, int length) { 601 int[] toSkip = null; 606 int i = 0; 607 ReferenceBinding declaringClass = methods[i].declaringClass; 608 if (!declaringClass.isInterface()) { 609 ReferenceBinding declaringClass2 = methods[++i].declaringClass; 613 while (declaringClass == declaringClass2) { 614 if (++i == length) return null; 615 declaringClass2 = methods[i].declaringClass; 616 } 617 if (!declaringClass2.isInterface()) { 618 toSkip = new int[length]; 620 do { 621 toSkip[i] = -1; 622 if (++i == length) return toSkip; 623 declaringClass2 = methods[i].declaringClass; 624 } while (!declaringClass2.isInterface()); 625 } 626 } 627 nextMethod : for (; i < length; i++) { 630 if (toSkip != null && toSkip[i] == -1) continue nextMethod; 631 declaringClass = methods[i].declaringClass; 632 for (int j = i + 1; j < length; j++) { 633 if (toSkip != null && toSkip[j] == -1) continue; 634 ReferenceBinding declaringClass2 = methods[j].declaringClass; 635 if (declaringClass == declaringClass2) continue; 636 if (declaringClass.implementsInterface(declaringClass2, true)) { 637 if (toSkip == null) 638 toSkip = new int[length]; 639 toSkip[j] = -1; 640 } else if (declaringClass2.implementsInterface(declaringClass, true)) { 641 if (toSkip == null) 642 toSkip = new int[length]; 643 toSkip[i] = -1; 644 continue nextMethod; 645 } 646 } 647 } 648 return toSkip; 649 } 650 boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) { 651 if (inheritedMethod.modifiers == newMethod.modifiers) return true; 652 653 if (newMethod.isPublic()) return true; if (inheritedMethod.isPublic()) return false; 655 656 if (newMethod.isProtected()) return true; 657 if (inheritedMethod.isProtected()) return false; 658 659 return !newMethod.isPrivate(); } 661 boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { 662 return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true); 664 } 665 boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) { 666 do { 667 if (testClass == superclass) return true; 668 } while ((testClass = testClass.superclass()) != null); 669 return false; 670 } 671 boolean mustImplementAbstractMethod(ReferenceBinding declaringClass) { 672 ReferenceBinding superclass = this.type.superclass(); 675 if (declaringClass.isClass()) { 676 while (superclass.isAbstract() && superclass != declaringClass) 677 superclass = superclass.superclass(); } else { 679 if (this.type.implementsInterface(declaringClass, false)) { 680 if (this.type.isAbstract()) return false; if (!superclass.implementsInterface(declaringClass, true)) return true; 683 } 684 while (superclass.isAbstract() && !superclass.implementsInterface(declaringClass, false)) 685 superclass = superclass.superclass(); } 687 return superclass.isAbstract(); } 689 boolean mustImplementAbstractMethods() { 690 return !this.type.isInterface() && !this.type.isAbstract(); 691 } 692 ProblemReporter problemReporter() { 693 return this.type.scope.problemReporter(); 694 } 695 ProblemReporter problemReporter(MethodBinding currentMethod) { 696 ProblemReporter reporter = problemReporter(); 697 if (currentMethod.declaringClass == type && currentMethod.sourceMethod() != null) reporter.referenceContext = currentMethod.sourceMethod(); 699 return reporter; 700 } 701 711 boolean reportIncompatibleReturnTypeError(MethodBinding currentMethod, MethodBinding inheritedMethod) { 712 problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); 713 return true; 714 } 715 ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) { 716 ReferenceBinding[] exceptions = method.thrownExceptions; 717 if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) 718 return exceptions; 719 720 if (!(method.declaringClass instanceof BinaryTypeBinding)) 721 return Binding.NO_EXCEPTIONS; 723 for (int i = exceptions.length; --i >= 0;) 724 exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true); 725 return exceptions; 726 } 727 void verify(SourceTypeBinding someType) { 728 this.type = someType; 729 computeMethods(); 730 computeInheritedMethods(); 731 checkMethods(); 732 } 733 public String toString() { 734 StringBuffer buffer = new StringBuffer (10); 735 buffer.append("MethodVerifier for type: "); buffer.append(type.readableName()); 737 buffer.append('\n'); 738 buffer.append("\t-inherited methods: "); buffer.append(this.inheritedMethods); 740 return buffer.toString(); 741 } 742 } 743 | Popular Tags |