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