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
017package org.jetbrains.jet.lang.descriptors.impl;
018
019import com.google.common.collect.Sets;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022import org.jetbrains.jet.lang.descriptors.*;
023import org.jetbrains.jet.lang.psi.JetParameter;
024import org.jetbrains.jet.lang.resolve.BindingContextUtils;
025import org.jetbrains.jet.lang.resolve.BindingTrace;
026import org.jetbrains.jet.lang.resolve.name.Name;
027import org.jetbrains.jet.lang.resolve.scopes.*;
028
029import java.util.List;
030import java.util.Set;
031
032public 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}