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