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);
|
||||
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, 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);
|
||||
|
||||
@@ -13,15 +13,18 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.DeferredType;
|
||||
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.JetToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
@@ -57,7 +60,7 @@ public class DeclarationsChecker {
|
||||
for (Map.Entry<JetNamedFunction, NamedFunctionDescriptor> entry : functions.entrySet()) {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
NamedFunctionDescriptor functionDescriptor = entry.getValue();
|
||||
|
||||
|
||||
if (!context.completeAnalysisNeeded(function)) continue;
|
||||
checkFunction(function, functionDescriptor);
|
||||
checkModifiers(function.getModifierList());
|
||||
@@ -67,7 +70,7 @@ public class DeclarationsChecker {
|
||||
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
|
||||
JetProperty property = entry.getKey();
|
||||
PropertyDescriptor propertyDescriptor = entry.getValue();
|
||||
|
||||
|
||||
if (!context.completeAnalysisNeeded(property)) continue;
|
||||
checkProperty(property, propertyDescriptor);
|
||||
checkModifiers(property.getModifierList());
|
||||
@@ -78,6 +81,7 @@ public class DeclarationsChecker {
|
||||
private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
||||
checkOpenMembers(aClass, classDescriptor);
|
||||
checkTraitModifiers(aClass);
|
||||
checkEnum(aClass, classDescriptor);
|
||||
}
|
||||
|
||||
private void checkTraitModifiers(JetClass aClass) {
|
||||
@@ -95,23 +99,23 @@ public class DeclarationsChecker {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void checkObject(JetObjectDeclaration objectDeclaration, MutableClassDescriptor classDescriptor) {
|
||||
checkIllegalInThisContextModifiers(objectDeclaration.getModifierList(), Sets.newHashSet(JetTokens.ABSTRACT_KEYWORD, JetTokens.OPEN_KEYWORD, JetTokens.OVERRIDE_KEYWORD));
|
||||
}
|
||||
|
||||
private void checkOpenMembers(JetClass aClass, MutableClassDescriptor classDescriptor) {
|
||||
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) {
|
||||
|
||||
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor);
|
||||
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
||||
JetModifierList modifierList = member.getModifierList();
|
||||
assert modifierList != null;
|
||||
ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD);
|
||||
context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass));
|
||||
}
|
||||
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) {
|
||||
|
||||
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, memberDescriptor);
|
||||
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
||||
JetModifierList modifierList = member.getModifierList();
|
||||
assert modifierList != null;
|
||||
ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD);
|
||||
context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
@@ -256,7 +260,7 @@ public class DeclarationsChecker {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, nameIdentifier, functionDescriptor));
|
||||
@@ -344,7 +348,7 @@ public class DeclarationsChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public static Map<JetKeywordToken, ASTNode> getNodesCorrespondingToModifiers(@NotNull JetModifierList modifierList, Collection<JetKeywordToken> possibleModifiers) {
|
||||
Map<JetKeywordToken, ASTNode> nodes = Maps.newHashMap();
|
||||
@@ -355,4 +359,34 @@ public class DeclarationsChecker {
|
||||
}
|
||||
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