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