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.resolve.name.Name;
024    import org.jetbrains.jet.lang.resolve.scopes.*;
025    
026    import java.util.Collection;
027    import java.util.List;
028    import java.util.Set;
029    
030    public class MutableClassDescriptor extends MutableClassDescriptorLite implements ClassDescriptorWithResolutionScopes {
031        private final Set<ConstructorDescriptor> constructors = Sets.newLinkedHashSet();
032        private ConstructorDescriptor primaryConstructor;
033    
034        private final Set<CallableMemberDescriptor> declaredCallableMembers = Sets.newLinkedHashSet();
035        private final Set<CallableMemberDescriptor> allCallableMembers = Sets.newLinkedHashSet(); // includes fake overrides
036        private final Set<PropertyDescriptor> properties = Sets.newLinkedHashSet();
037        private final Set<SimpleFunctionDescriptor> functions = Sets.newLinkedHashSet();
038    
039        private final WritableScope scopeForMemberResolution;
040        // This scope contains type parameters but does not contain inner classes
041        private final WritableScope scopeForSupertypeResolution;
042        private WritableScope scopeForInitializers = null; //contains members + primary constructor value parameters + map for backing fields
043    
044        public MutableClassDescriptor(@NotNull DeclarationDescriptor containingDeclaration,
045                                      @NotNull JetScope outerScope, ClassKind kind, boolean isInner, Name name) {
046            super(containingDeclaration, name, kind, isInner);
047    
048            RedeclarationHandler redeclarationHandler = RedeclarationHandler.DO_NOTHING;
049    
050            setScopeForMemberLookup(new WritableScopeImpl(JetScope.EMPTY, this, redeclarationHandler, "MemberLookup")
051                                            .changeLockLevel(WritableScope.LockLevel.BOTH));
052            this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, redeclarationHandler, "SupertypeResolution")
053                    .changeLockLevel(WritableScope.LockLevel.BOTH);
054            this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler, "MemberResolution")
055                    .changeLockLevel(WritableScope.LockLevel.BOTH);
056            if (getKind() == ClassKind.TRAIT) {
057                setUpScopeForInitializers(this);
058            }
059    
060            scopeForMemberResolution.addLabeledDeclaration(this);
061        }
062    
063    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
064    
065    
066        public void setPrimaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
067            assert primaryConstructor == null : "Primary constructor assigned twice " + this;
068            primaryConstructor = constructorDescriptor;
069    
070            constructors.add(constructorDescriptor);
071    
072            if (defaultType.isComputed()) {
073                ((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(getDefaultType());
074            }
075    
076            if (constructorDescriptor.isPrimary()) {
077                setUpScopeForInitializers(constructorDescriptor);
078            }
079        }
080    
081        public void addConstructorParametersToInitializersScope(@NotNull Collection<? extends VariableDescriptor> variables) {
082            WritableScope scope = getWritableScopeForInitializers();
083            for (VariableDescriptor variable : variables) {
084                scope.addVariableDescriptor(variable);
085            }
086        }
087    
088        @NotNull
089        @Override
090        public Set<ConstructorDescriptor> getConstructors() {
091            return constructors;
092        }
093    
094        @Override
095        @Nullable
096        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
097            return primaryConstructor;
098        }
099    
100        @NotNull
101        public Set<SimpleFunctionDescriptor> getFunctions() {
102            return functions;
103        }
104    
105        @NotNull
106        public Set<PropertyDescriptor> getProperties() {
107            return properties;
108        }
109    
110        @Override
111        @NotNull
112        public Set<CallableMemberDescriptor> getDeclaredCallableMembers() {
113            return declaredCallableMembers;
114        }
115    
116        @NotNull
117        public Set<CallableMemberDescriptor> getAllCallableMembers() {
118            return allCallableMembers;
119        }
120    
121        @Override
122        public void setTypeParameterDescriptors(List<TypeParameterDescriptor> typeParameters) {
123            super.setTypeParameterDescriptors(typeParameters);
124            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
125                scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
126            }
127            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
128        }
129    
130        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131    
132        @Override
133        public void createTypeConstructor() {
134            super.createTypeConstructor();
135            for (FunctionDescriptor functionDescriptor : getConstructors()) {
136                ((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType());
137            }
138            scopeForMemberResolution.setImplicitReceiver(getThisAsReceiverParameter());
139        }
140    
141        @Override
142        @NotNull
143        public JetScope getScopeForClassHeaderResolution() {
144            return scopeForSupertypeResolution;
145        }
146    
147        @Override
148        @NotNull
149        public JetScope getScopeForMemberDeclarationResolution() {
150            return scopeForMemberResolution;
151        }
152    
153        private WritableScope getWritableScopeForInitializers() {
154            if (scopeForInitializers == null) {
155                throw new IllegalStateException("Scope for initializers queried before the primary constructor is set");
156            }
157            return scopeForInitializers;
158        }
159    
160        @Override
161        @NotNull
162        public JetScope getScopeForInitializerResolution() {
163            return getWritableScopeForInitializers();
164        }
165    
166        private void setUpScopeForInitializers(@NotNull DeclarationDescriptor containingDeclaration) {
167            this.scopeForInitializers = new WritableScopeImpl(
168                    scopeForMemberResolution, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Initializers")
169                        .changeLockLevel(WritableScope.LockLevel.BOTH);
170        }
171    
172        @Override
173        public void lockScopes() {
174            super.lockScopes();
175            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
176            scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING);
177            getWritableScopeForInitializers().changeLockLevel(WritableScope.LockLevel.READING);
178        }
179    
180        private PackageLikeBuilder builder = null;
181    
182        @Override
183        public PackageLikeBuilder getBuilder() {
184            if (builder == null) {
185                final PackageLikeBuilder superBuilder = super.getBuilder();
186                builder = new PackageLikeBuilder() {
187                    @NotNull
188                    @Override
189                    public DeclarationDescriptor getOwnerForChildren() {
190                        return superBuilder.getOwnerForChildren();
191                    }
192    
193                    @Override
194                    public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
195                        superBuilder.addClassifierDescriptor(classDescriptor);
196                        scopeForMemberResolution.addClassifierDescriptor(classDescriptor);
197                    }
198    
199                    @Override
200                    public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
201                        superBuilder.addFunctionDescriptor(functionDescriptor);
202                        functions.add(functionDescriptor);
203                        if (functionDescriptor.getKind().isReal()) {
204                            declaredCallableMembers.add(functionDescriptor);
205                        }
206                        allCallableMembers.add(functionDescriptor);
207                        scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
208                    }
209    
210                    @Override
211                    public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
212                        ClassObjectStatus r = superBuilder.setClassObjectDescriptor(classObjectDescriptor);
213                        if (r != ClassObjectStatus.OK) {
214                            return r;
215                        }
216    
217                        // Members of the class object are accessible from the class
218                        // The scope must be lazy, because classObjectDescriptor may not by fully built yet
219                        scopeForMemberResolution.importScope(new ClassObjectMixinScope(classObjectDescriptor));
220    
221                        return ClassObjectStatus.OK;
222                    }
223    
224                    @Override
225                    public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
226                        superBuilder.addPropertyDescriptor(propertyDescriptor);
227                        properties.add(propertyDescriptor);
228                        if (propertyDescriptor.getKind().isReal()) {
229                            declaredCallableMembers.add(propertyDescriptor);
230                        }
231                        allCallableMembers.add(propertyDescriptor);
232                        scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor);
233                    }
234                };
235            }
236    
237            return builder;
238        }
239    }