diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index aae2aa17435..1ac7c0efcf6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -144,7 +144,8 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { @NotNull @Override public ClassDescriptor substitute(TypeSubstitutor substitutor) { - throw new UnsupportedOperationException(); // TODO + if (substitutor.isEmpty()) return this; + return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.create(substitutor.getSubstitution(), getSubstitutor().getSubstitution())); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 2870b819424..39014c9d2fc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -23,8 +23,9 @@ import java.util.*; public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor, NamespaceLike { private ConstructorDescriptor primaryConstructor; private final Set constructors = Sets.newLinkedHashSet(); - private final Set functions = Sets.newHashSet(); + private final Set callableMembers = Sets.newHashSet(); private final Set properties = Sets.newHashSet(); + private final Set functions = Sets.newHashSet(); private List typeParameters = Lists.newArrayList(); private Collection supertypes = Lists.newArrayList(); @@ -95,18 +96,15 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme @Override public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { properties.add(propertyDescriptor); + callableMembers.add(propertyDescriptor); scopeForMemberLookup.addVariableDescriptor(propertyDescriptor); scopeForMemberResolution.addVariableDescriptor(propertyDescriptor); } - @NotNull - public Set getProperties() { - return properties; - } - @Override public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { functions.add(functionDescriptor); + callableMembers.add(functionDescriptor); scopeForMemberLookup.addFunctionDescriptor(functionDescriptor); scopeForMemberResolution.addFunctionDescriptor(functionDescriptor); } @@ -116,6 +114,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme return functions; } + @NotNull + public Set getProperties() { + return properties; + } + + @NotNull + public Set getCallableMembers() { + return callableMembers; + } + @Override public NamespaceDescriptorImpl getNamespace(String name) { throw new UnsupportedOperationException("Classes do not define namespaces"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java index 574117501a8..3657beb122d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java @@ -5,12 +5,18 @@ import java.text.MessageFormat; /** * @author abreslav */ -public class DiagnosticFactoryWithMessageFormat extends DiagnosticFactoryWithSeverity { +public abstract class DiagnosticFactoryWithMessageFormat extends DiagnosticFactoryWithSeverity { protected final MessageFormat messageFormat; + protected final Renderer renderer; public DiagnosticFactoryWithMessageFormat(Severity severity, String message) { + this(severity, message, Renderer.TO_STRING); + } + + public DiagnosticFactoryWithMessageFormat(Severity severity, String message, Renderer renderer) { super(severity); this.messageFormat = new MessageFormat(message); + this.renderer = renderer; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java index 5d19f299ae8..4243d9ed02c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java @@ -9,6 +9,11 @@ import org.jetbrains.annotations.NotNull; * @author svtk */ public abstract class DiagnosticFactoryWithPsiElement1 extends DiagnosticFactoryWithMessageFormat { + + protected DiagnosticFactoryWithPsiElement1(Severity severity, String message, Renderer renderer) { + super(severity, message, renderer); + } + protected DiagnosticFactoryWithPsiElement1(Severity severity, String message) { super(severity, message); } @@ -18,7 +23,7 @@ public abstract class DiagnosticFactoryWithPsiElement1 } protected String makeMessageFor(A argument) { - return argument.toString(); + return renderer.render(argument); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java index dc4ea2218f2..3453f4c0be0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java @@ -9,8 +9,12 @@ import org.jetbrains.annotations.NotNull; * @author abreslav */ public abstract class DiagnosticFactoryWithPsiElement2 extends DiagnosticFactoryWithMessageFormat { - - public DiagnosticFactoryWithPsiElement2(Severity severity, String message) { + + protected DiagnosticFactoryWithPsiElement2(Severity severity, String message, Renderer renderer) { + super(severity, message, renderer); + } + + protected DiagnosticFactoryWithPsiElement2(Severity severity, String message) { super(severity, message); } @@ -19,11 +23,11 @@ public abstract class DiagnosticFactoryWithPsiElement2 extends DiagnosticFactoryWithMessageFormat { - protected DiagnosticFactoryWithPsiElement3(Severity severity, String messageStub) { - super(severity, messageStub); +public abstract class DiagnosticFactoryWithPsiElement3 extends DiagnosticFactoryWithMessageFormat { + protected DiagnosticFactoryWithPsiElement3(Severity severity, String messageStub, Renderer renderer) { + super(severity, messageStub, renderer); + } + + protected DiagnosticFactoryWithPsiElement3(Severity severity, String message) { + super(severity, message); } protected String makeMessage(@NotNull A a, @NotNull B b, @NotNull C c) { @@ -18,15 +22,15 @@ public class DiagnosticFactoryWithPsiElement3 ext } protected String makeMessageForA(@NotNull A a) { - return a.toString(); + return renderer.render(a); } protected String makeMessageForB(@NotNull B b) { - return b.toString(); + return renderer.render(b); } protected String makeMessageForC(@NotNull C c) { - return c.toString(); + return renderer.render(c); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java index 5ff19dea923..872e368fbab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.diagnostics; /** * @author abreslav */ -public class DiagnosticFactoryWithSeverity extends AbstractDiagnosticFactory { +public abstract class DiagnosticFactoryWithSeverity extends AbstractDiagnosticFactory { protected final Severity severity; public DiagnosticFactoryWithSeverity(Severity severity) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index addf843e41e..af17069d46f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -4,6 +4,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.JetType; @@ -23,6 +24,24 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING; */ public interface Errors { + Renderer NAME = new Renderer() { + @NotNull + @Override + public String render(@Nullable Object object) { + if (object == null) return "null"; + if (object instanceof Named) { + return ((Named) object).getName(); + } + return object.toString(); + } + }; + + ParameterizedDiagnosticFactory1 EXCEPTION_WHILE_ANALYZING = new ParameterizedDiagnosticFactory1(ERROR, "{0}") { + @Override + protected String makeMessageFor(@NotNull Throwable e) { + return e.getClass().getSimpleName() + ": " + e.getMessage(); + } + }; UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.INSTANCE; RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE; PsiElementOnlyDiagnosticFactory2 TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); @@ -40,6 +59,7 @@ public interface Errors { return sb.toString(); } }; + PsiElementOnlyDiagnosticFactory2 REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2(Severity.WARNING, "Modifier {0} is redundant because {1} is present") { @NotNull @Override @@ -47,26 +67,25 @@ public interface Errors { return new DiagnosticWithAdditionalInfo(this, severity, makeMessage(redundantModifier, presentModifier), element, node.getTextRange(), redundantModifier); } }; - SimpleDiagnosticFactory SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES = SimpleDiagnosticFactory.create(ERROR, "Safe calls are not allowed on namespaces"); SimpleDiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = SimpleDiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem"); // TODO: message SimpleDiagnosticFactory RETURN_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "'return' is not allowed here"); SimpleDiagnosticFactory PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed for immediate arguments of a supertype"); SimpleDiagnosticFactory LABEL_NAME_CLASH = SimpleDiagnosticFactory.create(WARNING, "There is more than one label with such a name in this scope"); SimpleDiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = SimpleDiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found"); + SimpleDiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = SimpleDiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); SimpleDiagnosticFactory NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "This property does not have a backing field"); - SimpleDiagnosticFactory MIXING_NAMED_AND_POSITIONED_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Mixing named and positioned arguments in not allowed"); SimpleDiagnosticFactory ARGUMENT_PASSED_TWICE = SimpleDiagnosticFactory.create(ERROR, "An argument is already passed for this parameter"); SimpleDiagnosticFactory NAMED_PARAMETER_NOT_FOUND = SimpleDiagnosticFactory.create(ERROR, "Cannot find a parameter with this name"); SimpleDiagnosticFactory VARARG_OUTSIDE_PARENTHESES = SimpleDiagnosticFactory.create(ERROR, "Passing value as a vararg is only allowed inside a parenthesized argument list"); + SimpleDiagnosticFactory MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Only one function literal is allowed outside a parenthesized argument list"); - SimpleDiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, "This property must either have a type annotation or be initialized"); - SimpleDiagnosticFactory FUNCTION_WITH_NO_TYPE_NO_BODY = SimpleDiagnosticFactory.create(ERROR, "This function must either declare a return type or have a body element"); + SimpleDiagnosticFactory FUNCTION_WITH_NO_TYPE_NO_BODY = SimpleDiagnosticFactory.create(ERROR, "This function must either declare a return type or have a body element"); SimplePsiElementOnlyDiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property cannot be declared abstract"); SimplePsiElementOnlyDiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A property may be abstract only when defined in a class or trait"); //TODO pass String instead of JetType or ensure JetType's value is computed @@ -96,17 +115,17 @@ public interface Errors { PsiElementOnlyDiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract"); PsiElementOnlyDiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract"); SimplePsiElementOnlyDiagnosticFactory NON_MEMBER_ABSTRACT_ACCESSOR = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property is not a class or trait member and thus cannot have abstract accessors"); // TODO : Better message + PsiElementOnlyDiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body"); SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning - SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here"); SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = SimpleDiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor"); SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST = SimpleDiagnosticFactory.create(ERROR, "Secondary constructors must have an initializer list"); 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 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing"); + PsiElementOnlyDiagnosticFactory1 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT); ParameterizedDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = ParameterizedDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field"); ParameterizedDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") { @Override @@ -114,13 +133,7 @@ public interface Errors { return JetPsiUtil.safeName(argument.getName()); } }; - ParameterizedDiagnosticFactory1 EXCEPTION_WHILE_ANALYZING = new ParameterizedDiagnosticFactory1(ERROR, "{0}") { - @Override - protected String makeMessageFor(@NotNull Throwable e) { - return e.getClass().getSimpleName() + ": " + e.getMessage(); - } - }; - PsiElementOnlyDiagnosticFactory3 VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier"); + PsiElementOnlyDiagnosticFactory3 VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT); SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); ParameterizedDiagnosticFactory1 UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because ''{0}'' never terminates normally"); @@ -151,13 +164,7 @@ public interface Errors { SimpleDiagnosticFactory CAST_NEVER_SUCCEEDS = SimpleDiagnosticFactory.create(WARNING, "This cast can never succeed"); DiagnosticWithAdditionalInfoFactory1 WRONG_SETTER_PARAMETER_TYPE = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}"); DiagnosticWithAdditionalInfoFactory1 WRONG_GETTER_RETURN_TYPE = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}"); - ParameterizedDiagnosticFactory1 NO_CLASS_OBJECT = new ParameterizedDiagnosticFactory1(ERROR, "Classifier {0} does not have a class object") { - @Override - protected String makeMessageFor(@NotNull ClassifierDescriptor argument) { - return argument.getName(); - } - }; - + ParameterizedDiagnosticFactory1 NO_CLASS_OBJECT = ParameterizedDiagnosticFactory1.create(ERROR, "Classifier {0} does not have a class object", NAME); SimpleDiagnosticFactory NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR, "Generic arguments of the base type must be specified"); SimpleDiagnosticFactory HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property"); @@ -187,12 +194,7 @@ public interface Errors { return argument.getName(); } }; - ParameterizedDiagnosticFactory1 CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS = new ParameterizedDiagnosticFactory1(ERROR, "Class object upper bounds of {0} have empty intersection") { - @Override - protected String makeMessageFor(@NotNull TypeParameterDescriptor argument) { - return argument.getName(); - } - }; + ParameterizedDiagnosticFactory1 CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS = ParameterizedDiagnosticFactory1.create(ERROR, "Class object upper bounds of {0} have empty intersection", NAME); ParameterizedDiagnosticFactory1 TOO_MANY_ARGUMENTS = ParameterizedDiagnosticFactory1.create(ERROR, "Too many arguments for {0}"); ParameterizedDiagnosticFactory1 ERROR_COMPILE_TIME_VALUE = ParameterizedDiagnosticFactory1.create(ERROR, "{0}"); @@ -229,12 +231,7 @@ public interface Errors { return constraintOwner.getName(); } }; - ParameterizedDiagnosticFactory2 AUTOCAST_IMPOSSIBLE = new ParameterizedDiagnosticFactory2(ERROR, "Automatic cast to {0} is impossible, because variable {1} is mutable") { - @Override - protected String makeMessageForB(@NotNull VariableDescriptor variableDescriptor) { - return variableDescriptor.getName(); - } - }; + ParameterizedDiagnosticFactory2 AUTOCAST_IMPOSSIBLE = ParameterizedDiagnosticFactory2.create(ERROR, "Automatic cast to {0} is impossible, because variable {1} is mutable", NAME); ParameterizedDiagnosticFactory2 TYPE_MISMATCH_IN_FOR_LOOP = ParameterizedDiagnosticFactory2.create(ERROR, "The loop iterates over values of type {0} but the parameter is declared to be {1}"); ParameterizedDiagnosticFactory1 TYPE_MISMATCH_IN_CONDITION = ParameterizedDiagnosticFactory1.create(ERROR, "Condition must be of type Boolean, but was of type {0}"); @@ -273,32 +270,73 @@ public interface Errors { return nameExpression.getReferencedName(); } }; - ParameterizedDiagnosticFactory2 OVERRIDING_FINAL_MEMBER = new ParameterizedDiagnosticFactory2(ERROR, "{0} in {1} is final and cannot be overridden") { + ParameterizedDiagnosticFactory2 OVERRIDING_FINAL_MEMBER = ParameterizedDiagnosticFactory2.create(ERROR, "{0} in {1} is final and cannot be overridden", NAME); + ParameterizedDiagnosticFactory2 RETURN_TYPE_MISMATCH_ON_OVERRIDE = new ParameterizedDiagnosticFactory2(ERROR, "Return type of {0} is not a subtype of the return type overridden member {1}") { + @NotNull @Override - protected String makeMessageForA(@NotNull CallableMemberDescriptor functionDescriptor) { - return functionDescriptor.getName(); + public TextRange getTextRange(@NotNull Diagnostic diagnostic) { + PsiElement psiElement = ((DiagnosticWithPsiElement) diagnostic).getPsiElement(); + JetTypeReference returnTypeRef = null; + ASTNode nameNode = null; + if (psiElement instanceof JetNamedFunction) { + JetFunction function = (JetNamedFunction) psiElement; + returnTypeRef = function.getReturnTypeRef(); + nameNode = getNameNode(function); + } + else if (psiElement instanceof JetProperty) { + JetProperty property = (JetProperty) psiElement; + returnTypeRef = property.getPropertyTypeRef(); + nameNode = getNameNode(property); + } + else if (psiElement instanceof JetPropertyAccessor) { + JetPropertyAccessor accessor = (JetPropertyAccessor) psiElement; + returnTypeRef = accessor.getReturnTypeReference(); + nameNode = accessor.getNamePlaceholder().getNode(); + } + if (returnTypeRef != null) return returnTypeRef.getTextRange(); + if (nameNode != null) return nameNode.getTextRange(); + return super.getTextRange(diagnostic); + } + + private ASTNode getNameNode(JetNamedDeclaration function) { + PsiElement nameIdentifier = function.getNameIdentifier(); + return nameIdentifier == null ? null : nameIdentifier.getNode(); } @Override - protected String makeMessageForB(@NotNull DeclarationDescriptor descriptor) { - return descriptor.getName(); + protected String makeMessageForA(@NotNull CallableMemberDescriptor callableMemberDescriptor) { + return DescriptorRenderer.TEXT.render(callableMemberDescriptor); + } + + @Override + protected String makeMessageForB(@NotNull CallableMemberDescriptor callableMemberDescriptor) { + return DescriptorRenderer.TEXT.render(callableMemberDescriptor); } }; - ParameterizedDiagnosticFactory3 ABSTRACT_METHOD_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory3(ERROR, "Class ''{0}'' must be declared abstract or implement abstract method ''{1}'' declared in {2}") { + + + ParameterizedDiagnosticFactory2 ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") { @Override protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { return jetClassOrObject.getName(); } @Override - protected String makeMessageForB(@NotNull FunctionDescriptor functionDescriptor) { - return DescriptorRenderer.TEXT.render(functionDescriptor); + protected String makeMessageForB(@NotNull CallableMemberDescriptor memberDescriptor) { + return DescriptorRenderer.TEXT.render(memberDescriptor); + } + }; + + ParameterizedDiagnosticFactory2 MANY_IMPL_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2(ERROR, "Class ''{0}'' must override {1} because it inherits many implementations of it") { + @Override + protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { + return jetClassOrObject.getName(); } @Override - protected String makeMessageForC(@NotNull DeclarationDescriptor descriptor) { - return descriptor.getName(); + protected String makeMessageForB(@NotNull CallableMemberDescriptor memberDescriptor) { + return DescriptorRenderer.TEXT.render(memberDescriptor); } }; @@ -344,4 +382,5 @@ public interface Errors { private static final Initializer INSTANCE = new Initializer(); private Initializer() {}; } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java index 05a9de0c3df..90729dfdb17 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java @@ -14,8 +14,16 @@ public class ParameterizedDiagnosticFactory1 extends DiagnosticFactoryWithPsi return new ParameterizedDiagnosticFactory1(severity, messageStub); } - protected ParameterizedDiagnosticFactory1(Severity severity, String messageStub) { - super(severity, messageStub); + public static ParameterizedDiagnosticFactory1 create(Severity severity, String messageStub, Renderer renderer) { + return new ParameterizedDiagnosticFactory1(severity, messageStub, renderer); + } + + public ParameterizedDiagnosticFactory1(Severity severity, String message, Renderer renderer) { + super(severity, message, renderer); + } + + public ParameterizedDiagnosticFactory1(Severity severity, String message) { + super(severity, message); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java index eea8433558c..d76bc5b47e1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java @@ -14,6 +14,14 @@ public class ParameterizedDiagnosticFactory2 extends DiagnosticFactoryWith return new ParameterizedDiagnosticFactory2(severity, messageStub); } + public static ParameterizedDiagnosticFactory2 create(Severity severity, String messageStub, Renderer renderer) { + return new ParameterizedDiagnosticFactory2(severity, messageStub, renderer); + } + + public ParameterizedDiagnosticFactory2(Severity severity, String message, Renderer renderer) { + super(severity, message, renderer); + } + public ParameterizedDiagnosticFactory2(Severity severity, String messageStub) { super(severity, messageStub); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java index 77e7e047c75..ad574334bea 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java @@ -14,6 +14,14 @@ public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryW return new ParameterizedDiagnosticFactory3(severity, messageStub); } + public static ParameterizedDiagnosticFactory3 create(Severity severity, String messageStub, Renderer renderer) { + return new ParameterizedDiagnosticFactory3(severity, messageStub, renderer); + } + + public ParameterizedDiagnosticFactory3(Severity severity, String messageStub, Renderer renderer) { + super(severity, messageStub, renderer); + } + protected ParameterizedDiagnosticFactory3(Severity severity, String messageStub) { super(severity, messageStub); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java index 3f5c6baee6b..bd7a89b5af6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java @@ -8,7 +8,15 @@ public class PsiElementOnlyDiagnosticFactory1 extends D public static PsiElementOnlyDiagnosticFactory1 create(Severity severity, String messageStub) { return new PsiElementOnlyDiagnosticFactory1(severity, messageStub); } - + + public static PsiElementOnlyDiagnosticFactory1 create(Severity severity, String messageStub, Renderer renderer) { + return new PsiElementOnlyDiagnosticFactory1(severity, messageStub, renderer); + } + + public PsiElementOnlyDiagnosticFactory1(Severity severity, String message, Renderer renderer) { + super(severity, message, renderer); + } + protected PsiElementOnlyDiagnosticFactory1(Severity severity, String message) { super(severity, message); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java index eb7a0a3753c..a793ea0f3ac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java @@ -5,11 +5,19 @@ import com.intellij.psi.PsiElement; * @author svtk */ public class PsiElementOnlyDiagnosticFactory3 extends DiagnosticFactoryWithPsiElement3 implements PsiElementOnlyDiagnosticFactory { + public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub) { + return new PsiElementOnlyDiagnosticFactory3(severity, messageStub); + } + + public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub, Renderer renderer) { + return new PsiElementOnlyDiagnosticFactory3(severity, messageStub, renderer); + } + protected PsiElementOnlyDiagnosticFactory3(Severity severity, String messageStub) { super(severity, messageStub); } - public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub) { - return new PsiElementOnlyDiagnosticFactory3(severity, messageStub); + public PsiElementOnlyDiagnosticFactory3(Severity severity, String messageStub, Renderer renderer) { + super(severity, messageStub, renderer); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java new file mode 100644 index 00000000000..9439e6a2dfa --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java @@ -0,0 +1,25 @@ +package org.jetbrains.jet.lang.diagnostics; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author abreslav + */ +public interface Renderer { + Renderer TO_STRING = new Renderer() { + @NotNull + @Override + public String render(@Nullable Object object) { + return object == null ? "null" : object.toString(); + } + + @Override + public String toString() { + return "TO_STRING"; + } + }; + + @NotNull + String render(@Nullable Object object); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 1eb716a8cb3..6637d0bedec 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -1483,7 +1483,7 @@ public class JetParsing extends AbstractJetParsing { myBuilder.disableNewlines(); expect(LPAR, "Expecting '(", recoverySet); - if (!at(RPAR)) { + if (!at(RPAR) && !atSet(recoverySet)) { while (true) { if (at(COMMA)) { errorAndAdvance("Expecting a parameter declaration"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java index 328ae7b3e68..0b9154333f2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java @@ -71,6 +71,7 @@ public class JetPropertyAccessor extends JetDeclaration implements JetFunctionOr return findChildByClass(JetTypeReference.class); } + @NotNull public PsiElement getNamePlaceholder() { PsiElement get = findChildByType(JetTokens.GET_KEYWORD); if (get != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index e9c85a789d2..c34fe426683 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -525,7 +525,10 @@ public class ClassDescriptorResolver { final JetExpression initializer = property.getInitializer(); if (initializer == null) { // trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized"); - trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); + PsiElement nameIdentifier = property.getNameIdentifier(); + if (nameIdentifier != null) { + trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(nameIdentifier.getNode())); + } return ErrorUtils.createErrorType("No type, no body"); } else { // TODO : a risk of a memory leak diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java index 985064fd161..7a840513fdb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -139,13 +139,15 @@ public class DeclarationResolver { JetScope memberScope = classDescriptor.getScopeForSupertypeResolution(); ConstructorDescriptor constructorDescriptor = context.getClassDescriptorResolver().resolvePrimaryConstructorDescriptor(memberScope, classDescriptor, klass); for (JetParameter parameter : klass.getPrimaryConstructorParameters()) { - PropertyDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolvePrimaryConstructorParameterToAProperty( - classDescriptor, - memberScope, - parameter - ); - classDescriptor.addPropertyDescriptor(propertyDescriptor); - context.getPrimaryConstructorParameterProperties().add(propertyDescriptor); + if (parameter.getValOrVarNode() != null) { + PropertyDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolvePrimaryConstructorParameterToAProperty( + classDescriptor, + memberScope, + parameter + ); + classDescriptor.addPropertyDescriptor(propertyDescriptor); + context.getPrimaryConstructorParameterProperties().add(propertyDescriptor); + } } if (constructorDescriptor != null) { classDescriptor.setPrimaryConstructor(constructorDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index de1b8e91298..ecbc9cadbab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -68,7 +68,7 @@ public class OverrideResolver { private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) { Set functionGroup = supertype.getMemberScope().getFunctions(declaredFunction.getName()); for (FunctionDescriptor functionDescriptor : functionGroup) { - if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) { + if (OverridingUtil.isOverridableBy(functionDescriptor, declaredFunction).isSuccess()) { return functionDescriptor; } } @@ -81,7 +81,7 @@ public class OverrideResolver { if (property == null) { return null; } - if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), property, declaredProperty).isSuccess()) { + if (OverridingUtil.isOverridableBy(property, declaredProperty).isSuccess()) { return property; } return null; @@ -97,6 +97,13 @@ public class OverrideResolver { } protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { + // Check overrides for internal consistency + for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) { + checkOverride(member); + } + + // Check if everything that must be overridden, actually is + // Everything from supertypes Set inheritedFunctions = Sets.newLinkedHashSet(); for (JetType supertype : classDescriptor.getSupertypes()) { @@ -113,21 +120,21 @@ public class OverrideResolver { // Group members with "the same" signature Multimap factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap(); - JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker(); for (CallableMemberDescriptor one : filteredMembers) { if (factoredMembers.values().contains(one)) continue; for (CallableMemberDescriptor another : filteredMembers) { if (one == another) continue; factoredMembers.put(one, one); - if (OverridingUtil.isOverridableBy(typeChecker, one, another).isSuccess() - || OverridingUtil.isOverridableBy(typeChecker, another, one).isSuccess()) { + if (OverridingUtil.isOverridableBy(one, another).isSuccess() + || OverridingUtil.isOverridableBy(another, one).isSuccess()) { factoredMembers.put(one, another); } } } // More than one implementation or no implementations at all - Set mustBeOverridden = Sets.newLinkedHashSet(); + Set abstractNoImpl = Sets.newLinkedHashSet(); + Set manyImpl = Sets.newLinkedHashSet(); for (CallableMemberDescriptor key : factoredMembers.keySet()) { Collection mutuallyOverridable = factoredMembers.get(key); @@ -138,34 +145,47 @@ public class OverrideResolver { } } - if (implementationCount != 1) { - mustBeOverridden.addAll(mutuallyOverridable); + if (implementationCount == 0) { + abstractNoImpl.addAll(mutuallyOverridable); + } + else if (implementationCount > 1) { + manyImpl.addAll(mutuallyOverridable); } } // Members actually present (declared) in the class Set actuallyOverridden = Sets.newHashSet(); - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - actuallyOverridden.addAll(declaredFunction.getOverriddenDescriptors()); - } - for (PropertyDescriptor declaredProperty : classDescriptor.getProperties()) { - actuallyOverridden.addAll(declaredProperty.getOverriddenDescriptors()); + for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) { + actuallyOverridden.addAll(member.getOverriddenDescriptors()); } // Those to be overridden that are actually not - mustBeOverridden.removeAll(actuallyOverridden); + abstractNoImpl.removeAll(actuallyOverridden); + manyImpl.removeAll(actuallyOverridden); -// System.out.println(classDescriptor); -// println(mustBeOverridden); -// System.out.println("Actually overridden:"); -// println(actuallyOverridden); - - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - checkOverrideForFunction(declaredFunction); + PsiElement nameIdentifier = klass; + if (klass instanceof JetClass) { + nameIdentifier = ((JetClass) klass).getNameIdentifier(); } + else if (klass instanceof JetObjectDeclaration) { + nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); + } + +// for (CallableMemberDescriptor memberDescriptor : manyImpl) { +// context.getTrace().report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); +// break; +// } + + if (classDescriptor.getModality() == Modality.ABSTRACT) { return; } + +// for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) { +// context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); +// break; +// } + Set allOverriddenFunctions = Sets.newHashSet(); Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); for (DeclarationDescriptor descriptor : allDescriptors) { @@ -179,13 +199,6 @@ public class OverrideResolver { } } boolean foundError = false; - PsiElement nameIdentifier = null; - if (klass instanceof JetClass) { - nameIdentifier = ((JetClass) klass).getNameIdentifier(); - } - else if (klass instanceof JetObjectDeclaration) { - nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); - } for (DeclarationDescriptor descriptor : allDescriptors) { if (descriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; @@ -194,7 +207,7 @@ public class OverrideResolver { if (declarationDescriptor != classDescriptor) { // context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + // functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName()); - context.getTrace().report(ABSTRACT_METHOD_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor, declarationDescriptor)); + context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor)); foundError = true; } } @@ -202,32 +215,27 @@ public class OverrideResolver { } } - private void println(Collection inheritedProperties) { - for (CallableDescriptor inheritedProperty : inheritedProperties) { - System.out.println(" " + inheritedProperty); - } - } - - - private void checkOverrideForFunction(CallableMemberDescriptor declared) { + private void checkOverride(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 error = false; + boolean finalOverriddenError = false; + boolean typeMismatchError = false; for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) { if (overridden != null) { if (hasOverrideModifier) { - if (!overridden.getModality().isOpen() && !error) { + if (!overridden.getModality().isOpen() && !finalOverriddenError) { // 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; + finalOverriddenError = true; } - - if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared).isSuccess()) { + if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared) && !typeMismatchError) { + context.getTrace().report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden)); + typeMismatchError = true; } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index f850e3efb3d..151461e145b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -48,8 +48,8 @@ public class OverridingUtil { } for (D other : candidates) { if (me.getOriginal() == other.getOriginal() - && isOverridableBy(JetTypeChecker.INSTANCE, other, me).isSuccess() - && isOverridableBy(JetTypeChecker.INSTANCE, me, other).isSuccess()) { + && isOverridableBy(other, me).isSuccess() + && isOverridableBy(me, other).isSuccess()) { continue outerLoop; } } @@ -84,7 +84,7 @@ public class OverridingUtil { } @NotNull - public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + public static OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { if (!superDescriptor.getName().equals(subDescriptor.getName())) { return OverrideCompatibilityInfo.nameMismatch(); } @@ -135,7 +135,7 @@ public class OverridingUtil { } @NotNull - public static OverrideCompatibilityInfo isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { List superTypeParameters = superDescriptor.getTypeParameters(); List subTypeParameters = subDescriptor.getTypeParameters(); Map substitutionContext = Maps.newHashMap(); @@ -152,10 +152,10 @@ public class OverridingUtil { 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 false; } - return OverrideCompatibilityInfo.success(); + return true; } public static class OverrideCompatibilityInfo { @@ -194,7 +194,7 @@ public class OverridingUtil { @NotNull public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) { - return new OverrideCompatibilityInfo(false, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO + return new OverrideCompatibilityInfo(true, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CompositeTypeSubstitution.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CompositeTypeSubstitution.java new file mode 100644 index 00000000000..55cf5134be5 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CompositeTypeSubstitution.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.lang.types; + +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public class CompositeTypeSubstitution implements TypeSubstitutor.TypeSubstitution { + private final TypeSubstitutor.TypeSubstitution[] inner; + + public CompositeTypeSubstitution(@NotNull TypeSubstitutor.TypeSubstitution... inner) { + this.inner = inner; + } + + @Override + public TypeProjection get(TypeConstructor key) { + for (TypeSubstitutor.TypeSubstitution substitution : inner) { + TypeProjection value = substitution.get(key); + if (value != null) return value; + } + return null; + } + + @Override + public boolean isEmpty() { + for (TypeSubstitutor.TypeSubstitution substitution : inner) { + if (!substitution.isEmpty()) return false; + } + return true; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index 9745f1e646e..d6a5094cacc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -62,6 +62,10 @@ public class TypeSubstitutor { return new TypeSubstitutor(substitution); } + public static TypeSubstitutor create(@NotNull TypeSubstitution... substitutions) { + return create(new CompositeTypeSubstitution(substitutions)); + } + public static TypeSubstitutor create(@NotNull Map substitutionContext) { return create(new MapToTypeSubstitutionAdapter(substitutionContext)); } diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index b5abe519db1..93f0b82db9e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.diagnostics.Renderer; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; @@ -15,7 +16,7 @@ import java.util.List; /** * @author abreslav */ -public class DescriptorRenderer { +public class DescriptorRenderer implements Renderer { public static String getFQName(DeclarationDescriptor descriptor) { DeclarationDescriptor container = descriptor.getContainingDeclaration(); @@ -83,6 +84,13 @@ public class DescriptorRenderer { return escape("<"); } + @NotNull + @Override + public String render(@Nullable Object object) { + assert object instanceof DeclarationDescriptor; + return render((DeclarationDescriptor) object); + } + public String render(DeclarationDescriptor declarationDescriptor) { if (declarationDescriptor == null) return lt() + "null>"; StringBuilder stringBuilder = new StringBuilder(); diff --git a/idea/testData/checker/Constructors.jet b/idea/testData/checker/Constructors.jet index 70d1ce5a88a..7c6e8582a56 100644 --- a/idea/testData/checker/Constructors.jet +++ b/idea/testData/checker/Constructors.jet @@ -33,7 +33,7 @@ class Foo() : WithPC0, this() { } -class WithCPI_Dup(x : Int) { +class WithCPI_Dup(x : Int) { var x : Int } diff --git a/idea/testData/checker/infos/PropertiesWithBackingFields.jet b/idea/testData/checker/infos/PropertiesWithBackingFields.jet index 278297b6725..87409d71292 100644 --- a/idea/testData/checker/infos/PropertiesWithBackingFields.jet +++ b/idea/testData/checker/infos/PropertiesWithBackingFields.jet @@ -44,7 +44,7 @@ open class Super(i : Int) -class TestPCParameters(w : Int, x : Int, val y : Int, var z : Int) : Super(w) { +class TestPCParameters(w : Int, x : Int, val y : Int, var z : Int) : Super(w) { val xx = w @@ -52,6 +52,6 @@ class TestPCParameters(w : Int, x : Int, val y : Int, w + 1 } - fun foo() = x + fun foo() = x } \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Constructors.jet b/idea/testData/checkerWithErrorTypes/full/Constructors.jet index c6adf21f4b9..370fa759a3e 100644 --- a/idea/testData/checkerWithErrorTypes/full/Constructors.jet +++ b/idea/testData/checkerWithErrorTypes/full/Constructors.jet @@ -1,4 +1,3 @@ - open class NoC class NoC1 : NoC @@ -33,8 +32,8 @@ class Foo() : WithPC0, x : Int) { - var x : Int +class WithCPI_Dup(x : Int) { + var x : Int } class WithCPI(x : Int) { diff --git a/idea/testData/checkerWithErrorTypes/full/CovariantOverrideType.jet b/idea/testData/checkerWithErrorTypes/full/CovariantOverrideType.jet new file mode 100644 index 00000000000..a32e3d0ca40 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/CovariantOverrideType.jet @@ -0,0 +1,26 @@ +trait A { + fun foo() : Int = 1 + fun foo1() : Int = 1 + val a : Int + val a1 : Int + val g : Iterator + + fun g() : T + fun g1() : T +} + +abstract class B() : A { + override fun foo() { + } + override fun foo() : Unit { + } + + override val a : Double = 1.dbl + override val a1 = 1.dbl + + abstract override fun g() : Int + abstract override fun g1() : java.util.List + + abstract override val g : Iterator +} + diff --git a/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet index 8bdd70dd54a..cd4a142b85a 100644 --- a/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet +++ b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet @@ -52,6 +52,6 @@ class TestPCParameters(w : Int, x : Int, val y : Int, var z : Int) : Super(w) { w + 1 } - fun foo() = x + fun foo() = x } \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/quick/Override.jet b/idea/testData/checkerWithErrorTypes/quick/Override.jet index 4bc46e47790..23056bae452 100644 --- a/idea/testData/checkerWithErrorTypes/quick/Override.jet +++ b/idea/testData/checkerWithErrorTypes/quick/Override.jet @@ -16,17 +16,17 @@ namespace normal { class MyChildClass : MyClass {} - class MyIllegalClass : MyTrait, MyAbstractClass {} + class MyIllegalClass : MyTrait, MyAbstractClass {} - class MyIllegalClass2 : MyTrait, MyAbstractClass { + class MyIllegalClass2 : MyTrait, MyAbstractClass { override fun foo() {} } - class MyIllegalClass3 : MyTrait, MyAbstractClass { + class MyIllegalClass3 : MyTrait, MyAbstractClass { override fun bar() {} } - class MyIllegalClass4 : MyTrait, MyAbstractClass { + class MyIllegalClass4 : MyTrait, MyAbstractClass { fun foo() {} override fun other() {} } @@ -63,13 +63,13 @@ namespace generics { override fun bar(s: String) = s } - class MyIllegalGenericClass1 : MyTrait, MyAbstractClass {} - class MyIllegalGenericClass2 : MyTrait, MyAbstractClass { + class MyIllegalGenericClass1 : MyTrait, MyAbstractClass {} + class MyIllegalGenericClass2 : MyTrait, MyAbstractClass { override fun foo(r: R) = r } - class MyIllegalClass1 : MyTrait, MyAbstractClass {} + class MyIllegalClass1 : MyTrait, MyAbstractClass {} - class MyIllegalClass2 : MyTrait, MyAbstractClass { + class MyIllegalClass2 : MyTrait, MyAbstractClass { fun foo(t: T) = t fun bar(t: T) = t } diff --git a/idea/testData/codegen/classes/inheritance.jet b/idea/testData/codegen/classes/inheritance.jet index 6903e41e63d..0bfdb4e497f 100644 --- a/idea/testData/codegen/classes/inheritance.jet +++ b/idea/testData/codegen/classes/inheritance.jet @@ -5,7 +5,7 @@ trait Y { abstract val y : Int } -class YImpl(val y : Int) : Y {} +class YImpl(override val y : Int) : Y {} class Point(x : Int, yy : Int) : X(x) , Y { override val y : Int = yy diff --git a/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java b/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java index 158958e0101..913fdecbd7e 100644 --- a/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java @@ -139,7 +139,7 @@ public class JetOverridingTest extends LightDaemonAnalyzerTestCase { private void assertOverridabilityRelation(String superFun, String subFun, boolean expectedIsError) { FunctionDescriptor a = makeFunction(superFun); FunctionDescriptor b = makeFunction(subFun); - OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(semanticServices.getTypeChecker(), a, b); + OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(a, b); assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess()); }