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;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author abreslav
*/
public interface CallableMemberDescriptor extends CallableDescriptor, MemberDescriptor {
@NotNull
@Override
Set<? extends CallableMemberDescriptor> getOverriddenDescriptors();
}
@@ -8,7 +8,7 @@ import java.util.Set;
/**
* @author abreslav
*/
public interface FunctionDescriptor extends CallableDescriptor, MemberDescriptor {
public interface FunctionDescriptor extends CallableMemberDescriptor {
@Override
@NotNull
DeclarationDescriptor getContainingDeclaration();
@@ -20,7 +20,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
/**
* @author abreslav
*/
public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements FunctionDescriptor, CallableMemberDescriptor {
public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements FunctionDescriptor {
private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
@@ -166,7 +166,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
@NotNull
@Override
public Set<? extends CallableDescriptor> getOverriddenDescriptors() {
public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
return overriddenProperties;
}
}
@@ -1,6 +1,5 @@
package org.jetbrains.jet.lang.diagnostics;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
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 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");
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<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
@@ -121,7 +120,7 @@ public interface Errors {
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");
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();
}
};
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
protected String makeMessageForA(@NotNull FunctionDescriptor functionDescriptor) {
protected String makeMessageForA(@NotNull CallableMemberDescriptor functionDescriptor) {
return functionDescriptor.getName();
}
@@ -128,7 +128,7 @@ public class DeclarationResolver {
}
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (!klass.hasPrimaryConstructor()) return;
if (!klass.hasPrimaryConstructor() && classDescriptor.getKind() != ClassKind.OBJECT) return;
if (classDescriptor.getKind() == ClassKind.TRAIT) {
// 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) {
// Everything from supertypes
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) {
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
@@ -107,8 +108,10 @@ public class OverrideResolver {
}
}
// Only those actually inherited
Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions);
// Group members with "the same" signature
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap();
JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker();
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();
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
// System.out.println(key);
// println(mutuallyOverridable);
int implementationCount = 0;
for (CallableMemberDescriptor member : mutuallyOverridable) {
if (member.getModality() != Modality.ABSTRACT) {
@@ -142,22 +142,23 @@ public class OverrideResolver {
mustBeOverridden.addAll(mutuallyOverridable);
}
}
// Members actually present (declared) in the class
Set<CallableDescriptor> actuallyOverridden = Sets.newHashSet();
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
actuallyOverridden.addAll(declaredFunction.getOverriddenDescriptors());
}
for (PropertyDescriptor declaredProperty : classDescriptor.getProperties()) {
actuallyOverridden.addAll(declaredProperty.getOverriddenDescriptors());
}
// Those to be overridden that are actually not
mustBeOverridden.removeAll(actuallyOverridden);
System.out.println(classDescriptor);
println(mustBeOverridden);
System.out.println("Actually overridden:");
println(actuallyOverridden);
// System.out.println(classDescriptor);
// println(mustBeOverridden);
// System.out.println("Actually overridden:");
// println(actuallyOverridden);
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
checkOverrideForFunction(declaredFunction);
@@ -208,34 +209,40 @@ public class OverrideResolver {
}
private void checkOverrideForFunction(FunctionDescriptor declaredFunction) {
JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
assert function != null;
JetModifierList modifierList = function.getModifierList();
private void checkOverrideForFunction(CallableMemberDescriptor declared) {
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
assert member != null;
JetModifierList modifierList = member.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : 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 (hasOverrideModifier && !overridden.getModality().isOpen() && !foundError) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden");
context.getTrace().report(OVERRIDING_FINAL_FUNCTION.on(overrideNode, overridden, overridden.getContainingDeclaration()));
foundError = true;
if (hasOverrideModifier) {
if (!overridden.getModality().isOpen() && !error) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden");
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) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing");
context.getTrace().report(NOTHING_TO_OVERRIDE.on(function, overrideNode, declaredFunction));
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declared.getName() + " overrides nothing");
context.getTrace().report(NOTHING_TO_OVERRIDE.on(member, overrideNode, declared));
}
PsiElement nameIdentifier = function.getNameIdentifier();
if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
FunctionDescriptor overriddenFunction = declaredFunction.getOverriddenDescriptors().iterator().next();
PsiElement nameIdentifier = member.getNameIdentifier();
if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
CallableMemberDescriptor overridden = declared.getOverriddenDescriptors().iterator().next();
// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(),
// "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenFunction.getName() + "' in class " +
// overriddenFunction.getContainingDeclaration().getName() + " and needs 'override' modifier");
context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(function, nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration()));
// "Method '" + declared.getName() + "' overrides method '" + overridden.getName() + "' in class " +
// overridden.getContainingDeclaration().getName() + " and needs 'override' modifier");
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> subTypeParameters = subDescriptor.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
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()));
axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
}
@@ -132,13 +128,29 @@ public class OverridingUtil {
// 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
// TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
// JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
// assert substitutedSuperReturnType != null;
// if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
// return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType());
// }
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType());
}
return OverrideCompatibilityInfo.success();
}
@@ -13,7 +13,6 @@ import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection;
import java.util.Set;
/**
* @author svtk
@@ -71,7 +70,7 @@ public class QuickFixes {
add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory);
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());
@@ -27,12 +27,12 @@ namespace normal {
}
class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass4<!> : MyTrait, MyAbstractClass {
fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {}
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() {}
<!NOTHING_TO_OVERRIDE!>override<!> fun other() {}
}
class MyChildClass1 : MyClass {
fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {}
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() {}
override fun bar() {}
}
}
@@ -54,7 +54,7 @@ namespace generics {
class MyChildClass : MyGenericClass<Int> {}
class MyChildClass1<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
}