Lines 166-174
Link Here
|
166 |
currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; |
166 |
currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding; |
167 |
} |
167 |
} |
168 |
|
168 |
|
169 |
if (!areReturnTypesCompatible(currentMethod, inheritedMethod)) |
169 |
if (!areReturnTypesCompatible(currentMethod, inheritedMethod) |
|
|
170 |
&& (currentMethod.returnType.tagBits & TagBits.HasMissingType) == 0) { |
170 |
if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) |
171 |
if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod)) |
171 |
continue nextMethod; |
172 |
continue nextMethod; |
|
|
173 |
} |
172 |
|
174 |
|
173 |
if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS) |
175 |
if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS) |
174 |
checkExceptions(currentMethod, inheritedMethod); |
176 |
checkExceptions(currentMethod, inheritedMethod); |
Lines 192-197
Link Here
|
192 |
checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods); |
194 |
checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods); |
193 |
} |
195 |
} |
194 |
} |
196 |
} |
|
|
197 |
|
195 |
void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] abstractMethods) { |
198 |
void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] abstractMethods) { |
196 |
// Remember that interfaces can only define public instance methods |
199 |
// Remember that interfaces can only define public instance methods |
197 |
if (concreteMethod.isStatic()) |
200 |
if (concreteMethod.isStatic()) |
Lines 213-218
Link Here
|
213 |
for (int i = abstractMethods.length; --i >= 0;) |
216 |
for (int i = abstractMethods.length; --i >= 0;) |
214 |
checkExceptions(concreteMethod, abstractMethods[i]); |
217 |
checkExceptions(concreteMethod, abstractMethods[i]); |
215 |
} |
218 |
} |
|
|
219 |
|
216 |
/* |
220 |
/* |
217 |
"8.4.4" |
221 |
"8.4.4" |
218 |
Verify that newExceptions are all included in inheritedExceptions. |
222 |
Verify that newExceptions are all included in inheritedExceptions. |
Lines 227-239
Link Here
|
227 |
int j = inheritedExceptions.length; |
231 |
int j = inheritedExceptions.length; |
228 |
while (--j > -1 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/} |
232 |
while (--j > -1 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/} |
229 |
if (j == -1) |
233 |
if (j == -1) |
230 |
if (!newException.isUncheckedException(false)) |
234 |
if (!newException.isUncheckedException(false) |
|
|
235 |
&& (newException.tagBits & TagBits.HasMissingType) == 0) { |
231 |
problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException); |
236 |
problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException); |
|
|
237 |
} |
232 |
} |
238 |
} |
233 |
} |
239 |
} |
|
|
240 |
|
234 |
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) { |
241 |
void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods) { |
235 |
// no op before 1.5 |
242 |
// no op before 1.5 |
236 |
} |
243 |
} |
|
|
244 |
|
237 |
void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
245 |
void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
238 |
if (superInterfaces == Binding.NO_SUPERINTERFACES) return; |
246 |
if (superInterfaces == Binding.NO_SUPERINTERFACES) return; |
239 |
|
247 |
|
Lines 295-300
Link Here
|
295 |
} |
303 |
} |
296 |
} |
304 |
} |
297 |
} |
305 |
} |
|
|
306 |
|
298 |
void checkInheritedMethods(MethodBinding[] methods, int length) { |
307 |
void checkInheritedMethods(MethodBinding[] methods, int length) { |
299 |
if (length > 1) { |
308 |
if (length > 1) { |
300 |
int[] overriddenInheritedMethods = findOverriddenInheritedMethods(methods, length); |
309 |
int[] overriddenInheritedMethods = findOverriddenInheritedMethods(methods, length); |
Lines 349-354
Link Here
|
349 |
checkConcreteInheritedMethod(concreteMethod, abstractMethods); |
358 |
checkConcreteInheritedMethod(concreteMethod, abstractMethods); |
350 |
} |
359 |
} |
351 |
} |
360 |
} |
|
|
361 |
|
352 |
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { |
362 |
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) { |
353 |
MethodBinding first = methods[0]; |
363 |
MethodBinding first = methods[0]; |
354 |
int index = length; |
364 |
int index = length; |
Lines 447-452
Link Here
|
447 |
} |
457 |
} |
448 |
} |
458 |
} |
449 |
} |
459 |
} |
|
|
460 |
|
450 |
void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) { |
461 |
void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) { |
451 |
// check that the inherited abstract method (package private visibility) is implemented within the same package |
462 |
// check that the inherited abstract method (package private visibility) is implemented within the same package |
452 |
PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage; |
463 |
PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage; |
Lines 473-478
Link Here
|
473 |
// non visible abstract methods cannot be overridden so the type must be defined abstract |
484 |
// non visible abstract methods cannot be overridden so the type must be defined abstract |
474 |
problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod); |
485 |
problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod); |
475 |
} |
486 |
} |
|
|
487 |
|
476 |
void computeInheritedMethods() { |
488 |
void computeInheritedMethods() { |
477 |
ReferenceBinding superclass = this.type.isInterface() |
489 |
ReferenceBinding superclass = this.type.isInterface() |
478 |
? this.type.scope.getJavaLangObject() // check interface methods against Object |
490 |
? this.type.scope.getJavaLangObject() // check interface methods against Object |
Lines 480-485
Link Here
|
480 |
computeInheritedMethods(superclass, type.superInterfaces()); |
492 |
computeInheritedMethods(superclass, type.superInterfaces()); |
481 |
checkForRedundantSuperinterfaces(superclass, type.superInterfaces()); |
493 |
checkForRedundantSuperinterfaces(superclass, type.superInterfaces()); |
482 |
} |
494 |
} |
|
|
495 |
|
483 |
/* |
496 |
/* |
484 |
Binding creation is responsible for reporting: |
497 |
Binding creation is responsible for reporting: |
485 |
- all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations) |
498 |
- all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations) |
Lines 629-634
Link Here
|
629 |
} |
642 |
} |
630 |
} |
643 |
} |
631 |
} |
644 |
} |
|
|
645 |
|
632 |
void computeMethods() { |
646 |
void computeMethods() { |
633 |
MethodBinding[] methods = type.methods(); |
647 |
MethodBinding[] methods = type.methods(); |
634 |
int size = methods.length; |
648 |
int size = methods.length; |
Lines 647-657
Link Here
|
647 |
} |
661 |
} |
648 |
} |
662 |
} |
649 |
} |
663 |
} |
|
|
664 |
|
650 |
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { |
665 |
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { |
651 |
if (inheritedMethod == null) return null; |
666 |
if (inheritedMethod == null) return null; |
652 |
if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match |
667 |
if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match |
653 |
return inheritedMethod; |
668 |
return inheritedMethod; |
654 |
} |
669 |
} |
|
|
670 |
|
655 |
boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
671 |
boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { |
656 |
if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) |
672 |
if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) |
657 |
return false; |
673 |
return false; |
Lines 669-674
Link Here
|
669 |
} |
685 |
} |
670 |
return true; |
686 |
return true; |
671 |
} |
687 |
} |
|
|
688 |
|
672 |
// Answer whether the method overrides the inheritedMethod |
689 |
// Answer whether the method overrides the inheritedMethod |
673 |
// Check the necessary visibility rules & inheritance from the inheritedMethod's declaringClass |
690 |
// Check the necessary visibility rules & inheritance from the inheritedMethod's declaringClass |
674 |
// See isMethodSubsignature() for parameter comparisons |
691 |
// See isMethodSubsignature() for parameter comparisons |
Lines 683-691
Link Here
|
683 |
|
700 |
|
684 |
return isParameterSubsignature(method, inheritedMethod); |
701 |
return isParameterSubsignature(method, inheritedMethod); |
685 |
} |
702 |
} |
|
|
703 |
|
686 |
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
704 |
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { |
687 |
return null; // noop in 1.4 |
705 |
return null; // noop in 1.4 |
688 |
} |
706 |
} |
|
|
707 |
|
689 |
int[] findOverriddenInheritedMethods(MethodBinding[] methods, int length) { |
708 |
int[] findOverriddenInheritedMethods(MethodBinding[] methods, int length) { |
690 |
// NOTE assumes length > 1 |
709 |
// NOTE assumes length > 1 |
691 |
// inherited methods are added as we walk up the superclass hierarchy, then each superinterface |
710 |
// inherited methods are added as we walk up the superclass hierarchy, then each superinterface |
Lines 736-741
Link Here
|
736 |
} |
755 |
} |
737 |
return toSkip; |
756 |
return toSkip; |
738 |
} |
757 |
} |
|
|
758 |
|
739 |
boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) { |
759 |
boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) { |
740 |
if (inheritedMethod.modifiers == newMethod.modifiers) return true; |
760 |
if (inheritedMethod.modifiers == newMethod.modifiers) return true; |
741 |
|
761 |
|
Lines 747-769
Link Here
|
747 |
|
767 |
|
748 |
return !newMethod.isPrivate(); // The inheritedMethod cannot be private since it would not be visible |
768 |
return !newMethod.isPrivate(); // The inheritedMethod cannot be private since it would not be visible |
749 |
} |
769 |
} |
|
|
770 |
|
750 |
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { |
771 |
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) { |
751 |
// skip interface method with the same signature if visible to its declaringClass |
772 |
// skip interface method with the same signature if visible to its declaringClass |
752 |
return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true); |
773 |
return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true); |
753 |
} |
774 |
} |
|
|
775 |
|
754 |
public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
776 |
public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
755 |
return org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector) |
777 |
return org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector) |
756 |
&& isParameterSubsignature(method, inheritedMethod); |
778 |
&& isParameterSubsignature(method, inheritedMethod); |
757 |
} |
779 |
} |
|
|
780 |
|
758 |
boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
781 |
boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { |
759 |
return areParametersEqual(method, inheritedMethod); |
782 |
return areParametersEqual(method, inheritedMethod); |
760 |
} |
783 |
} |
|
|
784 |
|
761 |
boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) { |
785 |
boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) { |
762 |
do { |
786 |
do { |
763 |
if (testClass == superclass) return true; |
787 |
if (testClass == superclass) return true; |
764 |
} while ((testClass = testClass.superclass()) != null); |
788 |
} while ((testClass = testClass.superclass()) != null); |
765 |
return false; |
789 |
return false; |
766 |
} |
790 |
} |
|
|
791 |
|
767 |
boolean mustImplementAbstractMethod(ReferenceBinding declaringClass) { |
792 |
boolean mustImplementAbstractMethod(ReferenceBinding declaringClass) { |
768 |
// if the type's superclass is an abstract class, then all abstract methods must be implemented |
793 |
// if the type's superclass is an abstract class, then all abstract methods must be implemented |
769 |
// otherwise, skip it if the type's superclass must implement any of the inherited methods |
794 |
// otherwise, skip it if the type's superclass must implement any of the inherited methods |
Lines 782-799
Link Here
|
782 |
} |
807 |
} |
783 |
return superclass.isAbstract(); // if it is a concrete class then we have already reported problem against it |
808 |
return superclass.isAbstract(); // if it is a concrete class then we have already reported problem against it |
784 |
} |
809 |
} |
|
|
810 |
|
785 |
boolean mustImplementAbstractMethods() { |
811 |
boolean mustImplementAbstractMethods() { |
786 |
return !this.type.isInterface() && !this.type.isAbstract(); |
812 |
return !this.type.isInterface() && !this.type.isAbstract(); |
787 |
} |
813 |
} |
|
|
814 |
|
788 |
ProblemReporter problemReporter() { |
815 |
ProblemReporter problemReporter() { |
789 |
return this.type.scope.problemReporter(); |
816 |
return this.type.scope.problemReporter(); |
790 |
} |
817 |
} |
|
|
818 |
|
791 |
ProblemReporter problemReporter(MethodBinding currentMethod) { |
819 |
ProblemReporter problemReporter(MethodBinding currentMethod) { |
792 |
ProblemReporter reporter = problemReporter(); |
820 |
ProblemReporter reporter = problemReporter(); |
793 |
if (currentMethod.declaringClass == type && currentMethod.sourceMethod() != null) // only report against the currentMethod if its implemented by the type |
821 |
if (currentMethod.declaringClass == type && currentMethod.sourceMethod() != null) // only report against the currentMethod if its implemented by the type |
794 |
reporter.referenceContext = currentMethod.sourceMethod(); |
822 |
reporter.referenceContext = currentMethod.sourceMethod(); |
795 |
return reporter; |
823 |
return reporter; |
796 |
} |
824 |
} |
|
|
825 |
|
797 |
/** |
826 |
/** |
798 |
* Return true and report an incompatibleReturnType error if currentMethod's |
827 |
* Return true and report an incompatibleReturnType error if currentMethod's |
799 |
* return type is strictly incompatible with inheritedMethod's, else return |
828 |
* return type is strictly incompatible with inheritedMethod's, else return |
Lines 808-813
Link Here
|
808 |
problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); |
837 |
problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod); |
809 |
return true; |
838 |
return true; |
810 |
} |
839 |
} |
|
|
840 |
|
811 |
ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) { |
841 |
ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) { |
812 |
ReferenceBinding[] exceptions = method.thrownExceptions; |
842 |
ReferenceBinding[] exceptions = method.thrownExceptions; |
813 |
if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) |
843 |
if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) |
Lines 820-831
Link Here
|
820 |
exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true); |
850 |
exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true); |
821 |
return exceptions; |
851 |
return exceptions; |
822 |
} |
852 |
} |
|
|
853 |
|
823 |
void verify(SourceTypeBinding someType) { |
854 |
void verify(SourceTypeBinding someType) { |
824 |
this.type = someType; |
855 |
this.type = someType; |
825 |
computeMethods(); |
856 |
computeMethods(); |
826 |
computeInheritedMethods(); |
857 |
computeInheritedMethods(); |
827 |
checkMethods(); |
858 |
checkMethods(); |
828 |
} |
859 |
} |
|
|
860 |
|
829 |
public String toString() { |
861 |
public String toString() { |
830 |
StringBuffer buffer = new StringBuffer(10); |
862 |
StringBuffer buffer = new StringBuffer(10); |
831 |
buffer.append("MethodVerifier for type: "); //$NON-NLS-1$ |
863 |
buffer.append("MethodVerifier for type: "); //$NON-NLS-1$ |