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.TypeParameterDescriptor;
023 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
024 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025 import org.jetbrains.jet.lang.resolve.name.Name;
026 import org.jetbrains.jet.lang.types.JetType;
027 import org.jetbrains.jet.lang.types.TypeConstructor;
028 import org.jetbrains.jet.lang.types.TypeConstructorImpl;
029 import org.jetbrains.jet.lang.types.Variance;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031 import org.jetbrains.jet.storage.LockBasedStorageManager;
032
033 import java.util.Collections;
034 import java.util.Set;
035
036 public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor {
037 public static TypeParameterDescriptor createWithDefaultBound(
038 @NotNull DeclarationDescriptor containingDeclaration,
039 @NotNull Annotations annotations,
040 boolean reified,
041 @NotNull Variance variance,
042 @NotNull Name name,
043 int index
044 ) {
045 TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
046 typeParameterDescriptor.addUpperBound(KotlinBuiltIns.getInstance().getDefaultBound());
047 typeParameterDescriptor.setInitialized();
048 return typeParameterDescriptor;
049 }
050
051 public static TypeParameterDescriptorImpl createForFurtherModification(
052 @NotNull DeclarationDescriptor containingDeclaration,
053 @NotNull Annotations annotations,
054 boolean reified,
055 @NotNull Variance variance,
056 @NotNull Name name,
057 int index
058 ) {
059 return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index);
060 }
061
062 private final Set<JetType> upperBounds = Sets.newLinkedHashSet();
063 private boolean initialized = false;
064
065 private TypeParameterDescriptorImpl(
066 @NotNull DeclarationDescriptor containingDeclaration,
067 @NotNull Annotations annotations,
068 boolean reified,
069 @NotNull Variance variance,
070 @NotNull Name name,
071 int index
072 ) {
073 super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index);
074 }
075
076 @NotNull
077 @Override
078 protected TypeConstructor createTypeConstructor() {
079 // TODO: Should we actually pass the annotations on to the type constructor?
080 return TypeConstructorImpl.createForTypeParameter(
081 this,
082 getAnnotations(),
083 false,
084 getName().asString(),
085 Collections.<TypeParameterDescriptor>emptyList(),
086 upperBounds
087 );
088 }
089
090 private void checkInitialized() {
091 if (!initialized) {
092 throw new IllegalStateException("Type parameter descriptor is not initialized: " + nameForAssertions());
093 }
094 }
095
096 private void checkUninitialized() {
097 if (initialized) {
098 throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions());
099 }
100 }
101
102 private String nameForAssertions() {
103 return getName() + " declared in " + DescriptorUtils.getFqName(getContainingDeclaration());
104 }
105
106 public void setInitialized() {
107 checkUninitialized();
108 initialized = true;
109 }
110
111 public void addUpperBound(@NotNull JetType bound) {
112 checkUninitialized();
113 doAddUpperBound(bound);
114 }
115
116 private void doAddUpperBound(JetType bound) {
117 upperBounds.add(bound); // TODO : Duplicates?
118 }
119
120 public void addDefaultUpperBound() {
121 checkUninitialized();
122
123 if (upperBounds.isEmpty()) {
124 doAddUpperBound(KotlinBuiltIns.getInstance().getDefaultBound());
125 }
126 }
127
128 @NotNull
129 @Override
130 protected Set<JetType> resolveUpperBounds() {
131 checkInitialized();
132 return upperBounds;
133 }
134 }