Report errors for type parameters of properties that are not used in receiver types

This commit is contained in:
Pavel V. Talanov
2015-10-12 14:18:45 +03:00
parent b5537e7d42
commit be15399313
6 changed files with 101 additions and 0 deletions
@@ -269,6 +269,8 @@ public interface Errors {
DiagnosticFactory0<JetDeclaration> TYPE_PARAMETERS_NOT_ALLOWED
= DiagnosticFactory0.create(ERROR, TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE);
DiagnosticFactory0<JetTypeParameter> TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> CYCLIC_GENERIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetTypeParameter> MISPLACED_TYPE_PARAMETER_CONSTRAINTS = DiagnosticFactory0.create(WARNING);
@@ -629,6 +629,8 @@ public class DefaultErrorMessages {
MAP.put(REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, "Cannot use ''{0}'' as reified type parameter", RENDER_TYPE);
MAP.put(TYPE_PARAMETERS_NOT_ALLOWED, "Type parameters are not allowed here");
MAP.put(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER, "Type parameter of a property must be used in its receiver type");
MAP.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes");
MAP.put(MISSING_VAL_ON_ANNOTATION_PARAMETER, "'val' keyword is missing on annotation parameter");
MAP.put(ANNOTATION_CLASS_CONSTRUCTOR_CALL, "Annotation class cannot be instantiated");
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -471,6 +472,33 @@ public class DeclarationsChecker {
checkAccessors(property, propertyDescriptor);
checkTypeParameterConstraints(property);
checkPropertyExposedType(property, propertyDescriptor);
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor);
}
private void checkPropertyTypeParametersAreUsedInReceiverType(@NotNull PropertyDescriptor descriptor) {
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
if (isTypeParameterUsedInReceiverType(typeParameter, descriptor)) continue;
PsiElement typeParameterPsi = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameter);
if (typeParameterPsi instanceof JetTypeParameter) {
trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on((JetTypeParameter) typeParameterPsi));
}
}
}
private static boolean isTypeParameterUsedInReceiverType(
@NotNull final TypeParameterDescriptor parameter,
@NotNull PropertyDescriptor descriptor
) {
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
if (receiverParameter == null) return false;
return TypeUtils.containsSpecialType(receiverParameter.getType(), new Function1<JetType, Boolean>() {
@Override
public Boolean invoke(JetType type) {
return parameter.equals(type.getConstructor().getDeclarationDescriptor());
}
});
}
private void checkPropertyLateInit(@NotNull JetCallableDeclaration property, @NotNull PropertyDescriptor propertyDescriptor) {