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