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 }