Constructors in
This commit is contained in:
@@ -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();
|
||||
|
||||
+1
-1
@@ -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());
|
||||
|
||||
|
||||
+3
-3
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user