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 @NotNull
128 public Variance getVariance() {
129 return variance;
130 }
131
132 public void addUpperBound(@NotNull JetType bound) {
133 checkUninitialized();
134 doAddUpperBound(bound);
135 }
136
137 private void doAddUpperBound(JetType bound) {
138 upperBounds.add(bound); // TODO : Duplicates?
139 }
140
141 public void addDefaultUpperBound() {
142 checkUninitialized();
143
144 if (upperBounds.isEmpty()) {
145 doAddUpperBound(KotlinBuiltIns.getInstance().getDefaultBound());
146 }
147 }
148
149 @Override
150 @NotNull
151 public Set<JetType> getUpperBounds() {
152 checkInitialized();
153 return upperBounds;
154 }
155
156 @Override
157 @NotNull
158 public JetType getUpperBoundsAsType() {
159 checkInitialized();
160 if (upperBoundsAsType == null) {
161 assert upperBounds != null : "Upper bound list is null in " + getName();
162 assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
163 upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
164 if (upperBoundsAsType == null) {
165 upperBoundsAsType = KotlinBuiltIns.getInstance().getNothingType();
166 }
167 }
168 return upperBoundsAsType;
169 }
170
171 @Override
172 @NotNull
173 public Set<JetType> getLowerBounds() {
174 //checkInitialized();
175 return Collections.singleton(KotlinBuiltIns.getInstance().getNothingType());
176 }
177
178 @Override
179 @NotNull
180 public JetType getLowerBoundsAsType() {
181 checkInitialized();
182 return KotlinBuiltIns.getInstance().getNothingType();
183 }
184
185
186 @NotNull
187 @Override
188 public TypeConstructor getTypeConstructor() {
189 //checkInitialized();
190 return typeConstructor;
191 }
192
193 @Override
194 public String toString() {
195 try {
196 return DescriptorRenderer.TEXT.render(this);
197 } catch (Exception e) {
198 return this.getClass().getName() + "@" + System.identityHashCode(this);
199 }
200 }
201
202 @NotNull
203 @Override
204 @Deprecated
205 public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
206 throw new UnsupportedOperationException();
207 }
208
209 @Override
210 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
211 checkInitialized();
212 return visitor.visitTypeParameterDescriptor(this, data);
213 }
214
215 @NotNull
216 @Override
217 public JetType getDefaultType() {
218 //checkInitialized();
219 if (defaultType == null) {
220 defaultType = new JetTypeImpl(
221 Collections.<AnnotationDescriptor>emptyList(),
222 getTypeConstructor(),
223 TypeUtils.hasNullableLowerBound(this),
224 Collections.<TypeProjection>emptyList(),
225 new LazyScopeAdapter(new RecursionIntolerantLazyValue<JetScope>() {
226 @Override
227 protected JetScope compute() {
228 return getUpperBoundsAsType().getMemberScope();
229 }
230 }));
231 }
232 return defaultType;
233 }
234
235 @Override
236 public JetType getClassObjectType() {
237 checkInitialized();
238 if (classObjectUpperBounds.isEmpty()) return null;
239
240 if (classObjectBoundsAsType == null) {
241 classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds);
242 if (classObjectBoundsAsType == null) {
243 classObjectBoundsAsType = KotlinBuiltIns.getInstance().getNothingType();
244 }
245 }
246 return classObjectBoundsAsType;
247 }
248
249 public void addClassObjectBound(@NotNull JetType bound) {
250 checkUninitialized();
251 classObjectUpperBounds.add(bound); // TODO : Duplicates?
252 }
253
254 @Override
255 public int getIndex() {
256 checkInitialized();
257 return index;
258 }
259 }