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.descriptors.impl; 018 019import com.google.common.collect.Sets; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 022import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor; 023import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; 024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 025import org.jetbrains.jet.lang.resolve.DescriptorUtils; 026import org.jetbrains.jet.lang.resolve.name.Name; 027import org.jetbrains.jet.lang.resolve.scopes.JetScope; 028import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; 029import org.jetbrains.jet.lang.types.*; 030import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 031import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 032import org.jetbrains.jet.renderer.DescriptorRenderer; 033import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue; 034 035import java.util.Collections; 036import java.util.List; 037import java.util.Set; 038 039public class TypeParameterDescriptorImpl extends DeclarationDescriptorNonRootImpl implements TypeParameterDescriptor { 040 public static TypeParameterDescriptor createWithDefaultBound( 041 @NotNull DeclarationDescriptor containingDeclaration, 042 @NotNull List<AnnotationDescriptor> annotations, 043 boolean reified, 044 @NotNull Variance variance, 045 @NotNull Name name, 046 int index) { 047 TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index); 048 typeParameterDescriptor.addUpperBound(KotlinBuiltIns.getInstance().getDefaultBound()); 049 typeParameterDescriptor.setInitialized(); 050 return typeParameterDescriptor; 051 } 052 053 public static TypeParameterDescriptorImpl createForFurtherModification( 054 @NotNull DeclarationDescriptor containingDeclaration, 055 @NotNull List<AnnotationDescriptor> annotations, 056 boolean reified, 057 @NotNull Variance variance, 058 @NotNull Name name, 059 int index) { 060 return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index); 061 } 062 063 // 0-based 064 private final int index; 065 private final Variance variance; 066 private final Set<JetType> upperBounds; 067 private JetType upperBoundsAsType; 068 private final TypeConstructor typeConstructor; 069 private JetType defaultType; 070 private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet(); 071 private JetType classObjectBoundsAsType; 072 073 private final boolean reified; 074 075 private boolean initialized = false; 076 077 private TypeParameterDescriptorImpl( 078 @NotNull DeclarationDescriptor containingDeclaration, 079 @NotNull List<AnnotationDescriptor> annotations, 080 boolean reified, 081 @NotNull Variance variance, 082 @NotNull Name name, 083 int index) { 084 super(containingDeclaration, annotations, name); 085 this.index = index; 086 this.variance = variance; 087 this.upperBounds = Sets.newLinkedHashSet(); 088 this.reified = reified; 089 // TODO: Should we actually pass the annotations on to the type constructor? 090 this.typeConstructor = new TypeConstructorImpl( 091 this, 092 annotations, 093 false, 094 name.asString(), 095 Collections.<TypeParameterDescriptor>emptyList(), 096 upperBounds); 097 } 098 099 private void checkInitialized() { 100 if (!initialized) { 101 throw new IllegalStateException("Type parameter descriptor in not initialized: " + nameForAssertions()); 102 } 103 } 104 105 private void checkUninitialized() { 106 if (initialized) { 107 throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions()); 108 } 109 } 110 111 private String nameForAssertions() { 112 return getName() + " declared in " + DescriptorUtils.getFQName(getContainingDeclaration()); 113 } 114 115 public void setInitialized() { 116 checkUninitialized(); 117 initialized = true; 118 } 119 120 @Override 121 public boolean isReified() { 122 checkInitialized(); 123 return reified; 124 } 125 126 @Override 127 public Variance getVariance() { 128 return variance; 129 } 130 131 public void addUpperBound(@NotNull JetType bound) { 132 checkUninitialized(); 133 doAddUpperBound(bound); 134 } 135 136 private void doAddUpperBound(JetType bound) { 137 upperBounds.add(bound); // TODO : Duplicates? 138 } 139 140 public void addDefaultUpperBound() { 141 checkUninitialized(); 142 143 if (upperBounds.isEmpty()) { 144 doAddUpperBound(KotlinBuiltIns.getInstance().getDefaultBound()); 145 } 146 } 147 148 @Override 149 @NotNull 150 public Set<JetType> getUpperBounds() { 151 checkInitialized(); 152 return upperBounds; 153 } 154 155 @Override 156 @NotNull 157 public JetType getUpperBoundsAsType() { 158 checkInitialized(); 159 if (upperBoundsAsType == null) { 160 assert upperBounds != null : "Upper bound list is null in " + getName(); 161 assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName(); 162 upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); 163 if (upperBoundsAsType == null) { 164 upperBoundsAsType = KotlinBuiltIns.getInstance().getNothingType(); 165 } 166 } 167 return upperBoundsAsType; 168 } 169 170 @Override 171 @NotNull 172 public Set<JetType> getLowerBounds() { 173 //checkInitialized(); 174 return Collections.singleton(KotlinBuiltIns.getInstance().getNothingType()); 175 } 176 177 @Override 178 @NotNull 179 public JetType getLowerBoundsAsType() { 180 checkInitialized(); 181 return KotlinBuiltIns.getInstance().getNothingType(); 182 } 183 184 185 @NotNull 186 @Override 187 public TypeConstructor getTypeConstructor() { 188 //checkInitialized(); 189 return typeConstructor; 190 } 191 192 @Override 193 public String toString() { 194 try { 195 return DescriptorRenderer.TEXT.render(this); 196 } catch (Exception e) { 197 return this.getClass().getName() + "@" + System.identityHashCode(this); 198 } 199 } 200 201 @NotNull 202 @Override 203 @Deprecated 204 public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) { 205 throw new UnsupportedOperationException(); 206 } 207 208 @Override 209 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) { 210 checkInitialized(); 211 return visitor.visitTypeParameterDescriptor(this, data); 212 } 213 214 @NotNull 215 @Override 216 public JetType getDefaultType() { 217 //checkInitialized(); 218 if (defaultType == null) { 219 defaultType = new JetTypeImpl( 220 Collections.<AnnotationDescriptor>emptyList(), 221 getTypeConstructor(), 222 TypeUtils.hasNullableLowerBound(this), 223 Collections.<TypeProjection>emptyList(), 224 new LazyScopeAdapter(new RecursionIntolerantLazyValue<JetScope>() { 225 @Override 226 protected JetScope compute() { 227 return getUpperBoundsAsType().getMemberScope(); 228 } 229 })); 230 } 231 return defaultType; 232 } 233 234 @Override 235 public JetType getClassObjectType() { 236 checkInitialized(); 237 if (classObjectUpperBounds.isEmpty()) return null; 238 239 if (classObjectBoundsAsType == null) { 240 classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds); 241 if (classObjectBoundsAsType == null) { 242 classObjectBoundsAsType = KotlinBuiltIns.getInstance().getNothingType(); 243 } 244 } 245 return classObjectBoundsAsType; 246 } 247 248 public void addClassObjectBound(@NotNull JetType bound) { 249 checkUninitialized(); 250 classObjectUpperBounds.add(bound); // TODO : Duplicates? 251 } 252 253 @Override 254 public int getIndex() { 255 checkInitialized(); 256 return index; 257 } 258}