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