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.descriptors.impl;
018
019 import com.google.common.collect.Sets;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
022 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
023 import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
024 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026 import org.jetbrains.jet.lang.resolve.name.Name;
027 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
028 import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
029 import org.jetbrains.jet.lang.types.*;
030 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
031 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
032 import org.jetbrains.jet.renderer.DescriptorRenderer;
033 import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue;
034
035 import java.util.Collections;
036 import java.util.List;
037 import java.util.Set;
038
039 public 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 }