001 /*
002 * Copyright 2010-2015 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.kotlin.descriptors.impl;
018
019 import kotlin.jvm.functions.Function1;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
023 import org.jetbrains.kotlin.descriptors.SourceElement;
024 import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker;
025 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
026 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
027 import org.jetbrains.kotlin.name.Name;
028 import org.jetbrains.kotlin.resolve.DescriptorUtils;
029 import org.jetbrains.kotlin.storage.LockBasedStorageManager;
030 import org.jetbrains.kotlin.types.KotlinType;
031 import org.jetbrains.kotlin.types.TypeConstructor;
032 import org.jetbrains.kotlin.types.TypeConstructorImpl;
033 import org.jetbrains.kotlin.types.Variance;
034
035 import java.util.ArrayList;
036 import java.util.Collections;
037 import java.util.List;
038
039 import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
040
041 public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor {
042 @Nullable
043 private final Function1<KotlinType, Void> reportCycleError;
044 @NotNull
045 private final SupertypeLoopChecker supertypeLoopsChecker;
046
047 public static TypeParameterDescriptor createWithDefaultBound(
048 @NotNull DeclarationDescriptor containingDeclaration,
049 @NotNull Annotations annotations,
050 boolean reified,
051 @NotNull Variance variance,
052 @NotNull Name name,
053 int index
054 ) {
055 TypeParameterDescriptorImpl typeParameterDescriptor =
056 createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, SourceElement.NO_SOURCE);
057 typeParameterDescriptor.addUpperBound(getBuiltIns(containingDeclaration).getDefaultBound());
058 typeParameterDescriptor.setInitialized();
059 return typeParameterDescriptor;
060 }
061
062 public static TypeParameterDescriptorImpl createForFurtherModification(
063 @NotNull DeclarationDescriptor containingDeclaration,
064 @NotNull Annotations annotations,
065 boolean reified,
066 @NotNull Variance variance,
067 @NotNull Name name,
068 int index,
069 @NotNull SourceElement source
070 ) {
071 return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
072 /* reportCycleError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
073 }
074
075 public static TypeParameterDescriptorImpl createForFurtherModification(
076 @NotNull DeclarationDescriptor containingDeclaration,
077 @NotNull Annotations annotations,
078 boolean reified,
079 @NotNull Variance variance,
080 @NotNull Name name,
081 int index,
082 @NotNull SourceElement source,
083 @Nullable Function1<KotlinType, Void> reportCycleError,
084 @NotNull SupertypeLoopChecker supertypeLoopsResolver
085 ) {
086 return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source, reportCycleError,
087 supertypeLoopsResolver);
088 }
089
090 private final List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
091 private boolean initialized = false;
092
093 private TypeParameterDescriptorImpl(
094 @NotNull DeclarationDescriptor containingDeclaration,
095 @NotNull Annotations annotations,
096 boolean reified,
097 @NotNull Variance variance,
098 @NotNull Name name,
099 int index,
100 @NotNull SourceElement source,
101 @Nullable Function1<KotlinType, Void> reportCycleError,
102 @NotNull SupertypeLoopChecker supertypeLoopsChecker
103 ) {
104 super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source);
105 this.reportCycleError = reportCycleError;
106 // ?
107 this.supertypeLoopsChecker = supertypeLoopsChecker;
108 }
109
110 @NotNull
111 @Override
112 protected TypeConstructor createTypeConstructor() {
113 // TODO: Should we actually pass the annotations on to the type constructor?
114 return TypeConstructorImpl.createForTypeParameter(
115 this,
116 getAnnotations(),
117 false,
118 getName().asString(),
119 Collections.<TypeParameterDescriptor>emptyList(),
120 upperBounds
121 );
122 }
123
124 private void checkInitialized() {
125 if (!initialized) {
126 throw new IllegalStateException("Type parameter descriptor is not initialized: " + nameForAssertions());
127 }
128 }
129
130 private void checkUninitialized() {
131 if (initialized) {
132 throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions());
133 }
134 }
135
136 private String nameForAssertions() {
137 return getName() + " declared in " + DescriptorUtils.getFqName(getContainingDeclaration());
138 }
139
140 public void setInitialized() {
141 checkUninitialized();
142 initialized = true;
143 }
144
145 public void addUpperBound(@NotNull KotlinType bound) {
146 checkUninitialized();
147 doAddUpperBound(bound);
148 }
149
150 private void doAddUpperBound(KotlinType bound) {
151 upperBounds.add(bound); // TODO : Duplicates?
152 }
153
154 public void addDefaultUpperBound() {
155 checkUninitialized();
156
157 if (upperBounds.isEmpty()) {
158 doAddUpperBound(getBuiltIns(getContainingDeclaration()).getDefaultBound());
159 }
160 }
161
162 @NotNull
163 @Override
164 protected SupertypeLoopChecker getSupertypeLoopChecker() {
165 return supertypeLoopsChecker;
166 }
167
168 @Override
169 protected void reportCycleError(@NotNull KotlinType type) {
170 if (reportCycleError == null) return;
171 reportCycleError.invoke(type);
172 }
173
174 @NotNull
175 @Override
176 protected List<KotlinType> resolveUpperBounds() {
177 checkInitialized();
178 return upperBounds;
179 }
180 }