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.collections.CollectionsKt;
020    import kotlin.jvm.functions.Function1;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.descriptors.*;
024    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
025    import org.jetbrains.kotlin.name.Name;
026    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
027    import org.jetbrains.kotlin.resolve.scopes.SubstitutingScope;
028    import org.jetbrains.kotlin.types.*;
029    
030    import java.util.ArrayList;
031    import java.util.Collection;
032    import java.util.List;
033    
034    public class LazySubstitutingClassDescriptor implements ClassDescriptor {
035        private final ClassDescriptor original;
036        private final TypeSubstitutor originalSubstitutor;
037        private TypeSubstitutor newSubstitutor;
038        private List<TypeParameterDescriptor> typeConstructorParameters;
039        private List<TypeParameterDescriptor> declaredTypeParameters;
040        private TypeConstructor typeConstructor;
041    
042        public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) {
043            this.original = descriptor;
044            this.originalSubstitutor = substitutor;
045        }
046    
047        private TypeSubstitutor getSubstitutor() {
048            if (newSubstitutor == null) {
049                if (originalSubstitutor.isEmpty()) {
050                    newSubstitutor = originalSubstitutor;
051                }
052                else {
053                    List<TypeParameterDescriptor> originalTypeParameters = original.getTypeConstructor().getParameters();
054                    typeConstructorParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
055                    newSubstitutor = DescriptorSubstitutor.substituteTypeParameters(
056                            originalTypeParameters, originalSubstitutor.getSubstitution(), this, typeConstructorParameters
057                    );
058    
059                    declaredTypeParameters = CollectionsKt.filter(typeConstructorParameters, new Function1<TypeParameterDescriptor, Boolean>() {
060                        @Override
061                        public Boolean invoke(TypeParameterDescriptor descriptor) {
062                            return !descriptor.isCapturedFromOuterDeclaration();
063                        }
064                    });
065                }
066            }
067            return newSubstitutor;
068        }
069    
070        @NotNull
071        @Override
072        public TypeConstructor getTypeConstructor() {
073            TypeConstructor originalTypeConstructor = original.getTypeConstructor();
074            if (originalSubstitutor.isEmpty()) {
075                return originalTypeConstructor;
076            }
077    
078            if (typeConstructor == null) {
079                TypeSubstitutor substitutor = getSubstitutor();
080    
081                Collection<KotlinType> originalSupertypes = originalTypeConstructor.getSupertypes();
082                Collection<KotlinType> supertypes = new ArrayList<KotlinType>(originalSupertypes.size());
083                for (KotlinType supertype : originalSupertypes) {
084                    supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
085                }
086    
087                typeConstructor = new ClassTypeConstructorImpl(this, originalTypeConstructor.isFinal(), typeConstructorParameters, supertypes);
088            }
089    
090            return typeConstructor;
091        }
092    
093        @NotNull
094        @Override
095        public MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
096            MemberScope memberScope = original.getMemberScope(typeArguments);
097            if (originalSubstitutor.isEmpty()) {
098                return memberScope;
099            }
100            return new SubstitutingScope(memberScope, getSubstitutor());
101        }
102    
103        @NotNull
104        @Override
105        public MemberScope getMemberScope(@NotNull TypeSubstitution typeSubstitution) {
106            MemberScope memberScope = original.getMemberScope(typeSubstitution);
107            if (originalSubstitutor.isEmpty()) {
108                return memberScope;
109            }
110            return new SubstitutingScope(memberScope, getSubstitutor());
111        }
112    
113        @NotNull
114        @Override
115        public MemberScope getUnsubstitutedMemberScope() {
116            MemberScope memberScope = original.getUnsubstitutedMemberScope();
117            if (originalSubstitutor.isEmpty()) {
118                return memberScope;
119            }
120            return new SubstitutingScope(memberScope, getSubstitutor());
121        }
122    
123        @NotNull
124        @Override
125        public MemberScope getStaticScope() {
126            return original.getStaticScope();
127        }
128    
129        @NotNull
130        @Override
131        public KotlinType getDefaultType() {
132            List<TypeProjection> typeProjections = TypeUtils.getDefaultTypeProjections(getTypeConstructor().getParameters());
133            return KotlinTypeImpl.create(
134                    getAnnotations(),
135                    this,
136                    false,
137                    typeProjections
138            );
139        }
140    
141        @NotNull
142        @Override
143        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
144            throw new UnsupportedOperationException(); // TODO
145        }
146    
147        @NotNull
148        @Override
149        public Collection<ConstructorDescriptor> getConstructors() {
150            Collection<ConstructorDescriptor> originalConstructors = original.getConstructors();
151            Collection<ConstructorDescriptor> result = new ArrayList<ConstructorDescriptor>(originalConstructors.size());
152            for (ConstructorDescriptor constructor : originalConstructors) {
153                ConstructorDescriptor copy =
154                        constructor.copy(this, constructor.getModality(), constructor.getVisibility(), constructor.getKind(), false);
155                result.add(copy.substitute(getSubstitutor()));
156            }
157            return result;
158        }
159    
160        @NotNull
161        @Override
162        public Annotations getAnnotations() {
163            return original.getAnnotations();
164        }
165    
166        @NotNull
167        @Override
168        public Name getName() {
169            return original.getName();
170        }
171    
172        @NotNull
173        @Override
174        public ClassDescriptor getOriginal() {
175            return original.getOriginal();
176        }
177    
178        @NotNull
179        @Override
180        public DeclarationDescriptor getContainingDeclaration() {
181            return original.getContainingDeclaration();
182        }
183    
184        @NotNull
185        @Override
186        public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
187            if (substitutor.isEmpty()) return this;
188            return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.createChainedSubstitutor(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
189        }
190    
191        @Override
192        public ClassDescriptor getCompanionObjectDescriptor() {
193            return original.getCompanionObjectDescriptor();
194        }
195    
196        @NotNull
197        @Override
198        public ClassKind getKind() {
199            return original.getKind();
200        }
201    
202        @Override
203        @NotNull
204        public Modality getModality() {
205            return original.getModality();
206        }
207    
208        @NotNull
209        @Override
210        public Visibility getVisibility() {
211            return original.getVisibility();
212        }
213    
214        @Override
215        public boolean isInner() {
216            return original.isInner();
217        }
218    
219        @Override
220        public boolean isData() {
221            return original.isData();
222        }
223    
224        @Override
225        public boolean isCompanionObject() {
226            return original.isCompanionObject();
227        }
228    
229        @Override
230        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
231            return visitor.visitClassDescriptor(this, data);
232        }
233    
234        @Override
235        public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
236            throw new UnsupportedOperationException(); // TODO
237        }
238    
239        @NotNull
240        @Override
241        public MemberScope getUnsubstitutedInnerClassesScope() {
242            return original.getUnsubstitutedInnerClassesScope();
243        }
244    
245        @Nullable
246        @Override
247        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
248            return original.getUnsubstitutedPrimaryConstructor();
249        }
250    
251        @NotNull
252        @Override
253        public SourceElement getSource() {
254            return SourceElement.NO_SOURCE;
255        }
256    
257        @NotNull
258        @Override
259        public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
260            getSubstitutor();
261            return declaredTypeParameters;
262        }
263    }