From ed16a29a5f7f40d4973fa63adc36150823f5f126 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 2 Jun 2011 20:56:01 +0400 Subject: [PATCH] JET-76 Support object declarations JET-62 Support object-expressions No tests yet --- idea/src/org/jetbrains/jet/JetNodeTypes.java | 1 + .../annotations/JetLineMarkerProvider.java | 20 +++ .../jet/lang/parsing/JetParsing.java | 2 + .../jet/lang/psi/JetClassOrObject.java | 9 ++ .../jet/lang/psi/JetObjectDeclaration.java | 45 ++++++ .../lang/psi/JetObjectDeclarationName.java | 14 ++ .../jetbrains/jet/lang/psi/JetVisitor.java | 4 + .../jet/lang/resolve/BindingContext.java | 5 +- .../jet/lang/resolve/BindingTraceContext.java | 4 +- .../lang/resolve/ClassDescriptorResolver.java | 26 +++- .../jet/lang/resolve/TopDownAnalyzer.java | 141 +++++++++++++----- .../jet/lang/types/JetTypeInferrer.java | 10 ++ .../jet/resolve/DescriptorRenderer.java | 24 ++- .../tests/org/jetbrains/jet/JetTestUtils.java | 2 +- 14 files changed, 261 insertions(+), 46 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclarationName.java diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index 35b1e95998d..2e34e9805c4 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -17,6 +17,7 @@ public interface JetNodeTypes { JetNodeType EXTENSION = new JetNodeType("EXTENSION", JetExtension.class); JetNodeType TYPEDEF = new JetNodeType("TYPEDEF", JetTypedef.class); JetNodeType OBJECT_DECLARATION = new JetNodeType("OBJECT_DECLARATION", JetObjectDeclaration.class); + JetNodeType OBJECT_DECLARATION_NAME = new JetNodeType("OBJECT_DECLARATION_NAME", JetObjectDeclarationName.class); JetNodeType CLASS_OBJECT = new JetNodeType("CLASS_OBJECT", JetClassObject.class); JetNodeType CONSTRUCTOR = new JetNodeType("CONSTRUCTOR", JetConstructor.class); diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java b/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java index 3322c3ec271..7aa3127370f 100644 --- a/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java +++ b/idea/src/org/jetbrains/jet/lang/annotations/JetLineMarkerProvider.java @@ -172,6 +172,26 @@ public class JetLineMarkerProvider implements LineMarkerProvider { } ); } + + if (element instanceof JetObjectDeclaration) { + JetObjectDeclaration jetObjectDeclaration = (JetObjectDeclaration) element; + return new LineMarkerInfo( + jetObjectDeclaration, jetObjectDeclaration.getTextOffset(), Icons.ANONYMOUS_CLASS_ICON, Pass.UPDATE_ALL, + new Function() { + @Override + public String fun(JetObjectDeclaration jetObjectDeclaration) { + ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(jetObjectDeclaration); + return DescriptorRenderer.HTML.renderAsObject(classDescriptor); + } + }, + new GutterIconNavigationHandler() { + @Override + public void navigate(MouseEvent e, JetObjectDeclaration elt) { + } + } + ); + } + return null; } diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index e96b63be26d..89658c76d97 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -607,7 +607,9 @@ public class JetParsing extends AbstractJetParsing { advance(); // OBJECT_KEYWORD if (declaration) { + PsiBuilder.Marker propertyDeclaration = mark(); expect(IDENTIFIER, "Expecting object name", TokenSet.create(LBRACE)); + propertyDeclaration.done(OBJECT_DECLARATION_NAME); } else { if (at(IDENTIFIER)) { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClassOrObject.java b/idea/src/org/jetbrains/jet/lang/psi/JetClassOrObject.java index 25efc2e3f61..ab66e28be2c 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClassOrObject.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClassOrObject.java @@ -16,4 +16,13 @@ public interface JetClassOrObject { @NotNull List getDelegationSpecifiers(); + + @NotNull + List getAnonymousInitializers(); + + // Objects always "have" a primary constructor + boolean hasPrimaryConstructor(); + + @Nullable + String getName(); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java index a4d22123a01..71c7c17caba 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java @@ -1,6 +1,9 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; @@ -16,6 +19,29 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas super(node); } + @Override + public String getName() { + JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); + return nameAsDeclaration == null ? "" : nameAsDeclaration.getName(); + } + + @Override + public PsiElement getNameIdentifier() { + JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); + return nameAsDeclaration == null ? null : nameAsDeclaration.getNameIdentifier(); + } + + @Override + public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { + JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); + return nameAsDeclaration == null ? null : nameAsDeclaration.setName(name); + } + + @Nullable + public JetObjectDeclarationName getNameAsDeclaration() { + return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME); + } + @Override @Nullable public JetDelegationSpecifierList getDelegationSpecifierList() { @@ -29,6 +55,20 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas return list != null ? list.getDelegationSpecifiers() : Collections.emptyList(); } + @Override + @NotNull + public List getAnonymousInitializers() { + JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY); + if (body == null) return Collections.emptyList(); + + return body.getAnonymousInitializers(); + } + + @Override + public boolean hasPrimaryConstructor() { + return true; + } + @Override @NotNull public List getDeclarations() { @@ -37,4 +77,9 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas return body.getDeclarations(); } + + @Override + public void accept(JetVisitor visitor) { + visitor.visitObjectDeclaration(this); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclarationName.java b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclarationName.java new file mode 100644 index 00000000000..f64da39750e --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclarationName.java @@ -0,0 +1,14 @@ +package org.jetbrains.jet.lang.psi; + +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public class JetObjectDeclarationName extends JetNamedDeclaration { + + public JetObjectDeclarationName(@NotNull ASTNode node) { + super(node); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java index 746b6557f14..1a1d2d8c695 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java @@ -393,4 +393,8 @@ public class JetVisitor extends PsiElementVisitor { public void visitDecomposerPattern(JetDecomposerPattern pattern) { visitPattern(pattern); } + + public void visitObjectDeclaration(JetObjectDeclaration declaration) { + visitNamedDeclaration(declaration); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 86d38107773..ddd753afb7c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -1,11 +1,10 @@ package org.jetbrains.jet.lang.resolve; import com.intellij.psi.PsiElement; -import org.jetbrains.jet.codegen.ClassCodegen; import org.jetbrains.jet.lang.JetDiagnostic; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.JetType; import java.util.Collection; @@ -17,7 +16,7 @@ public interface BindingContext { DeclarationDescriptor getDeclarationDescriptor(PsiElement declaration); NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration); - ClassDescriptor getClassDescriptor(JetClass declaration); + ClassDescriptor getClassDescriptor(JetClassOrObject declaration); TypeParameterDescriptor getTypeParameterDescriptor(JetTypeParameter declaration); FunctionDescriptor getFunctionDescriptor(JetFunction declaration); ConstructorDescriptor getConstructorDescriptor(JetElement declaration); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index 675f0faefd5..120f284f37e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -165,8 +165,8 @@ public class BindingTraceContext implements BindingContext, BindingTrace { } @Override - public ClassDescriptor getClassDescriptor(JetClass declaration) { - return (ClassDescriptor) declarationsToDescriptors.get(declaration); + public ClassDescriptor getClassDescriptor(JetClassOrObject declaration) { + return (ClassDescriptor) declarationsToDescriptors.get((JetDeclaration) declaration); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 26d5a4c7436..a4c71c2949a 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -148,7 +148,7 @@ public class ClassDescriptorResolver { // TODO : Bounds from with } - public void resolveSupertypes(@NotNull JetClass jetClass, @NotNull MutableClassDescriptor descriptor) { + public void resolveSupertypes(@NotNull JetClassOrObject jetClass, @NotNull MutableClassDescriptor descriptor) { List delegationSpecifiers = jetClass.getDelegationSpecifiers(); // TODO : assuming that the hierarchy is acyclic Collection superclasses = delegationSpecifiers.isEmpty() @@ -355,6 +355,30 @@ public class ClassDescriptorResolver { return variableDescriptor; } + public PropertyDescriptor resolveObjectDeclarationAsPropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, JetObjectDeclaration objectDeclaration, @NotNull ClassDescriptor classDescriptor) { + JetModifierList modifierList = objectDeclaration.getModifierList(); + PropertyDescriptor propertyDescriptor = new PropertyDescriptor( + containingDeclaration, + AnnotationResolver.INSTANCE.resolveAnnotations(modifierList), + resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts + false, + null, + JetPsiUtil.safeName(objectDeclaration.getName()), + null, + classDescriptor.getDefaultType()); + + propertyDescriptor.initialize( + Collections.emptyList(), + null, // TODO : is it really OK? + null); + + JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration(); + if (nameAsDeclaration != null) { + trace.recordDeclarationResolution(nameAsDeclaration, propertyDescriptor); + } + return propertyDescriptor; + } + @NotNull public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index dd650a38589..75f033a2b9d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -24,6 +24,7 @@ import java.util.*; 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(); @@ -36,11 +37,11 @@ public class TopDownAnalyzer { private final JetSemanticServices semanticServices; private final ClassDescriptorResolver classDescriptorResolver; - private final BindingTraceContext trace; + private final BindingTrace trace; private final BindingTraceAdapter traceForConstructors; private final BindingTraceAdapter traceForMembers; - public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTraceContext bindingTrace) { + public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTrace bindingTrace) { this.semanticServices = semanticServices; this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(bindingTrace); this.trace = bindingTrace; @@ -53,7 +54,7 @@ public class TopDownAnalyzer { if (expression instanceof JetSimpleNameExpression) { JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression; if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { - if (!trace.hasBackingField((PropertyDescriptor) descriptor)) { + if (!trace.getBindingContext().hasBackingField((PropertyDescriptor) descriptor)) { TopDownAnalyzer.this.trace.getErrorHandler().genericError(expression.getNode(), "This property does not have a backing field"); } } @@ -83,14 +84,46 @@ public class TopDownAnalyzer { process(outerScope, standardLibraryNamespace, namespace.getDeclarations()); } - public void process(@NotNull WritableScope outerScope, NamespaceLike owner, @NotNull List declarations) { + public void processObject(@NotNull JetScope outerScope, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetObjectDeclaration object) { +// objects.put(object, mutableClassDescriptor); +// WritableScopeImpl writableScope = new WritableScopeImpl(outerScope, outerScope.getContainingDeclaration(), trace.getErrorHandler()); + process(outerScope, new NamespaceLike.Adapter(containingDeclaration) { + + @Override + public NamespaceDescriptorImpl getNamespace(String name) { + throw new UnsupportedOperationException(); + } + + @Override + public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { + throw new UnsupportedOperationException(); + } + + @Override + public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) { + + } + + @Override + public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { + throw new UnsupportedOperationException(); + } + + @Override + public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { + + } + }, Collections.singletonList(object)); + } + + public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes createTypeConstructors(); // create type constructors for classes and generic parameters resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) checkGenericBoundsInClassHeaders(); // For the types resolved so far - resolveFunctionAndPropertyHeaders(declarations); // Constructor headers are resolved as well + resolveFunctionAndPropertyHeaders(); // Constructor headers are resolved as well resolveBehaviorDeclarationBodies(); } @@ -131,16 +164,32 @@ public class TopDownAnalyzer { @Override public void visitClass(JetClass klass) { + visitClassOrObject(klass, (Map) classes, owner, outerScope); + } + + @Override + public void visitObjectDeclaration(JetObjectDeclaration declaration) { + MutableClassDescriptor mutableClassDescriptor = visitClassOrObject(declaration, (Map) objects, owner, outerScope); + ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(mutableClassDescriptor, Collections.emptyList(), true); + constructorDescriptor.initialize(Collections.emptyList()); + // TODO : make the constructor private? + mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor); + trace.recordDeclarationResolution(declaration, mutableClassDescriptor); + } + + private MutableClassDescriptor visitClassOrObject(JetClassOrObject declaration, Map map, NamespaceLike owner, JetScope outerScope) { MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(trace, owner, outerScope); - mutableClassDescriptor.setName(JetPsiUtil.safeName(klass.getName())); + mutableClassDescriptor.setName(JetPsiUtil.safeName(declaration.getName())); owner.addClassifierDescriptor(mutableClassDescriptor); - classes.put(klass, mutableClassDescriptor); - declaringScopes.put(klass, outerScope); + map.put(declaration, mutableClassDescriptor); + declaringScopes.put((JetDeclaration) declaration, outerScope); JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution(); - collectNamespacesAndClassifiers(classScope, mutableClassDescriptor, klass.getDeclarations()); + collectNamespacesAndClassifiers(classScope, mutableClassDescriptor, declaration.getDeclarations()); + + return mutableClassDescriptor; } @Override @@ -156,6 +205,7 @@ public class TopDownAnalyzer { } } + private void processImports(@NotNull JetNamespace namespace, @NotNull WriteThroughScope namespaceScope, @NotNull JetScope outerScope) { List importDirectives = namespace.getImportDirectives(); for (JetImportDirective importDirective : importDirectives) { @@ -223,6 +273,11 @@ public class TopDownAnalyzer { classDescriptorResolver.resolveGenericBounds(jetClass, descriptor); classDescriptorResolver.resolveSupertypes(jetClass, descriptor); } + for (Map.Entry entry : objects.entrySet()) { + JetClassOrObject jetClass = entry.getKey(); + MutableClassDescriptor descriptor = entry.getValue(); + classDescriptorResolver.resolveSupertypes(jetClass, descriptor); + } } private void checkGenericBoundsInClassHeaders() { @@ -230,14 +285,14 @@ public class TopDownAnalyzer { JetClass jetClass = entry.getKey(); for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { - JetType type = trace.resolveTypeReference(delegationSpecifier.getTypeReference()); + JetType type = trace.getBindingContext().resolveTypeReference(delegationSpecifier.getTypeReference()); classDescriptorResolver.checkBounds(delegationSpecifier.getTypeReference(), type); } for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) { JetTypeReference extendsBound = jetTypeParameter.getExtendsBound(); if (extendsBound != null) { - JetType type = trace.resolveTypeReference(extendsBound); + JetType type = trace.getBindingContext().resolveTypeReference(extendsBound); classDescriptorResolver.checkBounds(extendsBound, type); } } @@ -247,17 +302,17 @@ public class TopDownAnalyzer { } - private void resolveFunctionAndPropertyHeaders(@NotNull List declarations) { + private void resolveFunctionAndPropertyHeaders() { for (Map.Entry entry : namespaceScopes.entrySet()) { JetNamespace namespace = entry.getKey(); - final WritableScope namespaceScope = entry.getValue(); - final NamespaceLike namespaceDescriptor = namespaceDescriptors.get(namespace); + WritableScope namespaceScope = entry.getValue(); + NamespaceLike namespaceDescriptor = namespaceDescriptors.get(namespace); resolveFunctionAndPropertyHeaders(namespace.getDeclarations(), namespaceScope, namespaceDescriptor); } for (Map.Entry entry : classes.entrySet()) { JetClass jetClass = entry.getKey(); - final MutableClassDescriptor classDescriptor = entry.getValue(); + MutableClassDescriptor classDescriptor = entry.getValue(); resolveFunctionAndPropertyHeaders(jetClass.getDeclarations(), classDescriptor.getScopeForMemberResolution(), classDescriptor); processPrimaryConstructor(classDescriptor, jetClass); @@ -267,6 +322,12 @@ public class TopDownAnalyzer { // TODO : Constructors } + for (Map.Entry entry : objects.entrySet()) { + JetObjectDeclaration object = entry.getKey(); + MutableClassDescriptor classDescriptor = entry.getValue(); + + resolveFunctionAndPropertyHeaders(object.getDeclarations(), classDescriptor.getScopeForMemberResolution(), classDescriptor); + } // TODO : Extensions } @@ -289,6 +350,12 @@ public class TopDownAnalyzer { properties.put(property, propertyDescriptor); declaringScopes.put(property, scope); } + + @Override + public void visitObjectDeclaration(JetObjectDeclaration declaration) { + PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(namespaceLike, declaration, objects.get(declaration)); + namespaceLike.addPropertyDescriptor(propertyDescriptor); + } }); } } @@ -374,7 +441,7 @@ public class TopDownAnalyzer { JetClass jetClass = entry.getKey(); if (!jetClass.hasPrimaryConstructor()) { for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { - if (trace.hasBackingField(propertyDescriptor)) { + if (trace.getBindingContext().hasBackingField(propertyDescriptor)) { PsiElement nameIdentifier = jetClass.getNameIdentifier(); if (nameIdentifier != null) { trace.getErrorHandler().genericError(nameIdentifier.getNode(), @@ -406,7 +473,7 @@ public class TopDownAnalyzer { if (delegateExpression != null) { JetScope scope = scopeForConstructor == null ? descriptor.getScopeForMemberResolution() : scopeForConstructor; JetType type = typeInferrer.getType(scope, delegateExpression, false); - JetType supertype = trace.resolveTypeReference(specifier.getTypeReference()); + JetType supertype = trace.getBindingContext().resolveTypeReference(specifier.getTypeReference()); if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible? trace.getErrorHandler().typeMismatch(delegateExpression, supertype, type); } @@ -431,7 +498,7 @@ public class TopDownAnalyzer { @Override public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { - JetType supertype = trace.resolveTypeReference(specifier.getTypeReference()); + JetType supertype = trace.getBindingContext().resolveTypeReference(specifier.getTypeReference()); if (supertype != null) { DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { @@ -463,23 +530,27 @@ public class TopDownAnalyzer { private void resolveAnonymousInitializers() { for (Map.Entry entry : classes.entrySet()) { - JetClass jetClass = entry.getKey(); - MutableClassDescriptor classDescriptor = entry.getValue(); + resolveAnonymousInitializers(entry.getKey(), entry.getValue()); + } + for (Map.Entry entry : objects.entrySet()) { + resolveAnonymousInitializers(entry.getKey(), entry.getValue()); + } + } - List anonymousInitializers = jetClass.getAnonymousInitializers(); - if (jetClass.hasPrimaryConstructor()) { - ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); - assert primaryConstructor != null; - final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); - JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow - for (JetClassInitializer anonymousInitializer : anonymousInitializers) { - typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true); - } + private void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) { + List anonymousInitializers = jetClassOrObject.getAnonymousInitializers(); + if (jetClassOrObject.hasPrimaryConstructor()) { + ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); + assert primaryConstructor != null; + final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true); + JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow + for (JetClassInitializer anonymousInitializer : anonymousInitializers) { + typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), true); } - else { - for (JetClassInitializer anonymousInitializer : anonymousInitializers) { - trace.getErrorHandler().genericError(anonymousInitializer.getNode(), "Anonymous initializers are only allowed in the presence of a primary constructor"); - } + } + else { + for (JetClassInitializer anonymousInitializer : anonymousInitializers) { + trace.getErrorHandler().genericError(anonymousInitializer.getNode(), "Anonymous initializers are only allowed in the presence of a primary constructor"); } } } @@ -574,7 +645,7 @@ public class TopDownAnalyzer { constructorScope.setThisType(descriptor.getContainingDeclaration().getDefaultType()); for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getUnsubstitutedValueParameters()) { - JetParameter parameter = (JetParameter) trace.getDeclarationPsiElement(valueParameterDescriptor); + JetParameter parameter = (JetParameter) trace.getBindingContext().getDeclarationPsiElement(valueParameterDescriptor); if (parameter.getValOrVarNode() == null || !primary) { constructorScope.addVariableDescriptor(valueParameterDescriptor); } @@ -664,7 +735,7 @@ public class TopDownAnalyzer { } JetExpression initializer = property.getInitializer(); - if (!property.isVar() && initializer != null && !trace.hasBackingField(propertyDescriptor)) { + if (!property.isVar() && initializer != null && !trace.getBindingContext().hasBackingField(propertyDescriptor)) { trace.getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no setter and no backing field either"); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 359cfec1ea5..bbbe6269c2b 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -731,6 +731,16 @@ public class JetTypeInferrer { return namespace.getNamespaceType(); } + @Override + public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { + TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, trace); + topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), expression.getObjectDeclaration()); + ClassDescriptor classDescriptor = trace.getBindingContext().getClassDescriptor(expression.getObjectDeclaration()); + if (classDescriptor != null) { + result = classDescriptor.getDefaultType(); + } + } + @Override public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { if (preferBlock && !expression.hasParameterSpecification()) { diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index bf6596bda56..cdd21b45eea 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -47,7 +47,7 @@ public class DescriptorRenderer { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private final DeclarationDescriptorVisitor rootVisitor = new RenderDeclarationDescriptorVisitor(); + private final RenderDeclarationDescriptorVisitor rootVisitor = new RenderDeclarationDescriptorVisitor(); private final DeclarationDescriptorVisitor subVisitor = new RenderDeclarationDescriptorVisitor() { @Override @@ -80,12 +80,23 @@ public class DescriptorRenderer { if (declarationDescriptor == null) return lt() + "null>"; StringBuilder stringBuilder = new StringBuilder(); declarationDescriptor.accept(rootVisitor, stringBuilder); - stringBuilder.append(" " + renderMessage("defined in") + " "); + appendDefinedIn(declarationDescriptor, stringBuilder); + return stringBuilder.toString(); + } + + private void appendDefinedIn(DeclarationDescriptor declarationDescriptor, StringBuilder stringBuilder) { + stringBuilder.append(" ").append(renderMessage("defined in")).append(" "); final DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration(); if (containingDeclaration != null) { renderFullyQualifiedName(containingDeclaration, stringBuilder); } + } + + public String renderAsObject(@NotNull ClassDescriptor classDescriptor) { + StringBuilder stringBuilder = new StringBuilder(); + rootVisitor.renderClassDescriptor(classDescriptor, stringBuilder, "object"); + appendDefinedIn(classDescriptor, stringBuilder); return stringBuilder.toString(); } @@ -219,7 +230,13 @@ public class DescriptorRenderer { @Override public Void visitClassDescriptor(ClassDescriptor descriptor, StringBuilder builder) { - builder.append(renderKeyword("class")).append(" "); + String keyword = "class"; + renderClassDescriptor(descriptor, builder, keyword); + return super.visitClassDescriptor(descriptor, builder); + } + + public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) { + builder.append(renderKeyword(keyword)).append(" "); renderName(descriptor, builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); Collection supertypes = descriptor.getTypeConstructor().getSupertypes(); @@ -233,7 +250,6 @@ public class DescriptorRenderer { } } } - return super.visitClassDescriptor(descriptor, builder); } protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) { diff --git a/idea/tests/org/jetbrains/jet/JetTestUtils.java b/idea/tests/org/jetbrains/jet/JetTestUtils.java index c707ac6cdad..2d25eb2326c 100644 --- a/idea/tests/org/jetbrains/jet/JetTestUtils.java +++ b/idea/tests/org/jetbrains/jet/JetTestUtils.java @@ -94,7 +94,7 @@ public class JetTestUtils { } @Override - public ClassDescriptor getClassDescriptor(JetClass declaration) { + public ClassDescriptor getClassDescriptor(JetClassOrObject declaration) { throw new UnsupportedOperationException(); // TODO }