KT-1193 Check enum entry supertype
This commit is contained in:
@@ -151,6 +151,9 @@ public interface Errors {
|
|||||||
PsiElementOnlyDiagnosticFactory1<JetModifierList, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT);
|
PsiElementOnlyDiagnosticFactory1<JetModifierList, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT);
|
||||||
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT);
|
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT);
|
||||||
|
|
||||||
|
ParameterizedDiagnosticFactory1<ClassDescriptor> ENUM_ENTRY_SHOULD_BE_INITIALIZED = ParameterizedDiagnosticFactory1.create(ERROR, "Missing delegation specifier ''{0}''", NAME);
|
||||||
|
ParameterizedDiagnosticFactory1<ClassDescriptor> ENUM_ENTRY_ILLEGAL_TYPE = ParameterizedDiagnosticFactory1.create(ERROR, "The type constructor of enum entry should be ''{0}''", NAME);
|
||||||
|
|
||||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
|
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
|
||||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME);
|
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME);
|
||||||
UnusedElementDiagnosticFactory<JetProperty, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME);
|
UnusedElementDiagnosticFactory<JetProperty, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME);
|
||||||
|
|||||||
@@ -13,15 +13,18 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
|
|||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.types.DeferredType;
|
import org.jetbrains.jet.lang.types.DeferredType;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
@@ -78,6 +81,7 @@ public class DeclarationsChecker {
|
|||||||
private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
||||||
checkOpenMembers(aClass, classDescriptor);
|
checkOpenMembers(aClass, classDescriptor);
|
||||||
checkTraitModifiers(aClass);
|
checkTraitModifiers(aClass);
|
||||||
|
checkEnum(aClass, classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTraitModifiers(JetClass aClass) {
|
private void checkTraitModifiers(JetClass aClass) {
|
||||||
@@ -101,17 +105,17 @@ public class DeclarationsChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
||||||
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) {
|
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) {
|
||||||
|
|
||||||
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor);
|
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor);
|
||||||
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
||||||
JetModifierList modifierList = member.getModifierList();
|
JetModifierList modifierList = member.getModifierList();
|
||||||
assert modifierList != null;
|
assert modifierList != null;
|
||||||
ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD);
|
ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD);
|
||||||
context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass));
|
context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
|
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
@@ -256,7 +260,7 @@ public class DeclarationsChecker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hasAbstractModifier) {
|
if (hasAbstractModifier) {
|
||||||
context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, abstractNode, functionDescriptor));
|
context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, abstractNode, functionDescriptor));
|
||||||
}
|
}
|
||||||
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) {
|
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) {
|
||||||
context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, nameIdentifier, functionDescriptor));
|
context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, nameIdentifier, functionDescriptor));
|
||||||
@@ -355,4 +359,34 @@ public class DeclarationsChecker {
|
|||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkEnum(JetClass aClass, ClassDescriptor classDescriptor) {
|
||||||
|
if (classDescriptor.getKind() != ClassKind.ENUM_ENTRY) return;
|
||||||
|
|
||||||
|
DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration().getContainingDeclaration();
|
||||||
|
assert declaration instanceof ClassDescriptor;
|
||||||
|
ClassDescriptor enumClass = (ClassDescriptor) declaration;
|
||||||
|
assert enumClass.getKind() == ClassKind.ENUM_CLASS;
|
||||||
|
|
||||||
|
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
||||||
|
ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor();
|
||||||
|
assert constructor != null;
|
||||||
|
if (!constructor.getValueParameters().isEmpty() && delegationSpecifiers.isEmpty()) {
|
||||||
|
PsiElement nameIdentifier = aClass.getNameIdentifier();
|
||||||
|
context.getTrace().report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(nameIdentifier != null ? nameIdentifier : aClass, enumClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
|
||||||
|
JetTypeReference typeReference = delegationSpecifier.getTypeReference();
|
||||||
|
if (typeReference != null) {
|
||||||
|
JetType type = context.getTrace().getBindingContext().get(TYPE, typeReference);
|
||||||
|
if (type != null) {
|
||||||
|
JetType enumType = enumClass.getDefaultType();
|
||||||
|
if (!type.getConstructor().equals(enumType.getConstructor())) {
|
||||||
|
context.getTrace().report(ENUM_ENTRY_ILLEGAL_TYPE.on(typeReference, enumClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//KT-1193 Check enum entry supertype
|
||||||
|
|
||||||
|
package kt1193
|
||||||
|
|
||||||
|
open enum class MyEnum(val i: Int) {
|
||||||
|
A : MyEnum(12)
|
||||||
|
<!ENUM_ENTRY_SHOULD_BE_INITIALIZED!>B<!> //no error
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class MyChildEnum(i: Int, val s: String) : MyEnum(i) {
|
||||||
|
C : <!ENUM_ENTRY_ILLEGAL_TYPE!>MyEnum<!>(3)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user