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