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 {
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        @NotNull
111        public Set<CallableMemberDescriptor> getDeclaredCallableMembers() {
112            return declaredCallableMembers;
113        }
114    
115        @NotNull
116        public Set<CallableMemberDescriptor> getAllCallableMembers() {
117            return allCallableMembers;
118        }
119    
120        @Override
121        public void setTypeParameterDescriptors(List<TypeParameterDescriptor> typeParameters) {
122            super.setTypeParameterDescriptors(typeParameters);
123            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
124                scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
125            }
126            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
127        }
128    
129        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
130    
131        @Override
132        public void createTypeConstructor() {
133            super.createTypeConstructor();
134            for (FunctionDescriptor functionDescriptor : getConstructors()) {
135                ((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType());
136            }
137            scopeForMemberResolution.setImplicitReceiver(getThisAsReceiverParameter());
138        }
139    
140        @NotNull
141        public JetScope getScopeForSupertypeResolution() {
142            return scopeForSupertypeResolution;
143        }
144    
145        @NotNull
146        public JetScope getScopeForMemberResolution() {
147            return scopeForMemberResolution;
148        }
149    
150        private WritableScope getWritableScopeForInitializers() {
151            if (scopeForInitializers == null) {
152                throw new IllegalStateException("Scope for initializers queried before the primary constructor is set");
153            }
154            return scopeForInitializers;
155        }
156    
157        @NotNull
158        public JetScope getScopeForInitializers() {
159            return getWritableScopeForInitializers();
160        }
161    
162        private void setUpScopeForInitializers(@NotNull DeclarationDescriptor containingDeclaration) {
163            this.scopeForInitializers = new WritableScopeImpl(
164                    scopeForMemberResolution, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Initializers")
165                        .changeLockLevel(WritableScope.LockLevel.BOTH);
166        }
167    
168        @Override
169        public void lockScopes() {
170            super.lockScopes();
171            scopeForSupertypeResolution.changeLockLevel(WritableScope.LockLevel.READING);
172            scopeForMemberResolution.changeLockLevel(WritableScope.LockLevel.READING);
173            getWritableScopeForInitializers().changeLockLevel(WritableScope.LockLevel.READING);
174        }
175    
176        private NamespaceLikeBuilder builder = null;
177    
178        @Override
179        public NamespaceLikeBuilder getBuilder() {
180            if (builder == null) {
181                final NamespaceLikeBuilder superBuilder = super.getBuilder();
182                builder = new NamespaceLikeBuilderDummy() {
183                    @NotNull
184                    @Override
185                    public DeclarationDescriptor getOwnerForChildren() {
186                        return superBuilder.getOwnerForChildren();
187                    }
188    
189                    @Override
190                    public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
191                        superBuilder.addClassifierDescriptor(classDescriptor);
192                        scopeForMemberResolution.addClassifierDescriptor(classDescriptor);
193                    }
194    
195                    @Override
196                    public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
197                        superBuilder.addFunctionDescriptor(functionDescriptor);
198                        functions.add(functionDescriptor);
199                        if (functionDescriptor.getKind().isReal()) {
200                            declaredCallableMembers.add(functionDescriptor);
201                        }
202                        allCallableMembers.add(functionDescriptor);
203                        scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
204                    }
205    
206                    @Override
207                    public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
208                        ClassObjectStatus r = superBuilder.setClassObjectDescriptor(classObjectDescriptor);
209                        if (r != ClassObjectStatus.OK) {
210                            return r;
211                        }
212    
213                        // Members of the class object are accessible from the class
214                        // The scope must be lazy, because classObjectDescriptor may not by fully built yet
215                        scopeForMemberResolution.importScope(new ClassObjectMixinScope(classObjectDescriptor));
216    
217                        return ClassObjectStatus.OK;
218                    }
219    
220                    @Override
221                    public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
222                        superBuilder.addPropertyDescriptor(propertyDescriptor);
223                        properties.add(propertyDescriptor);
224                        if (propertyDescriptor.getKind().isReal()) {
225                            declaredCallableMembers.add(propertyDescriptor);
226                        }
227                        allCallableMembers.add(propertyDescriptor);
228                        scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor);
229                    }
230                };
231            }
232    
233            return builder;
234        }
235    }