Merge remote branch 'origin/master'
This commit is contained in:
@@ -1196,10 +1196,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
getInIntRange(leftValue, rangeExpression, inverted);
|
getInIntRange(leftValue, rangeExpression, inverted);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
leftValue.put(JetTypeMapper.TYPE_OBJECT, v);
|
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
||||||
|
leftValue.put(typeMapper.mapType(op.getValueParameters().get(0).getOutType()), v);
|
||||||
genToJVMStack(expression.getRight());
|
genToJVMStack(expression.getRight());
|
||||||
v.swap();
|
v.swap();
|
||||||
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
|
||||||
invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
|
invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
|
||||||
}
|
}
|
||||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import org.jetbrains.jet.lang.types.*;
|
|||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
@@ -77,6 +74,8 @@ public class BodyResolver {
|
|||||||
resolveFunctionBodies();
|
resolveFunctionBodies();
|
||||||
|
|
||||||
checkIfPrimaryConstructorIsNecessary();
|
checkIfPrimaryConstructorIsNecessary();
|
||||||
|
|
||||||
|
checkOverrides();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindOverrides() {
|
private void bindOverrides() {
|
||||||
@@ -88,35 +87,15 @@ public class BodyResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindOverridesInAClass(MutableClassDescriptor classDescriptor) {
|
private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) {
|
||||||
|
|
||||||
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
|
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
|
||||||
JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
|
|
||||||
assert function != null;
|
|
||||||
JetModifierList modifierList = function.getModifierList();
|
|
||||||
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
|
|
||||||
boolean hasOverrideModifier = overrideNode != null;
|
|
||||||
boolean foundError = false;
|
|
||||||
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
|
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
|
||||||
FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype);
|
FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype);
|
||||||
if (overridden != null) {
|
if (overridden != null) {
|
||||||
if (hasOverrideModifier && !overridden.getModality().isOpen() && !foundError) {
|
|
||||||
context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and can not be overridden");
|
|
||||||
foundError = true;
|
|
||||||
}
|
|
||||||
((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden);
|
((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) {
|
|
||||||
context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing");
|
|
||||||
}
|
|
||||||
PsiElement nameIdentifier = function.getNameIdentifier();
|
|
||||||
if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
|
|
||||||
FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenDescriptors().iterator().next();
|
|
||||||
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(),
|
|
||||||
"Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " +
|
|
||||||
overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +110,87 @@ public class BodyResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkOverrides() {
|
||||||
|
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||||
|
checkOverridesInAClass(entry.getValue(), entry.getKey());
|
||||||
|
}
|
||||||
|
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
|
||||||
|
checkOverridesInAClass(entry.getValue(), entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
|
||||||
|
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
|
||||||
|
checkOverrideForFunction(declaredFunction);
|
||||||
|
}
|
||||||
|
if (classDescriptor.getModality() == Modality.ABSTRACT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<FunctionDescriptor> allOverriddenFunctions = Sets.newHashSet();
|
||||||
|
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
|
||||||
|
for (FunctionDescriptor overriddenDescriptor : declaredFunction.getOverriddenDescriptors()) {
|
||||||
|
allOverriddenFunctions.add(overriddenDescriptor.getOriginal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean foundError = false;
|
||||||
|
PsiElement nameIdentifier = null;
|
||||||
|
if (klass instanceof JetClass) {
|
||||||
|
nameIdentifier = ((JetClass) klass).getNameIdentifier();
|
||||||
|
}
|
||||||
|
else if (klass instanceof JetObjectDeclaration) {
|
||||||
|
nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier();
|
||||||
|
}
|
||||||
|
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
|
||||||
|
Collection<DeclarationDescriptor> allDescriptors = supertype.getMemberScope().getAllDescriptors();
|
||||||
|
for (DeclarationDescriptor descriptor : allDescriptors) {
|
||||||
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||||
|
if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) {
|
||||||
|
DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
|
||||||
|
assert declarationDescriptor != null;
|
||||||
|
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" +
|
||||||
|
functionDescriptor.getName() + "' in " + declarationDescriptor.getName());
|
||||||
|
foundError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOverrideForFunction(FunctionDescriptor declaredFunction) {
|
||||||
|
JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
|
||||||
|
assert function != null;
|
||||||
|
JetModifierList modifierList = function.getModifierList();
|
||||||
|
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
|
||||||
|
boolean hasOverrideModifier = overrideNode != null;
|
||||||
|
boolean foundError = false;
|
||||||
|
|
||||||
|
for (FunctionDescriptor overridden : declaredFunction.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");
|
||||||
|
foundError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) {
|
||||||
|
context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing");
|
||||||
|
}
|
||||||
|
PsiElement nameIdentifier = function.getNameIdentifier();
|
||||||
|
if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
|
||||||
|
FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenDescriptors().iterator().next();
|
||||||
|
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(),
|
||||||
|
"Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " +
|
||||||
|
overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void checkIfPrimaryConstructorIsNecessary() {
|
private void checkIfPrimaryConstructorIsNecessary() {
|
||||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||||
MutableClassDescriptor classDescriptor = entry.getValue();
|
MutableClassDescriptor classDescriptor = entry.getValue();
|
||||||
JetClass jetClass = entry.getKey();
|
JetClass jetClass = entry.getKey();
|
||||||
if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null) {
|
if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null && !(classDescriptor.getKind() == ClassKind.TRAIT)) {
|
||||||
for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) {
|
for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) {
|
||||||
if (context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
if (context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||||
PsiElement nameIdentifier = jetClass.getNameIdentifier();
|
PsiElement nameIdentifier = jetClass.getNameIdentifier();
|
||||||
@@ -177,7 +232,7 @@ public class BodyResolver {
|
|||||||
@Override
|
@Override
|
||||||
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
|
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
|
||||||
if (descriptor.getKind() == ClassKind.TRAIT) {
|
if (descriptor.getKind() == ClassKind.TRAIT) {
|
||||||
context.getTrace().getErrorHandler().genericError(specifier.getNode(), "Traits can not use delegation");
|
context.getTrace().getErrorHandler().genericError(specifier.getNode(), "Traits cannot use delegation");
|
||||||
}
|
}
|
||||||
JetType supertype = context.getTrace().getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType supertype = context.getTrace().getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
recordSupertype(specifier.getTypeReference(), supertype);
|
recordSupertype(specifier.getTypeReference(), supertype);
|
||||||
@@ -198,7 +253,7 @@ public class BodyResolver {
|
|||||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||||
ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
|
ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
|
||||||
if (descriptor.getKind() == ClassKind.TRAIT) {
|
if (descriptor.getKind() == ClassKind.TRAIT) {
|
||||||
context.getTrace().getErrorHandler().genericError(node, "Traits can not initialize supertypes");
|
context.getTrace().getErrorHandler().genericError(node, "Traits cannot initialize supertypes");
|
||||||
}
|
}
|
||||||
JetTypeReference typeReference = call.getTypeReference();
|
JetTypeReference typeReference = call.getTypeReference();
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
@@ -455,10 +510,7 @@ public class BodyResolver {
|
|||||||
JetExpression initializer = property.getInitializer();
|
JetExpression initializer = property.getInitializer();
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
if (primaryConstructor == null) {
|
if (primaryConstructor != null) {
|
||||||
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed when no primary constructor is present");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
JetScope scope = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true);
|
JetScope scope = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true);
|
||||||
resolvePropertyInitializer(property, propertyDescriptor, initializer, scope);
|
resolvePropertyInitializer(property, propertyDescriptor, initializer, scope);
|
||||||
}
|
}
|
||||||
@@ -520,47 +572,77 @@ public class BodyResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) {
|
protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) {
|
||||||
JetExpression initializer = property.getInitializer();
|
checkPropertyAbstractness(property, propertyDescriptor, classDescriptor);
|
||||||
|
checkPropertyInitializer(property, propertyDescriptor, classDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPropertyAbstractness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {
|
||||||
JetPropertyAccessor getter = property.getGetter();
|
JetPropertyAccessor getter = property.getGetter();
|
||||||
JetPropertyAccessor setter = property.getSetter();
|
JetPropertyAccessor setter = property.getSetter();
|
||||||
PsiElement nameIdentifier = property.getNameIdentifier();
|
JetModifierList modifierList = property.getModifierList();
|
||||||
ASTNode nameNode = nameIdentifier == null ? property.getNode() : nameIdentifier.getNode();
|
ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;
|
||||||
if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
|
|
||||||
|
if (abstractNode != null) { //has abstract modifier
|
||||||
if (classDescriptor == null) {
|
if (classDescriptor == null) {
|
||||||
context.getTrace().getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
|
context.getTrace().getErrorHandler().genericError(abstractNode, "This property cannot be abstract");
|
||||||
"Global property can not be abstract");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (classDescriptor.getModality() != Modality.ABSTRACT) {
|
if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) {
|
||||||
context.getTrace().getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD),
|
context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName());
|
||||||
"Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (classDescriptor.getKind() == ClassKind.TRAIT) {
|
||||||
|
context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in traits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
|
||||||
|
JetExpression initializer = property.getInitializer();
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property with initializer can not be abstract");
|
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property with initializer cannot be abstract");
|
||||||
}
|
}
|
||||||
if (getter != null && getter.getBodyExpression() != null) {
|
if (getter != null && getter.getBodyExpression() != null) {
|
||||||
context.getTrace().getErrorHandler().genericError(getter.getNode(), "Property with getter implementation can not be abstract");
|
context.getTrace().getErrorHandler().genericError(getter.getNode(), "Property with getter implementation cannot be abstract");
|
||||||
}
|
}
|
||||||
if (setter != null && setter.getBodyExpression() != null) {
|
if (setter != null && setter.getBodyExpression() != null) {
|
||||||
context.getTrace().getErrorHandler().genericError(setter.getNode(), "Property with setter implementation can not be abstract");
|
context.getTrace().getErrorHandler().genericError(setter.getNode(), "Property with setter implementation cannot be abstract");
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {
|
||||||
|
boolean hasAccessorImplementation = (property.getGetter() != null && property.getGetter().getBodyExpression() != null) ||
|
||||||
|
(property.getSetter() != null && property.getSetter().getBodyExpression() != null);
|
||||||
|
if (propertyDescriptor.getModality() == Modality.ABSTRACT) return;
|
||||||
|
|
||||||
|
boolean inTrait = classDescriptor != null && classDescriptor.getKind() == ClassKind.TRAIT;
|
||||||
|
JetExpression initializer = property.getInitializer();
|
||||||
boolean backingFieldRequired = context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
boolean backingFieldRequired = context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
||||||
if (backingFieldRequired) {
|
|
||||||
if (initializer == null && !context.getTrace().getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) {
|
PsiElement nameIdentifier = property.getNameIdentifier();
|
||||||
if (classDescriptor == null || (getter != null && getter.getBodyExpression() != null) || (setter != null && setter.getBodyExpression() != null)) {
|
ASTNode nameNode = nameIdentifier == null ? property.getNode() : nameIdentifier.getNode();
|
||||||
|
|
||||||
|
if (inTrait && backingFieldRequired && hasAccessorImplementation) {
|
||||||
|
context.getTrace().getErrorHandler().genericError(nameNode, "Property in trait cannot have backing field");
|
||||||
|
}
|
||||||
|
if (initializer == null) {
|
||||||
|
if (backingFieldRequired && !inTrait && !context.getTrace().getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) {
|
||||||
|
if (classDescriptor == null || hasAccessorImplementation) {
|
||||||
context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized");
|
context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized");
|
||||||
} else if (classDescriptor.getKind() != ClassKind.TRAIT) {
|
} else {
|
||||||
context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract");
|
context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
if (inTrait) {
|
||||||
if (initializer != null) {
|
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed in trait");
|
||||||
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no backing field");
|
}
|
||||||
}
|
else if (!backingFieldRequired) {
|
||||||
|
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no backing field");
|
||||||
|
}
|
||||||
|
else if (classDescriptor != null && classDescriptor.getUnsubstitutedPrimaryConstructor() == null) {
|
||||||
|
context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed when no primary constructor is present");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,16 +730,17 @@ public class BodyResolver {
|
|||||||
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
|
||||||
PsiElement nameIdentifier;
|
PsiElement nameIdentifier;
|
||||||
JetModifierList modifierList;
|
JetModifierList modifierList;
|
||||||
|
boolean isPropertyAccessor = false;
|
||||||
if (function instanceof JetNamedFunction) {
|
if (function instanceof JetNamedFunction) {
|
||||||
JetNamedFunction namedFunction = (JetNamedFunction) function;
|
JetNamedFunction namedFunction = (JetNamedFunction) function;
|
||||||
nameIdentifier = namedFunction.getNameIdentifier();
|
nameIdentifier = namedFunction.getNameIdentifier();
|
||||||
modifierList = namedFunction.getModifierList();
|
modifierList = namedFunction.getModifierList();
|
||||||
}
|
}
|
||||||
else if (function instanceof JetPropertyAccessor) {
|
else if (function instanceof JetPropertyAccessor) {
|
||||||
return;
|
isPropertyAccessor = true;
|
||||||
// JetPropertyAccessor propertyAccessor = (JetPropertyAccessor) function;
|
JetPropertyAccessor propertyAccessor = (JetPropertyAccessor) function;
|
||||||
// nameIdentifier = propertyAccessor.getNamePlaceholder();
|
nameIdentifier = propertyAccessor.getNamePlaceholder();
|
||||||
// modifierList = propertyAccessor.getModifierList();
|
modifierList = propertyAccessor.getModifierList();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
@@ -669,24 +752,30 @@ public class BodyResolver {
|
|||||||
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
|
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
|
||||||
boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS;
|
boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS;
|
||||||
boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT;
|
boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT;
|
||||||
|
String methodName = function.getName() != null ? function.getName() + " " : "";
|
||||||
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
|
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
|
||||||
context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName());
|
context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract method " + methodName + "in non-abstract class " + classDescriptor.getName());
|
||||||
}
|
}
|
||||||
if (hasAbstractModifier && inTrait) {
|
if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
|
||||||
context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is not necessary in traits");
|
context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in trait");
|
||||||
}
|
}
|
||||||
if (function.getBodyExpression() != null && hasAbstractModifier) {
|
if (function.getBodyExpression() != null && hasAbstractModifier) {
|
||||||
context.getTrace().getErrorHandler().genericError(abstractNode, "Method " + function.getName() + " with body can not be abstract");
|
context.getTrace().getErrorHandler().genericError(abstractNode, "Method " + methodName + "with body cannot be abstract");
|
||||||
}
|
}
|
||||||
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null) {
|
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) {
|
||||||
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Method " + function.getName() + " without body must be abstract");
|
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Method " + function.getName() + " without body must be abstract");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hasAbstractModifier) {
|
if (hasAbstractModifier) {
|
||||||
context.getTrace().getErrorHandler().genericError(abstractNode, "Function " + function.getName() + " can not be abstract");
|
if (!isPropertyAccessor) {
|
||||||
|
context.getTrace().getErrorHandler().genericError(abstractNode, "Function " + function.getName() + " cannot be abstract");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.getTrace().getErrorHandler().genericError(abstractNode, "This property accessor cannot be abstract");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) {
|
if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) {
|
||||||
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Function " + function.getName() + " must have body");
|
context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Function " + function.getName() + " must have body");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ public class TopDownAnalyzer {
|
|||||||
@Override
|
@Override
|
||||||
protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
|
protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
bodyResolver.resolveBehaviorDeclarationBodies();
|
bodyResolver.resolveBehaviorDeclarationBodies();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class WritableScopeImpl extends WritableScopeWithImports {
|
public class WritableScopeImpl extends WritableScopeWithImports {
|
||||||
|
|
||||||
private final Collection<DeclarationDescriptor> allDescriptors = Sets.newHashSet();
|
private final Collection<DeclarationDescriptor> allDescriptors = Sets.newLinkedHashSet();
|
||||||
private boolean allDescriptorsDone = false;
|
private boolean allDescriptorsDone = false;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -1,81 +1,226 @@
|
|||||||
namespace abstract
|
namespace abstract
|
||||||
|
|
||||||
class MyClass() {
|
class MyClass() {
|
||||||
|
//properties
|
||||||
|
val <error>a</error>: Int
|
||||||
|
val a1: Int = 1
|
||||||
|
<error>abstract</error> val a2: Int
|
||||||
|
<error>abstract</error> val a3: Int = 1
|
||||||
|
|
||||||
|
var <error>b</error>: Int private set
|
||||||
|
var b1: Int = 0; private set
|
||||||
|
<error>abstract</error> var b2: Int private set
|
||||||
|
<error>abstract</error> var b3: Int = 0; private set
|
||||||
|
|
||||||
|
var <error>c</error>: Int set(v: Int) { $c = v }
|
||||||
|
var c1: Int = 0; set(v: Int) { $c1 = v }
|
||||||
|
<error>abstract</error> var c2: Int set(v: Int) { $c2 = v }
|
||||||
|
<error>abstract</error> var c3: Int = 0; set(v: Int) { $c3 = v }
|
||||||
|
|
||||||
|
val e: Int get() = a
|
||||||
|
val e1: Int = <error>0</error>; get() = a
|
||||||
|
<error>abstract</error> val e2: Int get() = a
|
||||||
|
<error>abstract</error> val e3: Int = 0; get() = a
|
||||||
|
|
||||||
|
//methods
|
||||||
fun <error>f</error>()
|
fun <error>f</error>()
|
||||||
fun g() {}
|
fun g() {}
|
||||||
<error>abstract</error> fun h()
|
<error>abstract</error> fun h()
|
||||||
<error>abstract</error> fun j() {}
|
<error><error>abstract</error></error> fun j() {}
|
||||||
|
|
||||||
|
//property accessors
|
||||||
|
var i: Int <error>abstract</error> get <error>abstract</error> set
|
||||||
|
var i1: Int = <error>0</error>; <error>abstract</error> get <error>abstract</error> set
|
||||||
|
|
||||||
|
var j: Int get() = i; <error>abstract</error> set
|
||||||
|
var j1: Int = <error>0</error>; get() = i; <error>abstract</error> set
|
||||||
|
|
||||||
|
var <error>k</error>: Int <error>abstract</error> set
|
||||||
|
var k1: Int = 0; <error>abstract</error> set
|
||||||
|
|
||||||
|
var l: Int <error>abstract</error> get <error>abstract</error> set
|
||||||
|
var l1: Int = <error>0</error>; <error>abstract</error> get <error>abstract</error> set
|
||||||
|
|
||||||
|
var n: Int <error>abstract</error> get <error>abstract</error> set(v: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MyAbstractClass() {
|
abstract class MyAbstractClass() {
|
||||||
|
//properties
|
||||||
|
val <error>a</error>: Int
|
||||||
|
val a1: Int = 1
|
||||||
|
abstract val a2: Int
|
||||||
|
abstract val a3: Int = <error>1</error>
|
||||||
|
|
||||||
|
var <error>b</error>: Int private set
|
||||||
|
var b1: Int = 0; private set
|
||||||
|
abstract var b2: Int private set
|
||||||
|
abstract var b3: Int = <error>0</error>; private set
|
||||||
|
|
||||||
|
var <error>c</error>: Int set(v: Int) { $c = v }
|
||||||
|
var c1: Int = 0; set(v: Int) { $c1 = v }
|
||||||
|
abstract var c2: Int <error>set(v: Int) { $c2 = v }</error>
|
||||||
|
abstract var c3: Int = <error>0</error>; <error>set(v: Int) { $c3 = v }</error>
|
||||||
|
|
||||||
|
val e: Int get() = a
|
||||||
|
val e1: Int = <error>0</error>; get() = a
|
||||||
|
abstract val e2: Int <error>get() = a</error>
|
||||||
|
abstract val e3: Int = <error>0</error>; <error>get() = a</error>
|
||||||
|
|
||||||
|
//methods
|
||||||
fun <error>f</error>()
|
fun <error>f</error>()
|
||||||
fun g() {}
|
fun g() {}
|
||||||
abstract fun h()
|
abstract fun h()
|
||||||
<error>abstract</error> fun j() {}
|
<error>abstract</error> fun j() {}
|
||||||
|
|
||||||
|
//property accessors
|
||||||
|
var i: Int abstract get abstract set
|
||||||
|
var i1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var j: Int get() = i; abstract set
|
||||||
|
var j1: Int get() = i; abstract set
|
||||||
|
|
||||||
|
var <error>k</error>: Int abstract set
|
||||||
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
|
var l: Int abstract get abstract set
|
||||||
|
var l1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var n: Int abstract get <error>abstract</error> set(v: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
|
//properties
|
||||||
|
val a: Int
|
||||||
|
val a1: Int = <error>1</error>
|
||||||
|
<warning>abstract</warning> val a2: Int
|
||||||
|
<warning>abstract</warning> val a3: Int = <error>1</error>
|
||||||
|
|
||||||
|
var b: Int private set
|
||||||
|
var b1: Int = <error>0</error>; private set
|
||||||
|
<warning>abstract</warning> var b2: Int private set
|
||||||
|
<warning>abstract</warning> var b3: Int = <error>0</error>; private set
|
||||||
|
|
||||||
|
var <error>c</error>: Int set(v: Int) { $c = v }
|
||||||
|
var <error>c1</error>: Int = <error>0</error>; set(v: Int) { $c1 = v }
|
||||||
|
<warning>abstract</warning> var c2: Int <error>set(v: Int) { $c2 = v }</error>
|
||||||
|
<warning>abstract</warning> var c3: Int = <error>0</error>; <error>set(v: Int) { $c3 = v }</error>
|
||||||
|
|
||||||
|
val e: Int get() = a
|
||||||
|
val e1: Int = <error>0</error>; get() = a
|
||||||
|
<warning>abstract</warning> val e2: Int <error>get() = a</error>
|
||||||
|
<warning>abstract</warning> val e3: Int = <error>0</error>; <error>get() = a</error>
|
||||||
|
|
||||||
|
//methods
|
||||||
fun f()
|
fun f()
|
||||||
fun g() {}
|
fun g() {}
|
||||||
<warning>abstract</warning> fun h()
|
<warning>abstract</warning> fun h()
|
||||||
<error>abstract</error> fun j() {}
|
<error>abstract</error> fun j() {}
|
||||||
|
|
||||||
|
//property accessors
|
||||||
|
var i: Int abstract get abstract set
|
||||||
|
var i1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var j: Int get() = i; abstract set
|
||||||
|
var j1: Int = <error>0</error>; get() = i; abstract set
|
||||||
|
|
||||||
|
var k: Int abstract set
|
||||||
|
var k1: Int = <error>0</error>; abstract set
|
||||||
|
|
||||||
|
var l: Int abstract get abstract set
|
||||||
|
var l1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var n: Int abstract get <error>abstract</error> set(v: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class MyEnum {
|
enum class MyEnum() {
|
||||||
|
//properties
|
||||||
|
val <error>a</error>: Int
|
||||||
|
val a1: Int = 1
|
||||||
|
abstract val a2: Int
|
||||||
|
abstract val a3: Int = <error>1</error>
|
||||||
|
|
||||||
|
var <error>b</error>: Int private set
|
||||||
|
var b1: Int = 0; private set
|
||||||
|
abstract var b2: Int private set
|
||||||
|
abstract var b3: Int = <error>0</error>; private set
|
||||||
|
|
||||||
|
var <error>c</error>: Int set(v: Int) { $c = v }
|
||||||
|
var c1: Int = 0; set(v: Int) { $c1 = v }
|
||||||
|
abstract var c2: Int <error>set(v: Int) { $c2 = v }</error>
|
||||||
|
abstract var c3: Int = <error>0</error>; <error>set(v: Int) { $c3 = v }</error>
|
||||||
|
|
||||||
|
val e: Int get() = a
|
||||||
|
val e1: Int = <error>0</error>; get() = a
|
||||||
|
abstract val e2: Int <error>get() = a</error>
|
||||||
|
abstract val e3: Int = <error>0</error>; <error>get() = a</error>
|
||||||
|
|
||||||
|
//methods
|
||||||
fun <error>f</error>()
|
fun <error>f</error>()
|
||||||
fun g() {}
|
fun g() {}
|
||||||
abstract fun h()
|
abstract fun h()
|
||||||
<error>abstract</error> fun j() {}
|
<error>abstract</error> fun j() {}
|
||||||
|
|
||||||
|
//property accessors
|
||||||
|
var i: Int abstract get abstract set
|
||||||
|
var i1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var j: Int get() = i; abstract set
|
||||||
|
var j1: Int = <error>0</error>; get() = i; abstract set
|
||||||
|
|
||||||
|
var <error>k</error>: Int abstract set
|
||||||
|
var k1: Int = 0; abstract set
|
||||||
|
|
||||||
|
var l: Int abstract get abstract set
|
||||||
|
var l1: Int = <error>0</error>; abstract get abstract set
|
||||||
|
|
||||||
|
var n: Int abstract get <error>abstract</error> set(v: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class A1() {
|
abstract enum class MyAbstractEnum() {}
|
||||||
fun <error>foo</error>(): Int
|
|
||||||
<error>abstract</error> fun f(): Int
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class A2() {
|
namespace MyNamespace {
|
||||||
abstract fun f(): Int
|
//properties
|
||||||
}
|
val <error>a</error>: Int
|
||||||
|
val a1: Int = 1
|
||||||
|
<error>abstract</error> val a2: Int
|
||||||
|
<error>abstract</error> val a3: Int = 1
|
||||||
|
|
||||||
class A3() {
|
var <error>b</error>: Int private set
|
||||||
val <error>i</error>: Int
|
var b1: Int = 0; private set
|
||||||
val <error>j</error>: Int?
|
<error>abstract</error> var b2: Int private set
|
||||||
var <error>k</error>: String
|
<error>abstract</error> var b3: Int = 0; private set
|
||||||
var <error>l</error>: Int?
|
|
||||||
}
|
|
||||||
|
|
||||||
class <error>A4</error> {
|
var <error>c</error>: Int set(v: Int) { $c = v }
|
||||||
val <error>i</error>: Int?
|
var c1: Int = 0; set(v: Int) { $c1 = v }
|
||||||
}
|
<error>abstract</error> var c2: Int set(v: Int) { $c2 = v }
|
||||||
|
<error>abstract</error> var c3: Int = 0; set(v: Int) { $c3 = v }
|
||||||
|
|
||||||
class <error>A5</error> {
|
val e: Int get() = a
|
||||||
var <error>i</error>: Int?
|
val e1: Int = <error>0</error>; get() = a
|
||||||
}
|
<error>abstract</error> val e2: Int get() = a
|
||||||
|
<error>abstract</error> val e3: Int = 0; get() = a
|
||||||
|
|
||||||
class A6 {
|
//methods
|
||||||
<error>abstract</error> val i: Int
|
fun <error>f</error>()
|
||||||
}
|
fun g() {}
|
||||||
|
<error>abstract</error> fun h()
|
||||||
|
<error>abstract</error> fun j() {}
|
||||||
|
|
||||||
abstract class A7 {
|
//property accessors
|
||||||
abstract val i: Int //ok
|
var i: Int <error>abstract</error> get <error>abstract</error> set
|
||||||
}
|
var i1: Int = <error>0</error>; <error>abstract</error> get <error>abstract</error> set
|
||||||
|
|
||||||
class A8() {
|
var j: Int get() = i; <error>abstract</error> set
|
||||||
val i = 11
|
var j1: Int = <error>0</error>; get() = i; <error>abstract</error> set
|
||||||
}
|
|
||||||
|
|
||||||
class A9() {
|
var <error>k</error>: Int <error>abstract</error> set
|
||||||
<error>abstract</error> val i = 23
|
var k1: Int = 0; <error>abstract</error> set
|
||||||
}
|
|
||||||
|
|
||||||
abstract class <error>A10</error> {
|
var l: Int <error>abstract</error> get <error>abstract</error> set
|
||||||
val <error>i</error>: Int
|
var l1: Int = <error>0</error>; <error>abstract</error> get <error>abstract</error> set
|
||||||
}
|
|
||||||
|
|
||||||
<error>abstract</error> val i: Int
|
var n: Int <error>abstract</error> get <error>abstract</error> set(v: Int) {}
|
||||||
<error>abstract</error> fun foo(): fun(Int): Int
|
}
|
||||||
val <error>j</error>: Int
|
|
||||||
fun <error>foo1</error>(): fun(Int): Int
|
|
||||||
|
|
||||||
//creating an instance
|
//creating an instance
|
||||||
abstract class B1(
|
abstract class B1(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class StrangeIterateeImpl<in I, out O>(val obj: O) : Iteratee<I, O> {
|
|||||||
override fun process(item: I): Iteratee<I, O> = StrangeIterateeImpl<I, O>(obj)
|
override fun process(item: I): Iteratee<I, O> = StrangeIterateeImpl<I, O>(obj)
|
||||||
override val isDone = true
|
override val isDone = true
|
||||||
override val result = obj
|
override val result = obj
|
||||||
override val done = obj
|
override fun done() = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Sum() : Iteratee<Int, Int> {
|
abstract class Sum() : Iteratee<Int, Int> {
|
||||||
@@ -51,7 +51,7 @@ abstract class Sum() : Iteratee<Int, Int> {
|
|||||||
abstract override fun done() : Int
|
abstract override fun done() : Int
|
||||||
}
|
}
|
||||||
|
|
||||||
class Collection<E> : Iterable<E> {
|
abstract class Collection<E> : Iterable<E> {
|
||||||
fun iterate<O>(iteratee : Iteratee<E, O>) : O {
|
fun iterate<O>(iteratee : Iteratee<E, O>) : O {
|
||||||
for (x in this) {
|
for (x in this) {
|
||||||
val it = iteratee.process(x)
|
val it = iteratee.process(x)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
class XXX {
|
abstract class XXX {
|
||||||
val a : Int abstract get
|
val a : Int abstract get
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class MyCollection1(): java.lang.Iterable<Int> {
|
|||||||
|
|
||||||
override fun next() : Int = k--
|
override fun next() : Int = k--
|
||||||
override fun hasNext() = k > 0
|
override fun hasNext() = k > 0
|
||||||
|
override fun remove() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class MyRange1() : Range<Int> {
|
||||||
|
override fun contains(item: Int) = true
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyRange2() {
|
||||||
|
fun contains(item: Int) = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (1 in MyRange1()) {
|
||||||
|
if (1 in MyRange2()) {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
return "fail 2"
|
||||||
|
}
|
||||||
|
return "fail 1"
|
||||||
|
}
|
||||||
@@ -177,4 +177,8 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
assertEquals(true, main.invoke(null, null, "lala"));
|
assertEquals(true, main.invoke(null, null, "lala"));
|
||||||
assertEquals(false, main.invoke(null, "papa", "papa"));
|
assertEquals(false, main.invoke(null, "papa", "papa"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt299() throws Exception {
|
||||||
|
blackBoxFile("regressions/kt299.jet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user