if (overridingFT == null || overriddenFT == null) {
return false;
}
Type overridingFTReturnType = overridingFT.getReturnType();
Type overriddenFTReturnType = overriddenFT.getReturnType();
Type[] overridingNormalPT = overridingFT.getNormalParameterTypes();
Type[] overriddenNormalPT = overriddenFT.getNormalParameterTypes();
Type[] overridingPositionalPT = overridingFT.getOptionalParameterTypes();
Type[] overriddenPositionalPT = overriddenFT.getOptionalParameterTypes();
Map<String, Type> overridingNamedPT = overridingFT.getNamedParameterTypes();
Map<String, Type> overriddenNamedPT = overriddenFT.getNamedParameterTypes();
// CTEC.INVALID_OVERRIDE_REQUIRED, CTEC.INVALID_OVERRIDE_POSITIONAL and CTEC.INVALID_OVERRIDE_NAMED
if (overridingNormalPT.length > overriddenNormalPT.length) {
errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_REQUIRED,
errorNameTarget,
overriddenNormalPT.length,
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
if (overridingNormalPT.length + overridingPositionalPT.length < overriddenPositionalPT.length
+ overriddenNormalPT.length) {
errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_POSITIONAL,
errorNameTarget,
overriddenPositionalPT.length + overriddenNormalPT.length,
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
// For each named parameter in the overridden method, verify that there is the same name in
// the overriding method, and in the same order.
Set<String> overridingParameterNameSet = overridingNamedPT.keySet();
Iterator<String> overriddenParameterNameIterator = overriddenNamedPT.keySet().iterator();
while (overriddenParameterNameIterator.hasNext()) {
String overriddenParamName = overriddenParameterNameIterator.next();
if (!overridingParameterNameSet.contains(overriddenParamName)) {
// The overridden method expected the overriding method to have overridingParamName,
// but it does not.
errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_OVERRIDE_NAMED,
errorNameTarget,
overriddenParamName,
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
}
// SWC.INVALID_METHOD_OVERRIDE_*
// The following (comparing the function types with isSubtypeOf):
// !overridingFT.isSubtypeOf(overriddenFT)
// is equivalent to the following checks, we break it is split up for the purposes of
// providing better error messages.
// SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE
if (!overriddenFTReturnType.equals(VoidTypeImpl.getInstance())
&& !overridingFTReturnType.isAssignableTo(overriddenFTReturnType)) {
errorReporter.reportTypeErrorForNode(
!isGetter ? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE
: StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE,
errorNameTarget,
overridingFTReturnType,
overriddenFTReturnType,
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
// SWC.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
if (parameterLocations == null) {
return false;
}
int parameterIndex = 0;
for (int i = 0; i < overridingNormalPT.length; i++) {
if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) {
errorReporter.reportTypeErrorForNode(
!isSetter ? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
: StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE,
parameterLocations[parameterIndex],
overridingNormalPT[i],
overriddenNormalPT[i],
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
parameterIndex++;
}
// SWC.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE
for (int i = 0; i < overriddenPositionalPT.length; i++) {
if (!overridingPositionalPT[i].isAssignableTo(overriddenPositionalPT[i])) {
errorReporter.reportTypeErrorForNode(
StaticWarningCode.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE,
parameterLocations[parameterIndex],
overridingPositionalPT[i],
overriddenPositionalPT[i],
overriddenExecutable.getEnclosingElement().getDisplayName());
return true;
}
parameterIndex++;
}
// SWC.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE & SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
Iterator<Entry<String, Type>> overriddenNamedPTIterator = overriddenNamedPT.entrySet().iterator();
while (overriddenNamedPTIterator.hasNext()) {
Entry<String, Type> overriddenNamedPTEntry = overriddenNamedPTIterator.next();
Type overridingType = overridingNamedPT.get(overriddenNamedPTEntry.getKey());
if (overridingType == null) {
// Error, this is never reached- INVALID_OVERRIDE_NAMED would have been created above if
// this could be reached.
continue;
}