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 017package org.jetbrains.jet.lang.resolve.lazy.descriptors; 018 019import com.google.common.collect.Sets; 020import com.intellij.openapi.util.Computable; 021import com.intellij.psi.util.PsiTreeUtil; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; 024import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 025import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor; 026import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; 027import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 028import org.jetbrains.jet.lang.psi.*; 029import org.jetbrains.jet.lang.resolve.lazy.LazyDescriptor; 030import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue; 031import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; 032import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager; 033import org.jetbrains.jet.lang.resolve.name.Name; 034import org.jetbrains.jet.lang.resolve.scopes.JetScope; 035import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; 036import org.jetbrains.jet.lang.types.*; 037import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 038import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 039import org.jetbrains.jet.lexer.JetTokens; 040import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue; 041 042import java.util.Collection; 043import java.util.Collections; 044import java.util.List; 045import java.util.Set; 046 047public 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}