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