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.Sets;
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.*;
028    import org.jetbrains.jet.lang.types.*;
029    import org.jetbrains.jet.storage.LockBasedStorageManager;
030    
031    import java.util.ArrayList;
032    import java.util.Collection;
033    import java.util.List;
034    import java.util.Set;
035    
036    public class MutableClassDescriptor extends ClassDescriptorBase implements ClassDescriptorWithResolutionScopes {
037        private final ClassKind kind;
038        private final boolean isInner;
039    
040        private Annotations annotations;
041        private Modality modality;
042        private Visibility visibility;
043        private TypeConstructor typeConstructor;
044        private List<TypeParameterDescriptor> typeParameters;
045        private Collection<JetType> supertypes = new ArrayList<JetType>();
046    
047        private MutableClassDescriptor classObjectDescriptor;
048    
049        private final Set<ConstructorDescriptor> constructors = Sets.newLinkedHashSet();
050        private ConstructorDescriptor primaryConstructor;
051    
052        private final Set<CallableMemberDescriptor> declaredCallableMembers = Sets.newLinkedHashSet();
053        private final Set<CallableMemberDescriptor> allCallableMembers = Sets.newLinkedHashSet(); // includes fake overrides
054        private final Set<PropertyDescriptor> properties = Sets.newLinkedHashSet();
055        private final Set<SimpleFunctionDescriptor> functions = Sets.newLinkedHashSet();
056    
057        private final WritableScope scopeForMemberResolution;
058        // This scope contains type parameters but does not contain inner classes
059        private final WritableScope scopeForSupertypeResolution;
060        private WritableScope scopeForInitializers = null; //contains members + primary constructor value parameters + map for backing fields
061        private JetScope scopeForMemberLookup;
062    
063        public MutableClassDescriptor(
064                @NotNull DeclarationDescriptor containingDeclaration,
065                @NotNull JetScope outerScope,
066                @NotNull ClassKind kind,
067                boolean isInner,
068                @NotNull Name name
069        ) {
070            super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, name);
071            this.kind = kind;
072            this.isInner = isInner;
073    
074            RedeclarationHandler redeclarationHandler = RedeclarationHandler.DO_NOTHING;
075    
076            setScopeForMemberLookup(new WritableScopeImpl(JetScope.EMPTY, this, redeclarationHandler, "MemberLookup")
077                                            .changeLockLevel(WritableScope.LockLevel.BOTH));
078            this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, redeclarationHandler, "SupertypeResolution")
079                    .changeLockLevel(WritableScope.LockLevel.BOTH);
080            this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler, "MemberResolution")
081                    .changeLockLevel(WritableScope.LockLevel.BOTH);
082            if (getKind() == ClassKind.TRAIT) {
083                setUpScopeForInitializers(this);
084            }
085    
086            scopeForMemberResolution.addLabeledDeclaration(this);
087        }
088    
089        @Nullable
090        @Override
091        public MutableClassDescriptor getClassObjectDescriptor() {
092            return classObjectDescriptor;
093        }
094    
095        @NotNull
096        @Override
097        public Annotations getAnnotations() {
098            if (annotations == null) {
099                annotations = new AnnotationsImpl(new ArrayList<AnnotationDescriptor>(0));
100            }
101            return annotations;
102        }
103    
104        public void addAnnotations(@NotNull Iterable<AnnotationDescriptor> annotationsToAdd) {
105            List<AnnotationDescriptor> annotations = ((AnnotationsImpl) getAnnotations()).getAnnotationDescriptors();
106            for (AnnotationDescriptor annotationDescriptor : annotationsToAdd) {
107                annotations.add(annotationDescriptor);
108            }
109        }
110    
111        public void setModality(@NotNull Modality modality) {
112            this.modality = modality;
113        }
114    
115        @Override
116        @NotNull
117        public Modality getModality() {
118            return modality;
119        }
120    
121        @NotNull
122        @Override
123        public ClassKind getKind() {
124            return kind;
125        }
126    
127        public void setVisibility(@NotNull Visibility visibility) {
128            this.visibility = visibility;
129        }
130    
131        @NotNull
132        @Override
133        public Visibility getVisibility() {
134            return visibility;
135        }
136    
137        @Override
138        public boolean isInner() {
139            return isInner;
140        }
141    
142        @NotNull
143        @Override
144        public TypeConstructor getTypeConstructor() {
145            return typeConstructor;
146        }
147    
148        @NotNull
149        public Collection<JetType> getSupertypes() {
150            return supertypes;
151        }
152    
153        public void setSupertypes(@NotNull Collection<JetType> supertypes) {
154            this.supertypes = supertypes;
155        }
156    
157        public void addSupertype(@NotNull JetType supertype) {
158            assert !supertype.isError() : "Error types must be filtered out in DescriptorResolver";
159            if (TypeUtils.getClassDescriptor(supertype) != null) {
160                // See the Errors.SUPERTYPE_NOT_A_CLASS_OR_TRAIT
161                supertypes.add(supertype);
162            }
163        }
164    
165        public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
166            assert primaryConstructor == null : "Primary constructor assigned twice " + this;
167            primaryConstructor = constructorDescriptor;
168    
169            constructors.add(constructorDescriptor);
170    
171            ((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(new DelegatingType() {
172                @Override
173                protected JetType getDelegate() {
174                    return getDefaultType();
175                }
176            });
177    
178            if (constructorDescriptor.isPrimary()) {
179                setUpScopeForInitializers(constructorDescriptor);
180            }
181        }
182    
183        public void addConstructorParametersToInitializersScope(@NotNull Collection<? extends VariableDescriptor> variables) {
184            WritableScope scope = getWritableScopeForInitializers();
185            for (VariableDescriptor variable : variables) {
186                scope.addVariableDescriptor(variable);
187            }
188        }
189    
190        @NotNull
191        @Override
192        public Set<ConstructorDescriptor> getConstructors() {
193            return constructors;
194        }
195    
196        @Override
197        @Nullable
198        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
199            return primaryConstructor;
200        }
201    
202        @NotNull
203        public Set<SimpleFunctionDescriptor> getFunctions() {
204            return functions;
205        }
206    
207        @NotNull
208        public Set<PropertyDescriptor> getProperties() {
209            return properties;
210        }
211    
212        @Override
213        @NotNull
214        public Set<CallableMemberDescriptor> getDeclaredCallableMembers() {
215            return declaredCallableMembers;
216        }
217    
218        @NotNull
219        public Set<CallableMemberDescriptor> getAllCallableMembers() {
220            return allCallableMembers;
221        }
222    
223        public void setTypeParameterDescriptors(@NotNull List<TypeParameterDescriptor> typeParameters) {
224            if (this.typeParameters != null) {
225                throw new IllegalStateException("Type parameters are already set for " + getName());
226            }
227            this.typeParameters = new ArrayList<TypeParameterDescriptor>(typeParameters);
228            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
229                scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
230            }
231            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
232        }
233    
234        public void createTypeConstructor() {
235            assert typeConstructor == null : typeConstructor;
236            this.typeConstructor = new TypeConstructorImpl(
237                    this,
238                    Annotations.EMPTY, // TODO : pass annotations from the class?
239                    !getModality().isOverridable(),
240                    getName().asString(),
241                    typeParameters,
242                    supertypes
243            );
244            for (FunctionDescriptor functionDescriptor : getConstructors()) {
245                ((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType());
246            }
247            scopeForMemberResolution.setImplicitReceiver(getThisAsReceiverParameter());
248        }
249    
250        @Override
251        @NotNull
252        public JetScope getScopeForClassHeaderResolution() {
253            return scopeForSupertypeResolution;
254        }
255    
256        @Override
257        @NotNull
258        public JetScope getScopeForMemberDeclarationResolution() {
259            return scopeForMemberResolution;
260        }
261    
262        private WritableScope getWritableScopeForInitializers() {
263            if (scopeForInitializers == null) {
264                throw new IllegalStateException("Scope for initializers queried before the primary constructor is set");
265            }
266            return scopeForInitializers;
267        }
268    
269        @Override
270        @NotNull
271        public JetScope getScopeForInitializerResolution() {
272            return getWritableScopeForInitializers();
273        }
274    
275        private void setUpScopeForInitializers(@NotNull DeclarationDescriptor containingDeclaration) {
276            this.scopeForInitializers = new WritableScopeImpl(
277                    scopeForMemberResolution, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Initializers")
278                        .changeLockLevel(WritableScope.LockLevel.BOTH);
279        }
280    
281        public void setScopeForMemberLookup(@NotNull JetScope scopeForMemberLookup) {
282            this.scopeForMemberLookup = scopeForMemberLookup;
283        }
284    
285        @Override
286        @NotNull
287        public JetScope getScopeForMemberLookup() {
288            return scopeForMemberLookup;
289        }
290    
291        @NotNull
292        private WritableScope getScopeForMemberLookupAsWritableScope() {
293            // hack
294            return (WritableScope) scopeForMemberLookup;
295        }
296    
297        public void lockScopes() {
298            getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING);
299            if (classObjectDescriptor != null) {
300                classObjectDescriptor.lockScopes();
301            }
302            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
303            scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING);
304            getWritableScopeForInitializers().changeLockLevel(WritableScope.LockLevel.READING);
305        }
306    
307        private PackageLikeBuilder builder = null;
308    
309        @NotNull
310        public PackageLikeBuilder getBuilder() {
311            if (builder == null) {
312                builder = new PackageLikeBuilder() {
313                    @NotNull
314                    @Override
315                    public DeclarationDescriptor getOwnerForChildren() {
316                        return MutableClassDescriptor.this;
317                    }
318    
319                    @Override
320                    public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
321                        getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor);
322                        scopeForMemberResolution.addClassifierDescriptor(classDescriptor);
323                    }
324    
325                    @Override
326                    public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
327                        getScopeForMemberLookupAsWritableScope().addFunctionDescriptor(functionDescriptor);
328                        functions.add(functionDescriptor);
329                        if (functionDescriptor.getKind().isReal()) {
330                            declaredCallableMembers.add(functionDescriptor);
331                        }
332                        allCallableMembers.add(functionDescriptor);
333                        scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
334                    }
335    
336                    @Override
337                    public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
338                        if (getKind() == ClassKind.CLASS_OBJECT || isInner()) {
339                            return ClassObjectStatus.NOT_ALLOWED;
340                        }
341    
342                        if (MutableClassDescriptor.this.classObjectDescriptor != null) {
343                            return ClassObjectStatus.DUPLICATE;
344                        }
345    
346                        assert classObjectDescriptor.getKind() == ClassKind.CLASS_OBJECT;
347                        MutableClassDescriptor.this.classObjectDescriptor = classObjectDescriptor;
348    
349                        // Members of the class object are accessible from the class
350                        // The scope must be lazy, because classObjectDescriptor may not by fully built yet
351                        scopeForMemberResolution.importScope(new ClassObjectMixinScope(classObjectDescriptor));
352    
353                        return ClassObjectStatus.OK;
354                    }
355    
356                    @Override
357                    public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
358                        getScopeForMemberLookupAsWritableScope().addPropertyDescriptor(propertyDescriptor);
359                        properties.add(propertyDescriptor);
360                        if (propertyDescriptor.getKind().isReal()) {
361                            declaredCallableMembers.add(propertyDescriptor);
362                        }
363                        allCallableMembers.add(propertyDescriptor);
364                        scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor);
365                    }
366                };
367            }
368    
369            return builder;
370        }
371    
372        @Override
373        public String toString() {
374            return DeclarationDescriptorImpl.toString(this);
375        }
376    }