001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.jet.lang.descriptors.impl;
018
019import com.google.common.collect.Lists;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022import org.jetbrains.jet.lang.descriptors.*;
023import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
024import org.jetbrains.jet.lang.resolve.DescriptorResolver;
025import org.jetbrains.jet.lang.resolve.name.Name;
026import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
027import org.jetbrains.jet.lang.resolve.scopes.JetScope;
028import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
029import org.jetbrains.jet.lang.types.*;
030import org.jetbrains.jet.renderer.DescriptorRenderer;
031
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.Collections;
035import java.util.List;
036
037public abstract class MutableClassDescriptorLite extends ClassDescriptorBase {
038
039    private List<AnnotationDescriptor> annotations = Lists.newArrayList();
040
041    private List<TypeParameterDescriptor> typeParameters;
042    private Collection<JetType> supertypes = Lists.newArrayList();
043
044    private TypeConstructor typeConstructor;
045
046    private Modality modality;
047    private Visibility visibility;
048
049    private final boolean isInner;
050
051    private MutableClassDescriptorLite classObjectDescriptor;
052    private JetType classObjectType;
053    private final ClassKind kind;
054
055    private JetScope scopeForMemberLookup;
056    private JetScope innerClassesScope;
057
058    private ReceiverParameterDescriptor implicitReceiver;
059
060    private Name name;
061    private final DeclarationDescriptor containingDeclaration;
062
063    public MutableClassDescriptorLite(@NotNull DeclarationDescriptor containingDeclaration,
064                                      @NotNull ClassKind kind,
065                                      boolean isInner
066    ) {
067        this.containingDeclaration = containingDeclaration;
068        this.kind = kind;
069        this.isInner = isInner;
070    }
071
072    @NotNull
073    @Override
074    public DeclarationDescriptor getContainingDeclaration() {
075        return containingDeclaration;
076    }
077
078    @NotNull
079    @Override
080    public Name getName() {
081        return name;
082    }
083
084    public void setName(@NotNull Name name) {
085        assert this.name == null : this.name;
086        this.name = name;
087    }
088
089    @NotNull
090    @Override
091    public DeclarationDescriptor getOriginal() {
092        return this;
093    }
094
095    @NotNull
096    @Override
097    public TypeConstructor getTypeConstructor() {
098        return typeConstructor;
099    }
100
101    public void setScopeForMemberLookup(JetScope scopeForMemberLookup) {
102        this.scopeForMemberLookup = scopeForMemberLookup;
103        this.innerClassesScope = new InnerClassesScopeWrapper(scopeForMemberLookup);
104    }
105
106    public void createTypeConstructor() {
107        assert typeConstructor == null : typeConstructor;
108        this.typeConstructor = new TypeConstructorImpl(
109                this,
110                Collections.<AnnotationDescriptor>emptyList(), // TODO : pass annotations from the class?
111                !getModality().isOverridable(),
112                getName().asString(),
113                typeParameters,
114                supertypes);
115    }
116
117    private WritableScope getScopeForMemberLookupAsWritableScope() {
118        // hack
119        return (WritableScope) scopeForMemberLookup;
120    }
121
122
123    @NotNull
124    public JetScope getScopeForMemberLookup() {
125        return scopeForMemberLookup;
126    }
127
128    @Override
129    public JetType getClassObjectType() {
130        if (classObjectType == null && classObjectDescriptor != null) {
131            classObjectType = classObjectDescriptor.getDefaultType();
132        }
133        return classObjectType;
134    }
135
136    @NotNull
137    @Override
138    public ClassKind getKind() {
139        return kind;
140    }
141
142    public void setModality(Modality modality) {
143        this.modality = modality;
144    }
145
146    public void setVisibility(Visibility visibility) {
147        this.visibility = visibility;
148    }
149
150    @Override
151    @NotNull
152    public Modality getModality() {
153        return modality;
154    }
155
156    @NotNull
157    @Override
158    public Visibility getVisibility() {
159        return visibility;
160    }
161
162    @Override
163    public boolean isInner() {
164        return isInner;
165    }
166
167    public Collection<JetType> getSupertypes() {
168        return supertypes;
169    }
170
171    public void setSupertypes(@NotNull Collection<JetType> supertypes) {
172        this.supertypes = supertypes;
173    }
174
175
176    @Override
177    @Nullable
178    public MutableClassDescriptorLite getClassObjectDescriptor() {
179        return classObjectDescriptor;
180    }
181
182
183
184    @NotNull
185    @Override
186    public JetScope getUnsubstitutedInnerClassesScope() {
187        return innerClassesScope;
188    }
189
190
191    public void addSupertype(@NotNull JetType supertype) {
192        assert !ErrorUtils.isErrorType(supertype) : "Error types must be filtered out in DescriptorResolver";
193        if (TypeUtils.getClassDescriptor(supertype) != null) {
194            // See the Errors.SUPERTYPE_NOT_A_CLASS_OR_TRAIT
195            supertypes.add(supertype);
196        }
197    }
198
199    public void setTypeParameterDescriptors(List<TypeParameterDescriptor> typeParameters) {
200        if (this.typeParameters != null) {
201            throw new IllegalStateException();
202        }
203        this.typeParameters = new ArrayList<TypeParameterDescriptor>();
204        for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
205            this.typeParameters.add(typeParameterDescriptor);
206        }
207    }
208
209    public void lockScopes() {
210        getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
211        if (classObjectDescriptor != null) {
212            classObjectDescriptor.lockScopes();
213        }
214    }
215
216    @NotNull
217    @Override
218    public ReceiverParameterDescriptor getThisAsReceiverParameter() {
219        if (implicitReceiver == null) {
220            implicitReceiver = DescriptorResolver.createLazyReceiverParameterDescriptor(this);
221        }
222        return implicitReceiver;
223    }
224
225    @Override
226    public String toString() {
227        try {
228            return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
229        } catch (Throwable e) {
230            return super.toString();
231        }
232    }
233
234    @Override
235    public List<AnnotationDescriptor> getAnnotations() {
236        return annotations;
237    }
238
239    public void setAnnotations(List<AnnotationDescriptor> annotations) {
240        this.annotations = annotations;
241    }
242
243    private NamespaceLikeBuilder builder = null;
244    public NamespaceLikeBuilder getBuilder() {
245        if (builder == null) {
246            builder = new NamespaceLikeBuilderDummy() {
247                @NotNull
248                @Override
249                public DeclarationDescriptor getOwnerForChildren() {
250                    return MutableClassDescriptorLite.this;
251                }
252
253                @Override
254                public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
255                    getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor);
256                }
257
258                @Override
259                public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
260                    getScopeForMemberLookupAsWritableScope().addObjectDescriptor(objectDescriptor);
261                }
262
263                @Override
264                public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
265                    getScopeForMemberLookupAsWritableScope().addFunctionDescriptor(functionDescriptor);
266                }
267
268                @Override
269                public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
270                    getScopeForMemberLookupAsWritableScope().addPropertyDescriptor(propertyDescriptor);
271                }
272
273                @Override
274                public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
275                    if (getKind().isObject() || isInner()) {
276                        return ClassObjectStatus.NOT_ALLOWED;
277                    }
278
279                    if (MutableClassDescriptorLite.this.classObjectDescriptor != null) {
280                        return ClassObjectStatus.DUPLICATE;
281                    }
282
283                    assert classObjectDescriptor.getKind() == ClassKind.CLASS_OBJECT;
284                    MutableClassDescriptorLite.this.classObjectDescriptor = classObjectDescriptor;
285
286                    return ClassObjectStatus.OK;
287                }
288            };
289        }
290
291        return builder;
292    }
293}