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