Constructors in

This commit is contained in:
Andrey Breslav
2011-09-23 19:36:37 +04:00
parent ec91f309c3
commit 95af2868f0
10 changed files with 78 additions and 53 deletions
@@ -1,7 +1,14 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public interface CallableMemberDescriptor extends CallableDescriptor, MemberDescriptor { public interface CallableMemberDescriptor extends CallableDescriptor, MemberDescriptor {
@NotNull
@Override
Set<? extends CallableMemberDescriptor> getOverriddenDescriptors();
} }
@@ -8,7 +8,7 @@ import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public interface FunctionDescriptor extends CallableDescriptor, MemberDescriptor { public interface FunctionDescriptor extends CallableMemberDescriptor {
@Override @Override
@NotNull @NotNull
DeclarationDescriptor getContainingDeclaration(); DeclarationDescriptor getContainingDeclaration();
@@ -20,7 +20,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
/** /**
* @author abreslav * @author abreslav
*/ */
public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements FunctionDescriptor, CallableMemberDescriptor { public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements FunctionDescriptor {
private List<TypeParameterDescriptor> typeParameters; private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters; private List<ValueParameterDescriptor> unsubstitutedValueParameters;
@@ -166,7 +166,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
@NotNull @NotNull
@Override @Override
public Set<? extends CallableDescriptor> getOverriddenDescriptors() { public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
return overriddenProperties; return overriddenProperties;
} }
} }
@@ -1,6 +1,5 @@
package org.jetbrains.jet.lang.diagnostics; package org.jetbrains.jet.lang.diagnostics;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
@@ -107,7 +106,7 @@ public interface Errors {
SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors"); SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors");
SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required"); SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required");
SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed"); SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed");
PsiElementOnlyDiagnosticFactory1<JetFunction, FunctionDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} overrides nothing"); PsiElementOnlyDiagnosticFactory1<JetModifierListOwner, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing");
ParameterizedDiagnosticFactory1<PropertyDescriptor> PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = ParameterizedDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field"); ParameterizedDiagnosticFactory1<PropertyDescriptor> PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = ParameterizedDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field");
ParameterizedDiagnosticFactory1<JetClassOrObject> PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1<JetClassOrObject>(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") { ParameterizedDiagnosticFactory1<JetClassOrObject> PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1<JetClassOrObject>(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") {
@Override @Override
@@ -121,7 +120,7 @@ public interface Errors {
return e.getClass().getSimpleName() + ": " + e.getMessage(); return e.getClass().getSimpleName() + ": " + e.getMessage();
} }
}; };
PsiElementOnlyDiagnosticFactory3<JetFunction, FunctionDescriptor, FunctionDescriptor, DeclarationDescriptor> VIRTUAL_METHOD_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "Function ''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier"); PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier");
SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code");
ParameterizedDiagnosticFactory1<String> UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because ''{0}'' never terminates normally"); ParameterizedDiagnosticFactory1<String> UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because ''{0}'' never terminates normally");
@@ -274,9 +273,10 @@ public interface Errors {
return nameExpression.getReferencedName(); return nameExpression.getReferencedName();
} }
}; };
ParameterizedDiagnosticFactory2<FunctionDescriptor, DeclarationDescriptor> OVERRIDING_FINAL_FUNCTION = new ParameterizedDiagnosticFactory2<FunctionDescriptor, DeclarationDescriptor>(ERROR, "Method {0} in {1} is final and cannot be overridden") { ParameterizedDiagnosticFactory2<CallableMemberDescriptor, DeclarationDescriptor> OVERRIDING_FINAL_MEMBER = new ParameterizedDiagnosticFactory2<CallableMemberDescriptor, DeclarationDescriptor>(ERROR, "{0} in {1} is final and cannot be overridden") {
@Override @Override
protected String makeMessageForA(@NotNull FunctionDescriptor functionDescriptor) { protected String makeMessageForA(@NotNull CallableMemberDescriptor functionDescriptor) {
return functionDescriptor.getName(); return functionDescriptor.getName();
} }
@@ -128,7 +128,7 @@ public class DeclarationResolver {
} }
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (!klass.hasPrimaryConstructor()) return; if (!klass.hasPrimaryConstructor() && classDescriptor.getKind() != ClassKind.OBJECT) return;
if (classDescriptor.getKind() == ClassKind.TRAIT) { if (classDescriptor.getKind() == ClassKind.TRAIT) {
// context.getTrace().getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor"); // context.getTrace().getErrorHandler().genericError(klass.getPrimaryConstructorParameterList().getNode(), "A trait may not have a constructor");
@@ -97,6 +97,7 @@ public class OverrideResolver {
} }
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
// Everything from supertypes
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet(); Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) { for (JetType supertype : classDescriptor.getSupertypes()) {
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) { for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
@@ -107,8 +108,10 @@ public class OverrideResolver {
} }
} }
// Only those actually inherited
Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions); Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions);
// Group members with "the same" signature
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap(); Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap();
JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker(); JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker();
for (CallableMemberDescriptor one : filteredMembers) { for (CallableMemberDescriptor one : filteredMembers) {
@@ -123,14 +126,11 @@ public class OverrideResolver {
} }
} }
// More than one implementation or no implementations at all
Set<CallableMemberDescriptor> mustBeOverridden = Sets.newLinkedHashSet(); Set<CallableMemberDescriptor> mustBeOverridden = Sets.newLinkedHashSet();
for (CallableMemberDescriptor key : factoredMembers.keySet()) { for (CallableMemberDescriptor key : factoredMembers.keySet()) {
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key); Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
// System.out.println(key);
// println(mutuallyOverridable);
int implementationCount = 0; int implementationCount = 0;
for (CallableMemberDescriptor member : mutuallyOverridable) { for (CallableMemberDescriptor member : mutuallyOverridable) {
if (member.getModality() != Modality.ABSTRACT) { if (member.getModality() != Modality.ABSTRACT) {
@@ -142,22 +142,23 @@ public class OverrideResolver {
mustBeOverridden.addAll(mutuallyOverridable); mustBeOverridden.addAll(mutuallyOverridable);
} }
} }
// Members actually present (declared) in the class
Set<CallableDescriptor> actuallyOverridden = Sets.newHashSet(); Set<CallableDescriptor> actuallyOverridden = Sets.newHashSet();
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
actuallyOverridden.addAll(declaredFunction.getOverriddenDescriptors()); actuallyOverridden.addAll(declaredFunction.getOverriddenDescriptors());
} }
for (PropertyDescriptor declaredProperty : classDescriptor.getProperties()) { for (PropertyDescriptor declaredProperty : classDescriptor.getProperties()) {
actuallyOverridden.addAll(declaredProperty.getOverriddenDescriptors()); actuallyOverridden.addAll(declaredProperty.getOverriddenDescriptors());
} }
// Those to be overridden that are actually not
mustBeOverridden.removeAll(actuallyOverridden); mustBeOverridden.removeAll(actuallyOverridden);
System.out.println(classDescriptor); // System.out.println(classDescriptor);
println(mustBeOverridden); // println(mustBeOverridden);
System.out.println("Actually overridden:"); // System.out.println("Actually overridden:");
println(actuallyOverridden); // println(actuallyOverridden);
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
checkOverrideForFunction(declaredFunction); checkOverrideForFunction(declaredFunction);
@@ -208,34 +209,40 @@ public class OverrideResolver {
} }
private void checkOverrideForFunction(FunctionDescriptor declaredFunction) { private void checkOverrideForFunction(CallableMemberDescriptor declared) {
JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction); JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
assert function != null; assert member != null;
JetModifierList modifierList = function.getModifierList(); JetModifierList modifierList = member.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null; ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
boolean hasOverrideModifier = overrideNode != null; boolean hasOverrideModifier = overrideNode != null;
boolean foundError = false; boolean error = false;
for (FunctionDescriptor overridden : declaredFunction.getOverriddenDescriptors()) { for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
if (overridden != null) { if (overridden != null) {
if (hasOverrideModifier && !overridden.getModality().isOpen() && !foundError) { if (hasOverrideModifier) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden"); if (!overridden.getModality().isOpen() && !error) {
context.getTrace().report(OVERRIDING_FINAL_FUNCTION.on(overrideNode, overridden, overridden.getContainingDeclaration())); // context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden");
foundError = true; context.getTrace().report(OVERRIDING_FINAL_MEMBER.on(overrideNode, overridden, overridden.getContainingDeclaration()));
error = true;
}
if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared).isSuccess()) {
}
} }
} }
} }
if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) { if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing"); // context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declared.getName() + " overrides nothing");
context.getTrace().report(NOTHING_TO_OVERRIDE.on(function, overrideNode, declaredFunction)); context.getTrace().report(NOTHING_TO_OVERRIDE.on(member, overrideNode, declared));
} }
PsiElement nameIdentifier = function.getNameIdentifier(); PsiElement nameIdentifier = member.getNameIdentifier();
if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
FunctionDescriptor overriddenFunction = declaredFunction.getOverriddenDescriptors().iterator().next(); CallableMemberDescriptor overridden = declared.getOverriddenDescriptors().iterator().next();
// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), // context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(),
// "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenFunction.getName() + "' in class " + // "Method '" + declared.getName() + "' overrides method '" + overridden.getName() + "' in class " +
// overriddenFunction.getContainingDeclaration().getName() + " and needs 'override' modifier"); // overridden.getContainingDeclaration().getName() + " and needs 'override' modifier");
context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(function, nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration())); context.getTrace().report(VIRTUAL_MEMBER_HIDDEN.on(member, nameIdentifier, declared, overridden, overridden.getContainingDeclaration()));
} }
} }
} }
@@ -99,14 +99,10 @@ public class OverridingUtil {
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters(); List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters(); List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create(); BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor()); axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
} }
@@ -132,13 +128,29 @@ public class OverridingUtil {
// TODO : Default values, varargs etc // TODO : Default values, varargs etc
return OverrideCompatibilityInfo.success();
}
@NotNull
public static OverrideCompatibilityInfo isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
}
// This code compares return types, but they are not a part of the signature, so this code does not belong here // This code compares return types, but they are not a part of the signature, so this code does not belong here
// TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext); TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
// JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE); JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
// assert substitutedSuperReturnType != null; assert substitutedSuperReturnType != null;
// if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) { if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
// return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType()); return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType());
// } }
return OverrideCompatibilityInfo.success(); return OverrideCompatibilityInfo.success();
} }
@@ -13,7 +13,6 @@ import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection; import java.util.Collection;
import java.util.Set;
/** /**
* @author svtk * @author svtk
@@ -71,7 +70,7 @@ public class QuickFixes {
add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory); add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD)); add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD));
add(Errors.VIRTUAL_METHOD_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD)); add(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD));
add(Errors.VAL_WITH_SETTER, ChangeVariableMutabilityFix.createFactory()); add(Errors.VAL_WITH_SETTER, ChangeVariableMutabilityFix.createFactory());
@@ -27,12 +27,12 @@ namespace normal {
} }
class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass4<!> : MyTrait, MyAbstractClass { class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass4<!> : MyTrait, MyAbstractClass {
fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {} fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() {}
<!NOTHING_TO_OVERRIDE!>override<!> fun other() {} <!NOTHING_TO_OVERRIDE!>override<!> fun other() {}
} }
class MyChildClass1 : MyClass { class MyChildClass1 : MyClass {
fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {} fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() {}
override fun bar() {} override fun bar() {}
} }
} }
@@ -54,7 +54,7 @@ namespace generics {
class MyChildClass : MyGenericClass<Int> {} class MyChildClass : MyGenericClass<Int> {}
class MyChildClass1<T> : MyGenericClass<T> {} class MyChildClass1<T> : MyGenericClass<T> {}
class MyChildClass2<T> : MyGenericClass<T> { class MyChildClass2<T> : MyGenericClass<T> {
fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>(t: T) = t fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>(t: T) = t
override fun bar(t: T) = t override fun bar(t: T) = t
} }