001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve.lazy.descriptors;
018
019 import com.google.common.collect.Sets;
020 import com.intellij.openapi.util.Computable;
021 import com.intellij.psi.util.PsiTreeUtil;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
024 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
025 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
026 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
027 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
028 import org.jetbrains.jet.lang.psi.*;
029 import org.jetbrains.jet.lang.resolve.BindingContext;
030 import org.jetbrains.jet.lang.resolve.lazy.LazyDescriptor;
031 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
032 import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils;
033 import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
034 import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
035 import org.jetbrains.jet.lang.resolve.name.Name;
036 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
037 import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
038 import org.jetbrains.jet.lang.types.*;
039 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
040 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
041 import org.jetbrains.jet.lexer.JetTokens;
042 import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue;
043
044 import java.util.Collection;
045 import java.util.Collections;
046 import java.util.List;
047 import java.util.Set;
048
049 public class LazyTypeParameterDescriptor implements TypeParameterDescriptor, LazyDescriptor {
050 private final ResolveSession resolveSession;
051
052 private final JetTypeParameter jetTypeParameter;
053 private final Variance variance;
054 private final boolean reified;
055 private final int index;
056 private final LazyClassDescriptor containingDeclaration;
057 private final Name name;
058
059 private final NotNullLazyValue<TypeConstructor> typeConstructor;
060 private final NotNullLazyValue<JetType> defaultType;
061 private final NotNullLazyValue<Set<JetType>> upperBounds;
062 private final NotNullLazyValue<JetType> upperBoundsAsType;
063
064 public LazyTypeParameterDescriptor(
065 @NotNull ResolveSession resolveSession,
066 @NotNull LazyClassDescriptor containingDeclaration,
067 @NotNull JetTypeParameter jetTypeParameter,
068 int index) {
069 this.resolveSession = resolveSession;
070 this.jetTypeParameter = jetTypeParameter;
071 this.variance = jetTypeParameter.getVariance();
072 this.containingDeclaration = containingDeclaration;
073 this.index = index;
074 this.name = ResolveSessionUtils.safeNameForLazyResolve(jetTypeParameter.getNameAsName());
075
076 this.resolveSession.getTrace().record(BindingContext.TYPE_PARAMETER, jetTypeParameter, this);
077
078 this.reified = jetTypeParameter.hasModifier(JetTokens.REIFIED_KEYWORD);
079
080 StorageManager storageManager = resolveSession.getStorageManager();
081 this.typeConstructor = storageManager.createLazyValue(new Computable<TypeConstructor>() {
082 @Override
083 public TypeConstructor compute() {
084 return createTypeConstructor();
085 }
086 });
087 this.defaultType = storageManager.createLazyValue(new Computable<JetType>() {
088 @Override
089 public JetType compute() {
090 return createDefaultType();
091 }
092 });
093 this.upperBounds = storageManager.createLazyValue(new Computable<Set<JetType>>() {
094 @Override
095 public Set<JetType> compute() {
096 return resolveUpperBounds();
097 }
098 });
099 this.upperBoundsAsType = storageManager.createLazyValue(new Computable<JetType>() {
100 @Override
101 public JetType compute() {
102 return computeUpperBoundsAsType();
103 }
104 });
105 }
106
107 @Override
108 public boolean isReified() {
109 return reified;
110 }
111
112 @Override
113 public Variance getVariance() {
114 return variance;
115 }
116
117 @NotNull
118 @Override
119 public Set<JetType> getUpperBounds() {
120 return upperBounds.compute();
121 }
122
123 @NotNull
124 private Set<JetType> resolveUpperBounds() {
125 Set<JetType> upperBounds = Sets.newLinkedHashSet();
126
127 JetTypeParameter jetTypeParameter = this.jetTypeParameter;
128
129 resolveUpperBoundsFromWhereClause(upperBounds, false);
130
131 JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
132 if (extendsBound != null) {
133 upperBounds.add(resolveBoundType(extendsBound));
134 }
135
136 if (upperBounds.isEmpty()) {
137 upperBounds.add(KotlinBuiltIns.getInstance().getDefaultBound());
138 }
139
140 return upperBounds;
141 }
142
143 private void resolveUpperBoundsFromWhereClause(Set<JetType> upperBounds, boolean forClassObject) {
144 JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(jetTypeParameter, JetClassOrObject.class);
145 if (classOrObject instanceof JetClass) {
146 JetClass jetClass = (JetClass) classOrObject;
147 for (JetTypeConstraint jetTypeConstraint : jetClass.getTypeConstraints()) {
148 if (jetTypeConstraint.isClassObjectContraint() != forClassObject) continue;
149
150 JetSimpleNameExpression constrainedParameterName = jetTypeConstraint.getSubjectTypeParameterName();
151 if (constrainedParameterName != null) {
152 if (name.equals(constrainedParameterName.getReferencedNameAsName())) {
153
154 JetTypeReference boundTypeReference = jetTypeConstraint.getBoundTypeReference();
155 if (boundTypeReference != null) {
156 upperBounds.add(resolveBoundType(boundTypeReference));
157 }
158 }
159 }
160 }
161 }
162
163 }
164
165 private JetType resolveBoundType(@NotNull JetTypeReference boundTypeReference) {
166 return resolveSession.getInjector().getTypeResolver()
167 .resolveType(containingDeclaration.getScopeForClassHeaderResolution(), boundTypeReference,
168 resolveSession.getTrace(), false);
169 }
170
171 @NotNull
172 @Override
173 public JetType getUpperBoundsAsType() {
174 return upperBoundsAsType.compute();
175 }
176
177 @NotNull
178 private JetType computeUpperBoundsAsType() {
179 Set<JetType> upperBounds = getUpperBounds();
180 assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
181 JetType upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
182 if (upperBoundsAsType == null) {
183 upperBoundsAsType = KotlinBuiltIns.getInstance().getNothingType();
184 }
185 return upperBoundsAsType;
186 }
187
188 @NotNull
189 @Override
190 public Set<JetType> getLowerBounds() {
191 return Collections.singleton(getLowerBoundsAsType());
192 }
193
194 @NotNull
195 @Override
196 public JetType getLowerBoundsAsType() {
197 return KotlinBuiltIns.getInstance().getNothingType();
198 }
199
200 @NotNull
201 @Override
202 public TypeConstructor getTypeConstructor() {
203 return typeConstructor.compute();
204 }
205
206 @NotNull
207 private TypeConstructor createTypeConstructor() {
208 return new TypeConstructor() {
209 @NotNull
210 @Override
211 public Collection<JetType> getSupertypes() {
212 return LazyTypeParameterDescriptor.this.getUpperBounds();
213 }
214
215 @NotNull
216 @Override
217 public List<TypeParameterDescriptor> getParameters() {
218 return Collections.emptyList();
219 }
220
221 @Override
222 public boolean isSealed() {
223 return false;
224 }
225
226 @Override
227 public ClassifierDescriptor getDeclarationDescriptor() {
228 return LazyTypeParameterDescriptor.this;
229 }
230
231 @Override
232 public List<AnnotationDescriptor> getAnnotations() {
233 return LazyTypeParameterDescriptor.this.getAnnotations();
234 }
235
236 @Override
237 public String toString() {
238 return getName().toString();
239 }
240 };
241 }
242
243 @NotNull
244 @Override
245 public JetType getDefaultType() {
246 return defaultType.compute();
247 }
248
249 @NotNull
250 private JetType createDefaultType() {
251 return new JetTypeImpl(getTypeConstructor(), new LazyScopeAdapter(new RecursionIntolerantLazyValue<JetScope>() {
252 @Override
253 protected JetScope compute() {
254 return getUpperBoundsAsType().getMemberScope();
255 }
256 }));
257 }
258
259 @Override
260 public JetType getClassObjectType() {
261 return null;
262 }
263
264 @NotNull
265 @Override
266 public DeclarationDescriptor getOriginal() {
267 return this;
268 }
269
270 @NotNull
271 @Override
272 public DeclarationDescriptor getContainingDeclaration() {
273 return containingDeclaration;
274 }
275
276 @NotNull
277 @Override
278 @Deprecated
279 public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
280 throw new UnsupportedOperationException("Don't call substitute() on type parameters");
281 }
282
283 @Override
284 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
285 return visitor.visitTypeParameterDescriptor(this, data);
286 }
287
288 @Override
289 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
290 visitor.visitTypeParameterDescriptor(this, null);
291 }
292
293 @Override
294 public int getIndex() {
295 return index;
296 }
297
298 @Override
299 public List<AnnotationDescriptor> getAnnotations() {
300 return Collections.emptyList(); // TODO
301 }
302
303 @NotNull
304 @Override
305 public Name getName() {
306 return name;
307 }
308
309 @Override
310 public String toString() {
311 return getName().toString();
312 }
313
314 @Override
315 public void forceResolveAllContents() {
316 getAnnotations();
317 getClassObjectType();
318 getContainingDeclaration();
319 getDefaultType();
320 getIndex();
321 getLowerBounds();
322 getLowerBoundsAsType();
323 getOriginal();
324 getTypeConstructor();
325 getUpperBounds();
326 getUpperBoundsAsType();
327 getVariance();
328 }
329 }