diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index 6058eec9ff8..7e351cde8bc 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -43,4 +43,8 @@ public interface ClassDescriptor extends ClassifierDescriptor { JetType getClassObjectType(); boolean isObject(); + + boolean isAbstract(); + + boolean isOpen(); } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index ad23db0bb23..6b29bae2742 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -115,4 +115,14 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl public boolean hasConstructors() { return !constructors.isEmpty(); } + + @Override + public boolean isAbstract() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java index f6642f22907..4eae6040fc4 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java @@ -66,6 +66,11 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements return null; } + @Nullable + public MemberModifiers getModifiers() { + return null; + } + @Override public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) { throw new UnsupportedOperationException("Constructors cannot override anything"); diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java index 48c2622d412..cbaee1a462e 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java @@ -11,7 +11,7 @@ import java.util.Set; /** * @author abreslav */ -public interface FunctionDescriptor extends DeclarationDescriptor { +public interface FunctionDescriptor extends DeclarationDescriptor, MemberDescriptor { @Override @NotNull DeclarationDescriptor getContainingDeclaration(); diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index 16992f967e8..16170cd84d7 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -22,6 +22,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements private JetType unsubstitutedReturnType; private JetType receiverType; + private MemberModifiers modifiers; private final Set overriddenFunctions = Sets.newHashSet(); private final FunctionDescriptor original; @@ -68,6 +69,16 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements return overriddenFunctions; } + public void setModifiers(MemberModifiers modifiers) { + this.modifiers = modifiers; + } + + @Nullable + @Override + public MemberModifiers getModifiers() { + return modifiers; + } + public void addOverriddenFunction(@NotNull FunctionDescriptor overriddenFunction) { overriddenFunctions.add(overriddenFunction); } diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index d775e23119d..8767f4331e8 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -126,6 +126,16 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { return original.isObject(); } + @Override + public boolean isAbstract() { + return original.isAbstract(); + } + + @Override + public boolean isOpen() { + return original.isOpen(); + } + @Override public boolean isClassObjectAValue() { return original.isClassObjectAValue(); diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 7686e45aad8..7d1997588e6 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -23,6 +23,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private Collection supertypes = Lists.newArrayList(); private boolean open; + private boolean isAbstract; private TypeConstructor typeConstructor; private final WritableScope scopeForMemberResolution; private final WritableScope scopeForMemberLookup; @@ -139,6 +140,15 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme scopeForMemberResolution.addLabeledDeclaration(this); } + @Override + public boolean isAbstract() { + return isAbstract; + } + + public void setAbstract(boolean isAbstract) { + this.isAbstract = isAbstract; + } + public boolean isOpen() { return open; } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 4b28808398e..f24dfa43aae 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -27,6 +27,7 @@ public interface BindingContext { WritableSlice RESOLUTION_SCOPE = ManyMapSlices.createSimpleSlice("RESOLUTION_SCOPE"); WritableSlice VARIABLE_REASSIGNMENT = ManyMapSlices.createSimpleSetSlice("VARIABLE_REASSIGNMENT"); + WritableSlice VARIABLE_ASSIGNMENT = ManyMapSlices.createSimpleSlice("VARIABLE_ASSIGNMENT"); WritableSlice PROCESSED = ManyMapSlices.createSimpleSetSlice("PROCESSED"); WritableSlice STATEMENT = ManyMapSlices.createRemovableSetSlice("STATEMENT"); @@ -59,6 +60,7 @@ public interface BindingContext { return backingFieldRequired; } }; + WritableSlice IS_INITIALIZED = ManyMapSlices.createSimpleSetSlice("IS_INITIALIZED"); WritableSlice BLOCK = new ManyMapSlices.SetSlice("BLOCK", RewritePolicy.DO_NOTHING) { @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index ebff18e8796..f1b544fd260 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -65,6 +65,11 @@ public class ClassDescriptorResolver { Collection supertypes = delegationSpecifiers.isEmpty() ? Collections.singleton(JetStandardClasses.getAnyType()) : resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver); +// for (JetType supertype: supertypes) { +// if (supertype.getConstructor().isSealed()) { +// trace.getErrorHandler().genericError(classElement.getNameAsDeclaration().getNode(), "Class " + classElement.getName() + " can not extend final type " + supertype); +// } +// } boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD); final WritableScope memberDeclarations = new WritableScopeImpl(parameterScope, classDescriptor, trace.getErrorHandler()); @@ -141,6 +146,7 @@ public class ClassDescriptorResolver { descriptor.setTypeParameterDescriptors(typeParameters); descriptor.setOpen(classElement.hasModifier(JetTokens.OPEN_KEYWORD) || classElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)); + descriptor.setAbstract(classElement.hasModifier(JetTokens.ABSTRACT_KEYWORD)); trace.record(BindingContext.CLASS, classElement, descriptor); } @@ -220,6 +226,7 @@ public class ClassDescriptorResolver { returnType = ErrorUtils.createErrorType("No type, no body"); } } + functionDescriptor.setModifiers(resolveModifiers(function.getModifierList(), DEFAULT_MODIFIERS)); functionDescriptor.initialize( receiverType, diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 182d8731119..c73a3c1ca82 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -27,8 +27,9 @@ public class TopDownAnalyzer { private final Map classes = Maps.newLinkedHashMap(); private final Map objects = Maps.newLinkedHashMap(); - private final Map namespaceScopes = Maps.newHashMap(); - private final Map namespaceDescriptors = Maps.newHashMap(); + + protected final Map namespaceScopes = Maps.newHashMap(); + protected final Map namespaceDescriptors = Maps.newHashMap(); private final Map functions = Maps.newLinkedHashMap(); private final Map constructors = Maps.newLinkedHashMap(); @@ -76,46 +77,39 @@ public class TopDownAnalyzer { }); } - @Deprecated // For JetStandardLibraryOnly - public void processStandardLibraryNamespace(@NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) { - namespaceScopes.put(namespace, standardLibraryNamespace.getMemberScope()); - namespaceDescriptors.put(namespace, standardLibraryNamespace); - process(outerScope, standardLibraryNamespace, namespace.getDeclarations()); - } - public void processObject(@NotNull JetScope outerScope, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetObjectDeclaration object) { process(outerScope, new NamespaceLike.Adapter(containingDeclaration) { - @Override - public NamespaceDescriptorImpl getNamespace(String name) { - throw new UnsupportedOperationException(); - } + @Override + public NamespaceDescriptorImpl getNamespace(String name) { + throw new UnsupportedOperationException(); + } - @Override - public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { - throw new UnsupportedOperationException(); - } + @Override + public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { + throw new UnsupportedOperationException(); + } - @Override - public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) { + @Override + public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) { - } + } - @Override - public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { - throw new UnsupportedOperationException(); - } + @Override + public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { + throw new UnsupportedOperationException(); + } - @Override - public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { + @Override + public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { - } + } - @Override - public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { - return ClassObjectStatus.NOT_ALLOWED; - } - }, Collections.singletonList(object)); + @Override + public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { + return ClassObjectStatus.NOT_ALLOWED; + } + }, Collections.singletonList(object)); } public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { @@ -414,6 +408,7 @@ public class TopDownAnalyzer { @Override public void visitNamedFunction(JetNamedFunction function) { FunctionDescriptorImpl functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(namespaceLike, scope, function); + checkFunctionCorrectness(function, functionDescriptor, namespaceLike); namespaceLike.addFunctionDescriptor(functionDescriptor); functions.put(function, functionDescriptor); declaringScopes.put(function, scope); @@ -505,12 +500,29 @@ public class TopDownAnalyzer { private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) { for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { +// JetFunction function = (JetFunction) trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction); +// boolean isOverride = declaredFunction.getModifiers().isOverride(); for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype); if (overridden != null) { +// if (isOverride && overridden.getModifiers()!= null && !overridden.getModifiers().isOverridable()) { +// trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.OVERRIDE_KEYWORD), +// "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and can not be overridden"); +// isOverride = false; +// } ((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden); } } +// if (declaredFunction.getModifiers().isOverride() && declaredFunction.getOverriddenFunctions().size() == 0) { +// trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.OVERRIDE_KEYWORD), +// "Method " + declaredFunction.getName() + " overrides nothing"); +// } +// if (!declaredFunction.getModifiers().isOverride() && declaredFunction.getOverriddenFunctions().size() > 0) { +// FunctionDescriptor overriddenMethod = declaredFunction.getOverriddenFunctions().iterator().next(); +// trace.getErrorHandler().genericError(function.getNameIdentifier().getNode(), +// "Method " + declaredFunction.getName() + " overrides method " + overriddenMethod.getName() + " in class " + +// overriddenMethod.getContainingDeclaration().getName() + " and needs 'override' modifier"); +// } } } @@ -567,7 +579,9 @@ public class TopDownAnalyzer { public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) { JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { - JetScope scope = scopeForConstructor == null ? descriptor.getScopeForMemberResolution() : scopeForConstructor; + JetScope scope = scopeForConstructor == null + ? descriptor.getScopeForMemberResolution() + : scopeForConstructor; JetType type = typeInferrer.getType(scope, delegateExpression, false, JetTypeInferrer.NO_EXPECTED_TYPE); JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference()); if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible? @@ -587,7 +601,7 @@ public class TopDownAnalyzer { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); assert valueArgumentList != null; trace.getErrorHandler().genericError(valueArgumentList.getNode(), - "Class " + JetPsiUtil.safeName(jetClass.getName()) + " must have a constructor in order to be able to initialize supertypes"); + "Class " + JetPsiUtil.safeName(jetClass.getName()) + " must have a constructor in order to be able to initialize supertypes"); } } } @@ -642,7 +656,7 @@ public class TopDownAnalyzer { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); assert primaryConstructor != null; final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); - JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow + JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(createFieldAssignTrackingTrace(), JetFlowInformationProvider.NONE); // TODO : flow for (JetClassInitializer anonymousInitializer : anonymousInitializers) { typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true, JetTypeInferrer.NO_EXPECTED_TYPE); } @@ -782,6 +796,7 @@ public class TopDownAnalyzer { } resolvePropertyAccessors(property, propertyDescriptor, declaringScope); + checkPropertyCorrectness(property, propertyDescriptor, classDescriptor); processed.add(property); } } @@ -800,6 +815,7 @@ public class TopDownAnalyzer { } resolvePropertyAccessors(property, propertyDescriptor, declaringScope); + checkPropertyCorrectness(property, propertyDescriptor, null); } } @@ -833,9 +849,69 @@ public class TopDownAnalyzer { resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope); } +// JetExpression initializer = property.getInitializer(); +// if (!property.isVar() && initializer != null && !trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { +// trace.getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no setter and no backing field either"); +// } + } + + protected void checkPropertyCorrectness(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) { JetExpression initializer = property.getInitializer(); - if (!property.isVar() && initializer != null && !trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { - trace.getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no setter and no backing field either"); + JetPropertyAccessor getter = property.getGetter(); + JetPropertyAccessor setter = property.getSetter(); + if (propertyDescriptor.getModifiers().isAbstract()) { + if (classDescriptor == null) { + trace.getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), + "Global property can not be abstract"); + return; + } + if (! classDescriptor.isAbstract()) { + trace.getErrorHandler().genericError(property.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), + "Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName()); + return; + } + if (initializer != null) { + trace.getErrorHandler().genericError(initializer.getNode(), "Property with initializer can not be abstract"); + } + if (getter != null && getter.getBodyExpression() != null) { + trace.getErrorHandler().genericError(getter.getNode(), "Property with getter implementation can not be abstract"); + } + if (setter != null && setter.getBodyExpression() != null) { + trace.getErrorHandler().genericError(setter.getNode(), "Property with setter implementation can not be abstract"); + } + return; + } + boolean backingFieldRequired = trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); + if (initializer != null && ! backingFieldRequired) { + trace.getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no backing field"); + } + if (initializer == null && backingFieldRequired && ! trace.getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor)) { + if (classDescriptor == null || (getter != null && getter.getBodyExpression() != null) || (setter != null && setter.getBodyExpression() != null)) { + trace.getErrorHandler().genericError(property.getNameIdentifier().getNode(), "Property must be initialized"); + } else { + trace.getErrorHandler().genericError(property.getNameIdentifier().getNode(), "Property must be initialized or be abstract"); + } + } + } + + protected void checkFunctionCorrectness(JetNamedFunction function, FunctionDescriptor functionDescriptor, DeclarationDescriptor containingDescriptor) { + if (containingDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; + if (functionDescriptor.getModifiers().isAbstract() && !classDescriptor.isAbstract()) { + trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), + "Abstract method " + function.getName() + " in non-abstract class " + classDescriptor.getName()); + } + if (function.getBodyExpression() == null && !functionDescriptor.getModifiers().isAbstract()) { + trace.getErrorHandler().genericError(function.getNameIdentifier().getNode(), "Method without body must be abstract"); + } + return; + } + if (functionDescriptor.getModifiers().isAbstract()) { + trace.getErrorHandler().genericError(function.getModifierList().getModifierNode(JetTokens.ABSTRACT_KEYWORD), + "Global function " + function.getName() + " can not be abstract"); + } + if (function.getBodyExpression() == null && !functionDescriptor.getModifiers().isAbstract()) { + trace.getErrorHandler().genericError(function.getNameIdentifier().getNode(), "Global function must have body"); } } @@ -856,6 +932,22 @@ public class TopDownAnalyzer { }); } + private BindingTraceAdapter createFieldAssignTrackingTrace() { + return new BindingTraceAdapter(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new BindingTraceAdapter.RecordHandler() { + @Override + public void handleRecord(WritableSlice jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) { + if (expression instanceof JetSimpleNameExpression) { + JetSimpleNameExpression variable = (JetSimpleNameExpression) expression; + if (variable.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { + if (descriptor instanceof PropertyDescriptor) { + traceForMembers.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) descriptor); + } + } + } + } + }); + } + private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(property, initializer); // TODO : flow JET-15 JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(traceForConstructors, flowInformationProvider); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzerForStandardLibrary.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzerForStandardLibrary.java new file mode 100644 index 00000000000..542662963d5 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzerForStandardLibrary.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.JetNamespace; +import org.jetbrains.jet.lang.psi.JetProperty; + +/** + * @author svtk + */ +public class TopDownAnalyzerForStandardLibrary extends TopDownAnalyzer { + + public TopDownAnalyzerForStandardLibrary(JetSemanticServices semanticServices, @NotNull BindingTrace bindingTrace) { + super(semanticServices, bindingTrace); + } + + public void processStandardLibraryNamespace(@NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) { + namespaceScopes.put(namespace, standardLibraryNamespace.getMemberScope()); + namespaceDescriptors.put(namespace, standardLibraryNamespace); + process(outerScope, standardLibraryNamespace, namespace.getDeclarations()); + } + + @Override + protected void checkPropertyCorrectness(JetProperty property, PropertyDescriptor propertyDescriptor, ClassDescriptor classDescriptor) {} + + + @Override + protected void checkFunctionCorrectness(JetNamedFunction function, FunctionDescriptor functionDescriptor, DeclarationDescriptor containingDescriptor) {} +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java index eae0a7a704a..98ed1b2be9d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java @@ -115,6 +115,16 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements return false; } + @Override + public boolean isAbstract() { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + @Override public boolean isClassObjectAValue() { return false; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index 29c67d84591..220ea250226 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -81,7 +81,7 @@ public class JetStandardLibrary { JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this); BindingTraceContext bindingTraceContext = new BindingTraceContext(); - TopDownAnalyzer bootstrappingTDA = new TopDownAnalyzer(bootstrappingSemanticServices, bindingTraceContext); + TopDownAnalyzerForStandardLibrary bootstrappingTDA = new TopDownAnalyzerForStandardLibrary(bootstrappingSemanticServices, bindingTraceContext); WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, ErrorHandler.THROW_EXCEPTION).setDebugName("Root bootstrap scope"); // this.libraryScope = bootstrappingTDA.process(JetStandardClasses.STANDARD_CLASSES, file.getRootNamespace().getDeclarations()); // bootstrappingTDA.process(writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace().getDeclarations()); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index f6cf4ec7815..eae2b3dbd98 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -2806,6 +2806,17 @@ public class JetTypeInferrer { // context.trace.getErrorHandler().typeMismatch(right, leftType, rightType); // } } + if (left instanceof JetSimpleNameExpression) { + JetSimpleNameExpression variable = (JetSimpleNameExpression) left; + String referencedName = variable.getReferencedName(); + if (variable.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER + && referencedName != null) { + PropertyDescriptor property = context.scope.getPropertyByFieldReference(referencedName); + if (property != null) { + context.trace.record(BindingContext.VARIABLE_ASSIGNMENT, variable, property); + } + } + } return null; } diff --git a/idea/testData/checker/Abstract.jet b/idea/testData/checker/Abstract.jet new file mode 100644 index 00000000000..b1083b6934f --- /dev/null +++ b/idea/testData/checker/Abstract.jet @@ -0,0 +1,50 @@ +namespace abstract + +class A1() { + fun foo(): Int + abstract fun f(): Int +} + +abstract class A2() { + abstract fun f(): Int +} + +class A3() { + val i: Int + val j: Int? + var k: String + var l: Int? +} + +class A4 { + val i: Int? +} + +class A5 { + var i: Int? +} + +class A6 { + abstract val i: Int +} + +abstract class A7 { + abstract val i: Int //ok +} + +class A8() { + val i = 11 +} + +class A9() { + abstract val i = 23 +} + +abstract class A10 { + val i: Int +} + +abstract val i: Int +abstract fun foo(): fun(Int): Int +val j: Int +fun foo1(): fun(Int): Int \ No newline at end of file diff --git a/idea/testData/checker/BinaryCallsOnNullableValues.jet b/idea/testData/checker/BinaryCallsOnNullableValues.jet index b05563cd548..98f5a79e77d 100644 --- a/idea/testData/checker/BinaryCallsOnNullableValues.jet +++ b/idea/testData/checker/BinaryCallsOnNullableValues.jet @@ -1,13 +1,13 @@ -class A() { - fun equals(a : Any?) : Boolean +abstract class A() { + abstract fun equals(a : Any?) : Boolean } -class B() { - fun equals(a : Any?) : Boolean? +abstract class B() { + abstract fun equals(a : Any?) : Boolean? } -class C() { - fun equals(a : Any?) : Int +abstract class C() { + abstract fun equals(a : Any?) : Int } fun f(): Unit { diff --git a/idea/testData/checker/Bounds.jet b/idea/testData/checker/Bounds.jet index 3b3f6a41ed2..87d5cfa1579 100644 --- a/idea/testData/checker/Bounds.jet +++ b/idea/testData/checker/Bounds.jet @@ -18,10 +18,10 @@ namespace boundsWithSubstitutors { open class A {} open class B() - class CInt>, X : fun (B<Char>) : (B<Any>, B)>() : B<Any>() { // 2 errors + abstract class CInt>, X : fun (B<Char>) : (B<Any>, B)>() : B<Any>() { // 2 errors val a = B<Char>() // error - val x : fun (B<Char>) : B<Any> + abstract val x : fun (B<Char>) : B<Any> } diff --git a/idea/testData/checker/ExtensionFunctions.jet b/idea/testData/checker/ExtensionFunctions.jet index 669b51c0cbe..85b19d50dfe 100644 --- a/idea/testData/checker/ExtensionFunctions.jet +++ b/idea/testData/checker/ExtensionFunctions.jet @@ -1,5 +1,5 @@ -fun Int?.optint() : Unit -val Int?.optval : Unit +fun Int?.optint() : Unit {} +val Int?.optval : Unit = () fun T.foo(x : E, y : A) : T { y.plus(1) @@ -33,20 +33,20 @@ fun test() { val Int.abs : Int get() = if (this > 0) this else -this; -val T.foo : T +val T.foo : T fun Int.foo() = this namespace null_safety { fun parse(cmd: String): Command? { return null } - class Command() { + abstract class Command() { // fun equals(other : Any?) : Boolean - val foo : Int + abstract val foo : Int } - fun Any.equals(other : Any?) : Boolean - fun Any?.equals1(other : Any?) : Boolean + fun Any.equals(other : Any?) : Boolean = true + fun Any?.equals1(other : Any?) : Boolean = true fun main(args: Array) { diff --git a/idea/testData/checker/ForRangeConventions.jet b/idea/testData/checker/ForRangeConventions.jet index ebc71d5e462..6cbd3e3a0b4 100644 --- a/idea/testData/checker/ForRangeConventions.jet +++ b/idea/testData/checker/ForRangeConventions.jet @@ -4,65 +4,65 @@ class NotRange1() { } -class NotRange2() { - fun iterator() : Unit +abstract class NotRange2() { + abstract fun iterator() : Unit } -class ImproperIterator1 { - fun hasNext() : Boolean +abstract class ImproperIterator1 { + abstract fun hasNext() : Boolean } -class NotRange3() { - fun iterator() : ImproperIterator1 +abstract class NotRange3() { + abstract fun iterator() : ImproperIterator1 } -class ImproperIterator2 { - fun next() : Boolean +abstract class ImproperIterator2 { + abstract fun next() : Boolean } -class NotRange4() { - fun iterator() : ImproperIterator2 +abstract class NotRange4() { + abstract fun iterator() : ImproperIterator2 } -class ImproperIterator3 { - fun hasNext() : Int - fun next() : Int +abstract class ImproperIterator3 { + abstract fun hasNext() : Int + abstract fun next() : Int } -class NotRange5() { - fun iterator() : ImproperIterator3 +abstract class NotRange5() { + abstract fun iterator() : ImproperIterator3 } -class AmbiguousHasNextIterator { - fun hasNext() : Boolean +abstract class AmbiguousHasNextIterator { + abstract fun hasNext() : Boolean val hasNext : Boolean get() = false - fun next() : Int + abstract fun next() : Int } -class NotRange6() { - fun iterator() : AmbiguousHasNextIterator +abstract class NotRange6() { + abstract fun iterator() : AmbiguousHasNextIterator } -class ImproperIterator4 { +abstract class ImproperIterator4 { val hasNext : Int get() = 1 - fun next() : Int + abstract fun next() : Int } -class NotRange7() { - fun iterator() : ImproperIterator3 +abstract class NotRange7() { + abstract fun iterator() : ImproperIterator3 } -class GoodIterator { - fun hasNext() : Boolean - fun next() : Int +abstract class GoodIterator { + abstract fun hasNext() : Boolean + abstract fun next() : Int } -class Range0() { - fun iterator() : GoodIterator +abstract class Range0() { + abstract fun iterator() : GoodIterator } -class Range1() { - fun iterator() : Iterator +abstract class Range1() { + abstract fun iterator() : Iterator } fun test() { diff --git a/idea/testData/checker/FunctionReturnTypes.jet b/idea/testData/checker/FunctionReturnTypes.jet index a541589263a..4486374b84a 100644 --- a/idea/testData/checker/FunctionReturnTypes.jet +++ b/idea/testData/checker/FunctionReturnTypes.jet @@ -1,4 +1,4 @@ -fun none() +fun none() {} fun unitEmptyInfer() {} fun unitEmpty() : Unit {} diff --git a/idea/testData/checker/MultipleBounds.jet b/idea/testData/checker/MultipleBounds.jet index 126864510c1..aee719715ff 100644 --- a/idea/testData/checker/MultipleBounds.jet +++ b/idea/testData/checker/MultipleBounds.jet @@ -1,11 +1,11 @@ namespace Jet87 open class A() { - fun foo() : Int + fun foo() : Int = 1 } open class B() { - fun bar() : Double; + fun bar() : Double = 1.0; } class C() : A(), B() @@ -69,4 +69,4 @@ class Test<T> class object T : Foo, class object T : A {} -val x : Int \ No newline at end of file +val x : Int = 0 \ No newline at end of file diff --git a/idea/testData/checker/NamespaceQualified.jet b/idea/testData/checker/NamespaceQualified.jet index 2b8832aef89..e6360507d2c 100644 --- a/idea/testData/checker/NamespaceQualified.jet +++ b/idea/testData/checker/NamespaceQualified.jet @@ -22,22 +22,29 @@ val y1 = a.b ///////////////////////////////////////////////////////////////////////// -fun done(result : O) : Iteratee +fun done(result : O) : Iteratee = StrangeIterateeImpl(result) -class Iteratee { +abstract class Iteratee { abstract fun process(item : I) : Iteratee abstract val isDone : Boolean abstract val result : O abstract fun done() : O } -class Sum() : Iteratee { +class StrangeIterateeImpl(val obj: O) : Iteratee { + override fun process(item: I): Iteratee = StrangeIterateeImpl(obj) + override val isDone = true + override val result = obj + override val done = obj +} + +abstract class Sum() : Iteratee { override fun process(item : Int) : Iteratee { return foobar.done(item); } - override val isDone : Boolean - override val result : Int - override fun done() : Int + abstract override val isDone : Boolean + abstract override val result : Int + abstract override fun done() : Int } class Collection : Iterable { diff --git a/idea/testData/checker/Objects.jet b/idea/testData/checker/Objects.jet index 66f21030719..7bf4d985c94 100644 --- a/idea/testData/checker/Objects.jet +++ b/idea/testData/checker/Objects.jet @@ -60,11 +60,11 @@ namespace nestedObejcts { namespace localObjects { object A { - val x : Int + val x : Int = 0 } class Foo { - fun foo() : Int + fun foo() : Int = 1 } fun test() { diff --git a/idea/testData/checker/PrimaryConstructors.jet b/idea/testData/checker/PrimaryConstructors.jet index d453dad9602..d0a4707c60b 100644 --- a/idea/testData/checker/PrimaryConstructors.jet +++ b/idea/testData/checker/PrimaryConstructors.jet @@ -1,9 +1,9 @@ class X { - val x : Int + val x : Int } class Y() { - val x : Int + val x : Int = 2 } class Y1 { diff --git a/idea/testData/checker/Properties.jet b/idea/testData/checker/Properties.jet index 61330844bc4..b1bd354bab9 100644 --- a/idea/testData/checker/Properties.jet +++ b/idea/testData/checker/Properties.jet @@ -13,7 +13,7 @@ get() = 1 class Test() { - var a : Int + var a : Int = 111 var b : Int get() = $a; set(x) {a = x; $a = x} this(i : Int) : this() { diff --git a/idea/testData/checker/Redeclarations.jet b/idea/testData/checker/Redeclarations.jet index 4201582c728..6998ada29eb 100644 --- a/idea/testData/checker/Redeclarations.jet +++ b/idea/testData/checker/Redeclarations.jet @@ -1,6 +1,6 @@ namespace redeclarations { object A { - val x : Int + val x : Int = 0 val A = 1 } diff --git a/idea/testData/checker/infos/PropertiesWithBackingFields.jet b/idea/testData/checker/infos/PropertiesWithBackingFields.jet index 942763a1ee9..278297b6725 100644 --- a/idea/testData/checker/infos/PropertiesWithBackingFields.jet +++ b/idea/testData/checker/infos/PropertiesWithBackingFields.jet @@ -1,10 +1,10 @@ -class Test() { +abstract class Test() { abstract val x : Int abstract val x1 : Int get - abstract val x2 : Int get() = 1 + abstract val x2 : Int get() = 1 - val a : Int - val b : Int get + val a : Int + val b : Int get val c = 1 val c1 = 1 @@ -15,29 +15,30 @@ class Test() { get() { return 1 } val c4 : Int get() = 1 - val c5 : Int + val c5 : Int get() = $c5 + 1 abstract var y : Int abstract var y1 : Int get abstract var y2 : Int set abstract var y3 : Int set get - abstract var y4 : Int set get() = 1 - abstract var y5 : Int set(x) {} get() = 1 + abstract var y4 : Int set get() = 1 + abstract var y5 : Int set(x) {} get() = 1 + abstract var y6 : Int set(x) {} - var v : Int - var v1 : Int get - var v2 : Int get set - var v3 : Int get() = 1; set + var v : Int + var v1 : Int get + var v2 : Int get set + var v3 : Int get() = 1; set var v4 : Int get() = 1; set(x){} - var v5 : Int get() = 1; set(x){$v5 = x} - var v6 : Int get() = $v6 + 1; set(x){} + var v5 : Int get() = 1; set(x){$v5 = x} + var v6 : Int get() = $v6 + 1; set(x){} val v7 : Int abstract get var v8 : Int abstract get abstract set - var v9 : Int abstract set - var v10 : Int abstract get + var v9 : Int abstract set + var v10 : Int abstract get } diff --git a/idea/testData/checker/regression/Jet124.jet b/idea/testData/checker/regression/Jet124.jet index 79392a018f1..317b1438f41 100644 --- a/idea/testData/checker/regression/Jet124.jet +++ b/idea/testData/checker/regression/Jet124.jet @@ -1,4 +1,4 @@ -fun foo1() : fun (Int) : Int +fun foo1() : fun (Int) : Int = { (x: Int) => x } fun foo() { val h : fun (Int) : Int = foo1(); diff --git a/idea/testData/checker/regression/Jet183-1.jet b/idea/testData/checker/regression/Jet183-1.jet index 599560ac69f..37c72d83ef6 100644 --- a/idea/testData/checker/regression/Jet183-1.jet +++ b/idea/testData/checker/regression/Jet183-1.jet @@ -1,4 +1,4 @@ -enum class ProtocolState { +abstract enum class ProtocolState { WAITING { override fun signal() = ProtocolState.TALKING } diff --git a/idea/testData/checker/regression/Jet183.jet b/idea/testData/checker/regression/Jet183.jet index 92c5cca572b..58712e5db73 100644 --- a/idea/testData/checker/regression/Jet183.jet +++ b/idea/testData/checker/regression/Jet183.jet @@ -1,4 +1,4 @@ -enum class ProtocolState { +abstract enum class ProtocolState { WAITING { override fun signal() = ProtocolState.TALKING } diff --git a/idea/testData/checker/regression/Jet72.jet b/idea/testData/checker/regression/Jet72.jet index bcee3560ccc..d3d3272c8e3 100644 --- a/idea/testData/checker/regression/Jet72.jet +++ b/idea/testData/checker/regression/Jet72.jet @@ -2,8 +2,8 @@ import java.util.ArrayList -class Item(val room: Object) { - val name : String +abstract class Item(val room: Object) { + abstract val name : String } val items: ArrayList = ArrayList diff --git a/idea/testData/codegen/classes/classObjectMethod.jet b/idea/testData/codegen/classes/classObjectMethod.jet index 2a5d25f6213..d7d70a86d96 100644 --- a/idea/testData/codegen/classes/classObjectMethod.jet +++ b/idea/testData/codegen/classes/classObjectMethod.jet @@ -1,5 +1,5 @@ abstract open class Default { - fun defaultValue(): Int + abstract fun defaultValue(): Int } class MyInt() { diff --git a/idea/testData/codegen/classes/diamondInheritance.jet b/idea/testData/codegen/classes/diamondInheritance.jet index 63116f267b8..aefec63bfda 100644 --- a/idea/testData/codegen/classes/diamondInheritance.jet +++ b/idea/testData/codegen/classes/diamondInheritance.jet @@ -1,5 +1,5 @@ class Base() { - public var v : Int + public var v : Int = 0 } class Left() : Base() {} diff --git a/idea/testData/codegen/classes/initializerBlock.jet b/idea/testData/codegen/classes/initializerBlock.jet index 0c41f783a05..c89deeda87d 100644 --- a/idea/testData/codegen/classes/initializerBlock.jet +++ b/idea/testData/codegen/classes/initializerBlock.jet @@ -2,7 +2,7 @@ class C() { public var f: Int { - f = 610 + $f = 610 } } diff --git a/idea/testData/codegen/classes/propertyDelegation.jet b/idea/testData/codegen/classes/propertyDelegation.jet index dca646f0aef..af33786e627 100644 --- a/idea/testData/codegen/classes/propertyDelegation.jet +++ b/idea/testData/codegen/classes/propertyDelegation.jet @@ -3,7 +3,7 @@ class Base() { public val read : Int get() = 239 - public var readwrite : Int + public var readwrite : Int = 0 get() = $readwrite + 1 set(n : Int) { $readwrite = n diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 2a9fd6c98e7..767c579b744 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -72,7 +72,7 @@ public class ClassGenTest extends CodegenTestCase { } public void testAbstractMethod() throws Exception { - loadText("class Foo { abstract fun x(): String; fun y(): Int = 0 }"); + loadText("abstract class Foo { abstract fun x(): String; fun y(): Int = 0 }"); final ClassFileFactory codegens = generateClassesInFile(); final Class aClass = loadClass("Foo", codegens); diff --git a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java index f6621b37e98..dc09ab6ca26 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java @@ -125,7 +125,7 @@ public class PropertyGenTest extends CodegenTestCase { } public void testAbstractVal() throws Exception { - loadText("class Foo { public abstract val x: String }"); + loadText("abstract class Foo { public abstract val x: String }"); final ClassFileFactory codegens = generateClassesInFile(); final Class aClass = loadClass("Foo", codegens); assertNotNull(aClass.getMethod("getX"));