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