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    
017    package org.jetbrains.jet.lang.descriptors.impl;
018    
019    import com.google.common.collect.Lists;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.lang.descriptors.*;
023    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
024    import org.jetbrains.jet.lang.resolve.DescriptorResolver;
025    import org.jetbrains.jet.lang.resolve.name.Name;
026    import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
027    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
028    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
029    import org.jetbrains.jet.lang.types.*;
030    import org.jetbrains.jet.renderer.DescriptorRenderer;
031    
032    import java.util.ArrayList;
033    import java.util.Collection;
034    import java.util.Collections;
035    import java.util.List;
036    
037    public 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    }