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.DescriptorFactory;
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.JetType;
030    import org.jetbrains.jet.lang.types.TypeConstructor;
031    import org.jetbrains.jet.lang.types.TypeConstructorImpl;
032    import org.jetbrains.jet.lang.types.TypeUtils;
033    import org.jetbrains.jet.renderer.DescriptorRenderer;
034    
035    import java.util.ArrayList;
036    import java.util.Collection;
037    import java.util.Collections;
038    import java.util.List;
039    
040    public abstract class MutableClassDescriptorLite extends ClassDescriptorBase {
041    
042        private List<AnnotationDescriptor> annotations = Lists.newArrayList();
043    
044        private List<TypeParameterDescriptor> typeParameters;
045        private Collection<JetType> supertypes = Lists.newArrayList();
046    
047        private TypeConstructor typeConstructor;
048    
049        private Modality modality;
050        private Visibility visibility;
051    
052        private final boolean isInner;
053    
054        private MutableClassDescriptorLite classObjectDescriptor;
055        private JetType classObjectType;
056        private final ClassKind kind;
057    
058        private JetScope scopeForMemberLookup;
059        private JetScope innerClassesScope;
060    
061        private ReceiverParameterDescriptor implicitReceiver;
062    
063        public MutableClassDescriptorLite(@NotNull DeclarationDescriptor containingDeclaration,
064                                          @NotNull Name name,
065                                          @NotNull ClassKind kind,
066                                          boolean isInner
067        ) {
068            super(containingDeclaration, name);
069            this.kind = kind;
070            this.isInner = isInner;
071        }
072    
073        @NotNull
074        @Override
075        public TypeConstructor getTypeConstructor() {
076            return typeConstructor;
077        }
078    
079        public void setScopeForMemberLookup(JetScope scopeForMemberLookup) {
080            this.scopeForMemberLookup = scopeForMemberLookup;
081            this.innerClassesScope = new InnerClassesScopeWrapper(scopeForMemberLookup);
082        }
083    
084        public void createTypeConstructor() {
085            assert typeConstructor == null : typeConstructor;
086            this.typeConstructor = new TypeConstructorImpl(
087                    this,
088                    Collections.<AnnotationDescriptor>emptyList(), // TODO : pass annotations from the class?
089                    !getModality().isOverridable(),
090                    getName().asString(),
091                    typeParameters,
092                    supertypes);
093        }
094    
095        private WritableScope getScopeForMemberLookupAsWritableScope() {
096            // hack
097            return (WritableScope) scopeForMemberLookup;
098        }
099    
100    
101        @NotNull
102        public JetScope getScopeForMemberLookup() {
103            return scopeForMemberLookup;
104        }
105    
106        @Override
107        public JetType getClassObjectType() {
108            if (classObjectType == null && classObjectDescriptor != null) {
109                classObjectType = classObjectDescriptor.getDefaultType();
110            }
111            return classObjectType;
112        }
113    
114        @NotNull
115        @Override
116        public ClassKind getKind() {
117            return kind;
118        }
119    
120        public void setModality(Modality modality) {
121            this.modality = modality;
122        }
123    
124        public void setVisibility(Visibility visibility) {
125            this.visibility = visibility;
126        }
127    
128        @Override
129        @NotNull
130        public Modality getModality() {
131            return modality;
132        }
133    
134        @NotNull
135        @Override
136        public Visibility getVisibility() {
137            return visibility;
138        }
139    
140        @Override
141        public boolean isInner() {
142            return isInner;
143        }
144    
145        public Collection<JetType> getSupertypes() {
146            return supertypes;
147        }
148    
149        public void setSupertypes(@NotNull Collection<JetType> supertypes) {
150            this.supertypes = supertypes;
151        }
152    
153    
154        @Override
155        @Nullable
156        public MutableClassDescriptorLite getClassObjectDescriptor() {
157            return classObjectDescriptor;
158        }
159    
160    
161    
162        @NotNull
163        @Override
164        public JetScope getUnsubstitutedInnerClassesScope() {
165            return innerClassesScope;
166        }
167    
168    
169        public void addSupertype(@NotNull JetType supertype) {
170            assert !supertype.isError() : "Error types must be filtered out in DescriptorResolver";
171            if (TypeUtils.getClassDescriptor(supertype) != null) {
172                // See the Errors.SUPERTYPE_NOT_A_CLASS_OR_TRAIT
173                supertypes.add(supertype);
174            }
175        }
176    
177        public void setTypeParameterDescriptors(List<TypeParameterDescriptor> typeParameters) {
178            if (this.typeParameters != null) {
179                throw new IllegalStateException();
180            }
181            this.typeParameters = new ArrayList<TypeParameterDescriptor>();
182            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
183                this.typeParameters.add(typeParameterDescriptor);
184            }
185        }
186    
187        public void lockScopes() {
188            getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
189            if (classObjectDescriptor != null) {
190                classObjectDescriptor.lockScopes();
191            }
192        }
193    
194        @NotNull
195        @Override
196        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
197            if (implicitReceiver == null) {
198                implicitReceiver = DescriptorFactory.createLazyReceiverParameterDescriptor(this);
199            }
200            return implicitReceiver;
201        }
202    
203        @Override
204        public String toString() {
205            try {
206                return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
207            } catch (Throwable e) {
208                return super.toString();
209            }
210        }
211    
212        @Override
213        public List<AnnotationDescriptor> getAnnotations() {
214            return annotations;
215        }
216    
217        public void setAnnotations(List<AnnotationDescriptor> annotations) {
218            this.annotations = annotations;
219        }
220    
221        private NamespaceLikeBuilder builder = null;
222        public NamespaceLikeBuilder getBuilder() {
223            if (builder == null) {
224                builder = new NamespaceLikeBuilderDummy() {
225                    @NotNull
226                    @Override
227                    public DeclarationDescriptor getOwnerForChildren() {
228                        return MutableClassDescriptorLite.this;
229                    }
230    
231                    @Override
232                    public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
233                        getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor);
234                    }
235    
236                    @Override
237                    public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
238                        getScopeForMemberLookupAsWritableScope().addObjectDescriptor(objectDescriptor);
239                    }
240    
241                    @Override
242                    public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
243                        getScopeForMemberLookupAsWritableScope().addFunctionDescriptor(functionDescriptor);
244                    }
245    
246                    @Override
247                    public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
248                        getScopeForMemberLookupAsWritableScope().addPropertyDescriptor(propertyDescriptor);
249                    }
250    
251                    @Override
252                    public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
253                        if (getKind().isObject() || isInner()) {
254                            return ClassObjectStatus.NOT_ALLOWED;
255                        }
256    
257                        if (MutableClassDescriptorLite.this.classObjectDescriptor != null) {
258                            return ClassObjectStatus.DUPLICATE;
259                        }
260    
261                        assert classObjectDescriptor.getKind() == ClassKind.CLASS_OBJECT;
262                        MutableClassDescriptorLite.this.classObjectDescriptor = classObjectDescriptor;
263    
264                        return ClassObjectStatus.OK;
265                    }
266                };
267            }
268    
269            return builder;
270        }
271    }