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 jet.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.ReadOnly;
022    import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
023    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
024    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
025    import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
026    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
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    import org.jetbrains.jet.storage.NotNullLazyValue;
035    import org.jetbrains.jet.storage.StorageManager;
036    
037    import java.util.Collection;
038    import java.util.Collections;
039    import java.util.List;
040    import java.util.Set;
041    
042    public abstract class AbstractLazyTypeParameterDescriptor implements TypeParameterDescriptor {
043    
044        private final Variance variance;
045        private final boolean reified;
046        private final int index;
047        private final DeclarationDescriptor containingDeclaration;
048        private final Name name;
049    
050        private final NotNullLazyValue<TypeConstructor> typeConstructor;
051        private final NotNullLazyValue<JetType> defaultType;
052        private final NotNullLazyValue<Set<JetType>> upperBounds;
053        private final NotNullLazyValue<JetType> upperBoundsAsType;
054    
055        public AbstractLazyTypeParameterDescriptor(
056                @NotNull final StorageManager storageManager,
057                @NotNull DeclarationDescriptor containingDeclaration,
058                @NotNull Name name,
059                @NotNull Variance variance,
060                boolean isReified,
061                int index
062        ) {
063            this.variance = variance;
064            this.containingDeclaration = containingDeclaration;
065            this.index = index;
066            this.name = name;
067            this.reified = isReified;
068    
069            this.typeConstructor = storageManager.createLazyValue(new Function0<TypeConstructor>() {
070                @Override
071                public TypeConstructor invoke() {
072                    return createTypeConstructor();
073                }
074            });
075            this.defaultType = storageManager.createLazyValue(new Function0<JetType>() {
076                @Override
077                public JetType invoke() {
078                    return createDefaultType(storageManager);
079                }
080            });
081            this.upperBounds = storageManager.createLazyValue(new Function0<Set<JetType>>() {
082                @Override
083                public Set<JetType> invoke() {
084                    return resolveUpperBounds();
085                }
086            });
087            this.upperBoundsAsType = storageManager.createLazyValue(new Function0<JetType>() {
088                @Override
089                public JetType invoke() {
090                    return computeUpperBoundsAsType();
091                }
092            });
093        }
094    
095        @Override
096        public boolean isReified() {
097            return reified;
098        }
099    
100        @NotNull
101        @Override
102        public Variance getVariance() {
103            return variance;
104        }
105    
106        @NotNull
107        @Override
108        public Set<JetType> getUpperBounds() {
109            return upperBounds.invoke();
110        }
111    
112        @NotNull
113        @ReadOnly
114        protected abstract Set<JetType> resolveUpperBounds();
115    
116        @NotNull
117        @Override
118        public JetType getUpperBoundsAsType() {
119            return upperBoundsAsType.invoke();
120        }
121    
122        @NotNull
123        private JetType computeUpperBoundsAsType() {
124            Set<JetType> upperBounds = getUpperBounds();
125            assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
126            JetType upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
127            if (upperBoundsAsType == null) {
128                upperBoundsAsType = KotlinBuiltIns.getInstance().getNothingType();
129            }
130            return upperBoundsAsType;
131        }
132    
133    
134        @NotNull
135        @Override
136        public Set<JetType> getLowerBounds() {
137            return Collections.singleton(getLowerBoundsAsType());
138        }
139    
140        @NotNull
141        @Override
142        public JetType getLowerBoundsAsType() {
143            return KotlinBuiltIns.getInstance().getNothingType();
144        }
145    
146        @NotNull
147        @Override
148        public TypeConstructor getTypeConstructor() {
149            return typeConstructor.invoke();
150        }
151    
152        @NotNull
153        private TypeConstructor createTypeConstructor() {
154            return new TypeConstructor() {
155                @NotNull
156                @Override
157                public Collection<JetType> getSupertypes() {
158                    return AbstractLazyTypeParameterDescriptor.this.getUpperBounds();
159                }
160    
161                @NotNull
162                @Override
163                public List<TypeParameterDescriptor> getParameters() {
164                    return Collections.emptyList();
165                }
166    
167                @Override
168                public boolean isFinal() {
169                    return false;
170                }
171    
172                @Override
173                public boolean isDenotable() {
174                    return true;
175                }
176    
177                @Override
178                public ClassifierDescriptor getDeclarationDescriptor() {
179                    return AbstractLazyTypeParameterDescriptor.this;
180                }
181    
182                @NotNull
183                @Override
184                public List<AnnotationDescriptor> getAnnotations() {
185                    return AbstractLazyTypeParameterDescriptor.this.getAnnotations();
186                }
187    
188                @Override
189                public String toString() {
190                    return getName().toString();
191                }
192            };
193        }
194    
195        @NotNull
196        @Override
197        public JetType getDefaultType() {
198            return defaultType.invoke();
199        }
200    
201        @NotNull
202        private JetType createDefaultType(@NotNull StorageManager storageManager) {
203            return new JetTypeImpl(getTypeConstructor(), new LazyScopeAdapter(storageManager.createLazyValue(
204                    new Function0<JetScope>() {
205                        @Override
206                        public JetScope invoke() {
207                            return getUpperBoundsAsType().getMemberScope();
208                        }
209                    }
210            )));
211        }
212    
213        @Override
214        public JetType getClassObjectType() {
215            return null;
216        }
217    
218        @NotNull
219        @Override
220        public DeclarationDescriptor getOriginal() {
221            return this;
222        }
223    
224        @NotNull
225        @Override
226        public DeclarationDescriptor getContainingDeclaration() {
227            return containingDeclaration;
228        }
229    
230        @NotNull
231        @Override
232        @Deprecated
233        public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
234            throw new UnsupportedOperationException("Don't call substitute() on type parameters");
235        }
236    
237        @Override
238        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
239            return visitor.visitTypeParameterDescriptor(this, data);
240        }
241    
242        @Override
243        public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
244            visitor.visitTypeParameterDescriptor(this, null);
245        }
246    
247        @Override
248        public int getIndex() {
249            return index;
250        }
251    
252        @NotNull
253        @Override
254        public List<AnnotationDescriptor> getAnnotations() {
255            return Collections.emptyList(); // TODO
256        }
257    
258        @NotNull
259        @Override
260        public Name getName() {
261            return name;
262        }
263    
264        @Override
265        public String toString() {
266            try {
267                return DescriptorRenderer.DEBUG_TEXT.render(this);
268            }
269            catch (Exception e) {
270                return this.getClass().getName() + "@" + System.identityHashCode(this);
271            }
272        }
273    }