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(
088 this, originalTypeConstructor.getAnnotations(), originalTypeConstructor.isFinal(), typeConstructorParameters, supertypes
089 );
090 }
091
092 return typeConstructor;
093 }
094
095 @NotNull
096 @Override
097 public MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
098 MemberScope memberScope = original.getMemberScope(typeArguments);
099 if (originalSubstitutor.isEmpty()) {
100 return memberScope;
101 }
102 return new SubstitutingScope(memberScope, getSubstitutor());
103 }
104
105 @NotNull
106 @Override
107 public MemberScope getMemberScope(@NotNull TypeSubstitution typeSubstitution) {
108 MemberScope memberScope = original.getMemberScope(typeSubstitution);
109 if (originalSubstitutor.isEmpty()) {
110 return memberScope;
111 }
112 return new SubstitutingScope(memberScope, getSubstitutor());
113 }
114
115 @NotNull
116 @Override
117 public MemberScope getUnsubstitutedMemberScope() {
118 MemberScope memberScope = original.getUnsubstitutedMemberScope();
119 if (originalSubstitutor.isEmpty()) {
120 return memberScope;
121 }
122 return new SubstitutingScope(memberScope, getSubstitutor());
123 }
124
125 @NotNull
126 @Override
127 public MemberScope getStaticScope() {
128 return original.getStaticScope();
129 }
130
131 @NotNull
132 @Override
133 public KotlinType getDefaultType() {
134 List<TypeProjection> typeProjections = TypeUtils.getDefaultTypeProjections(getTypeConstructor().getParameters());
135 return KotlinTypeImpl.create(
136 getAnnotations(),
137 this,
138 false,
139 typeProjections
140 );
141 }
142
143 @NotNull
144 @Override
145 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
146 throw new UnsupportedOperationException(); // TODO
147 }
148
149 @NotNull
150 @Override
151 public Collection<ConstructorDescriptor> getConstructors() {
152 Collection<ConstructorDescriptor> originalConstructors = original.getConstructors();
153 Collection<ConstructorDescriptor> result = new ArrayList<ConstructorDescriptor>(originalConstructors.size());
154 for (ConstructorDescriptor constructor : originalConstructors) {
155 ConstructorDescriptor copy =
156 constructor.copy(this, constructor.getModality(), constructor.getVisibility(), constructor.getKind(), false);
157 result.add(copy.substitute(getSubstitutor()));
158 }
159 return result;
160 }
161
162 @NotNull
163 @Override
164 public Annotations getAnnotations() {
165 return original.getAnnotations();
166 }
167
168 @NotNull
169 @Override
170 public Name getName() {
171 return original.getName();
172 }
173
174 @NotNull
175 @Override
176 public ClassDescriptor getOriginal() {
177 return original.getOriginal();
178 }
179
180 @NotNull
181 @Override
182 public DeclarationDescriptor getContainingDeclaration() {
183 return original.getContainingDeclaration();
184 }
185
186 @NotNull
187 @Override
188 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
189 if (substitutor.isEmpty()) return this;
190 return new LazySubstitutingClassDescriptor(this, TypeSubstitutor.createChainedSubstitutor(substitutor.getSubstitution(), getSubstitutor().getSubstitution()));
191 }
192
193 @Override
194 public ClassDescriptor getCompanionObjectDescriptor() {
195 return original.getCompanionObjectDescriptor();
196 }
197
198 @NotNull
199 @Override
200 public ClassKind getKind() {
201 return original.getKind();
202 }
203
204 @Override
205 @NotNull
206 public Modality getModality() {
207 return original.getModality();
208 }
209
210 @NotNull
211 @Override
212 public Visibility getVisibility() {
213 return original.getVisibility();
214 }
215
216 @Override
217 public boolean isInner() {
218 return original.isInner();
219 }
220
221 @Override
222 public boolean isData() {
223 return original.isData();
224 }
225
226 @Override
227 public boolean isCompanionObject() {
228 return original.isCompanionObject();
229 }
230
231 @Override
232 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
233 return visitor.visitClassDescriptor(this, data);
234 }
235
236 @Override
237 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
238 throw new UnsupportedOperationException(); // TODO
239 }
240
241 @NotNull
242 @Override
243 public MemberScope getUnsubstitutedInnerClassesScope() {
244 return original.getUnsubstitutedInnerClassesScope();
245 }
246
247 @Nullable
248 @Override
249 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
250 return original.getUnsubstitutedPrimaryConstructor();
251 }
252
253 @NotNull
254 @Override
255 public SourceElement getSource() {
256 return SourceElement.NO_SOURCE;
257 }
258
259 @NotNull
260 @Override
261 public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
262 getSubstitutor();
263 return declaredTypeParameters;
264 }
265 }