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    }