001    /*
002     * Copyright 2010-2015 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.kotlin.descriptors.impl;
018    
019    import kotlin.jvm.functions.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.kotlin.descriptors.*;
022    import org.jetbrains.kotlin.name.Name;
023    import org.jetbrains.kotlin.resolve.scopes.InnerClassesScopeWrapper;
024    import org.jetbrains.kotlin.resolve.scopes.JetScope;
025    import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope;
026    import org.jetbrains.kotlin.storage.NotNullLazyValue;
027    import org.jetbrains.kotlin.storage.StorageManager;
028    import org.jetbrains.kotlin.types.*;
029    
030    import java.util.List;
031    import java.util.Map;
032    
033    public abstract class AbstractClassDescriptor implements ClassDescriptor {
034        private final Name name;
035        protected final NotNullLazyValue<JetType> defaultType;
036        private final NotNullLazyValue<JetScope> unsubstitutedInnerClassesScope;
037        private final NotNullLazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
038    
039        public AbstractClassDescriptor(@NotNull StorageManager storageManager, @NotNull Name name) {
040            this.name = name;
041            this.defaultType = storageManager.createLazyValue(new Function0<JetType>() {
042                @Override
043                public JetType invoke() {
044                    return TypeUtils.makeUnsubstitutedType(AbstractClassDescriptor.this, getScopeForMemberLookup());
045                }
046            });
047            this.unsubstitutedInnerClassesScope = storageManager.createLazyValue(new Function0<JetScope>() {
048                @Override
049                public JetScope invoke() {
050                    return new InnerClassesScopeWrapper(getScopeForMemberLookup());
051                }
052            });
053            this.thisAsReceiverParameter = storageManager.createLazyValue(new Function0<ReceiverParameterDescriptor>() {
054                @Override
055                public ReceiverParameterDescriptor invoke() {
056                    return new LazyClassReceiverParameterDescriptor(AbstractClassDescriptor.this);
057                }
058            });
059        }
060    
061        @NotNull
062        @Override
063        public Name getName() {
064            return name;
065        }
066    
067        @NotNull
068        @Override
069        public DeclarationDescriptor getOriginal() {
070            return this;
071        }
072    
073        @NotNull
074        protected abstract JetScope getScopeForMemberLookup();
075    
076        @NotNull
077        @Override
078        public JetScope getUnsubstitutedInnerClassesScope() {
079            return unsubstitutedInnerClassesScope.invoke();
080        }
081    
082        @NotNull
083        @Override
084        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
085            return thisAsReceiverParameter.invoke();
086        }
087    
088        @NotNull
089        @Override
090        public JetScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
091            assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Illegal number of type arguments: expected "
092                                                                                         + getTypeConstructor().getParameters().size() + " but was " + typeArguments.size()
093                                                                                         + " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters();
094            if (typeArguments.isEmpty()) return getScopeForMemberLookup();
095    
096            List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
097            Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments);
098    
099            TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
100            return new SubstitutingScope(getScopeForMemberLookup(), substitutor);
101        }
102    
103        @NotNull
104        @Override
105        public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
106            if (substitutor.isEmpty()) {
107                return this;
108            }
109            return new LazySubstitutingClassDescriptor(this, substitutor);
110        }
111    
112        @NotNull
113        @Override
114        public JetType getDefaultType() {
115            return defaultType.invoke();
116        }
117    
118        @Override
119        public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
120            visitor.visitClassDescriptor(this, null);
121        }
122    
123        @Override
124        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
125            return visitor.visitClassDescriptor(this, data);
126        }
127    }