Added error 'public member should specify type' and quick fix

This commit is contained in:
svtk
2011-10-04 14:48:19 +04:00
parent 29e76fda51
commit bdf4173680
21 changed files with 203 additions and 32 deletions
@@ -123,6 +123,8 @@ public interface Errors {
DiagnosticWithParameterFactory<JetNamedDeclaration, JetClass> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticWithParameterFactory.create(ERROR, "Non final member in a final class", DiagnosticParameters.CLASS);
DiagnosticWithParameterFactory<JetNamedDeclaration, JetType> PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Public member should specify a type", DiagnosticParameters.TYPE);
SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning
SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here");
SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = SimpleDiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor");
@@ -481,17 +481,7 @@ public class ClassDescriptorResolver {
JetType type = getVariableType(scopeWithTypeParameters, property, true);
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
boolean hasBody = hasBody(property);
Modality defaultModality = getDefaultModality(containingDeclaration, hasBody);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
@@ -513,6 +503,21 @@ public class ClassDescriptorResolver {
return propertyDescriptor;
}
/*package*/ static boolean hasBody(JetProperty property) {
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
if (getter != null && getter.getBodyExpression() != null) {
hasBody = true;
}
JetPropertyAccessor setter = property.getSetter();
if (!hasBody && setter != null && setter.getBodyExpression() != null) {
hasBody = true;
}
}
return hasBody;
}
@NotNull
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, boolean allowDeferred) {
// TODO : receiver?
@@ -137,6 +137,29 @@ public class DeclarationsChecker {
checkPropertyAbstractness(property, propertyDescriptor, classDescriptor);
checkPropertyInitializer(property, propertyDescriptor, classDescriptor);
checkAccessors(property, propertyDescriptor);
checkDeclaredTypeInPublicMember(property, propertyDescriptor);
}
private void checkDeclaredTypeInPublicMember(JetNamedDeclaration member, CallableMemberDescriptor memberDescriptor) {
PsiElement nameIdentifier = member.getNameIdentifier();
boolean hasDeferredType;
if (member instanceof JetProperty) {
hasDeferredType = ((JetProperty) member).getPropertyTypeRef() == null && ClassDescriptorResolver.hasBody((JetProperty) member);
}
else {
assert member instanceof JetFunction;
JetFunction function = (JetFunction) member;
hasDeferredType = function.getReturnTypeRef() == null && function.getBodyExpression() != null && !function.hasBlockBody();
}
if ((memberDescriptor.getVisibility() == Visibility.PUBLIC || memberDescriptor.getVisibility() == Visibility.PROTECTED) &&
hasDeferredType && nameIdentifier != null) {
JetType returnType = memberDescriptor.getReturnType();
if (returnType instanceof DeferredType) {
returnType = ((DeferredType) returnType).getActualType();
}
context.getTrace().report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member, nameIdentifier, returnType));
}
}
private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {
@@ -232,6 +255,7 @@ public class DeclarationsChecker {
JetModifierList modifierList = function.getModifierList();
ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;
boolean hasAbstractModifier = abstractNode != null;
checkDeclaredTypeInPublicMember(function, functionDescriptor);
if (containingDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;