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.resolve.lazy.descriptors;
018    
019    import com.intellij.openapi.util.Computable;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
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.AnnotationDescriptor;
026    import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
027    import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
028    import org.jetbrains.jet.lang.resolve.name.Name;
029    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
030    import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
031    import org.jetbrains.jet.lang.types.*;
032    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
033    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
034    import org.jetbrains.jet.renderer.DescriptorRenderer;
035    import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValue;
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 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 Computable<TypeConstructor>() {
070                @Override
071                public TypeConstructor compute() {
072                    return createTypeConstructor();
073                }
074            });
075            this.defaultType = storageManager.createLazyValue(new Computable<JetType>() {
076                @Override
077                public JetType compute() {
078                    return createDefaultType();
079                }
080            });
081            this.upperBounds = storageManager.createLazyValue(new Computable<Set<JetType>>() {
082                @Override
083                public Set<JetType> compute() {
084                    return resolveUpperBounds();
085                }
086            });
087            this.upperBoundsAsType = storageManager.createLazyValue(new Computable<JetType>() {
088                @Override
089                public JetType compute() {
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.compute();
110        }
111    
112        @NotNull
113        protected abstract Set<JetType> resolveUpperBounds();
114    
115        @NotNull
116        @Override
117        public JetType getUpperBoundsAsType() {
118            return upperBoundsAsType.compute();
119        }
120    
121        @NotNull
122        private JetType computeUpperBoundsAsType() {
123            Set<JetType> upperBounds = getUpperBounds();
124            assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
125            JetType upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
126            if (upperBoundsAsType == null) {
127                upperBoundsAsType = KotlinBuiltIns.getInstance().getNothingType();
128            }
129            return upperBoundsAsType;
130        }
131    
132    
133        @NotNull
134        @Override
135        public Set<JetType> getLowerBounds() {
136            return Collections.singleton(getLowerBoundsAsType());
137        }
138    
139        @NotNull
140        @Override
141        public JetType getLowerBoundsAsType() {
142            return KotlinBuiltIns.getInstance().getNothingType();
143        }
144    
145        @NotNull
146        @Override
147        public TypeConstructor getTypeConstructor() {
148            return typeConstructor.compute();
149        }
150    
151        @NotNull
152        private TypeConstructor createTypeConstructor() {
153            return new TypeConstructor() {
154                @NotNull
155                @Override
156                public Collection<JetType> getSupertypes() {
157                    return AbstractLazyTypeParameterDescriptor.this.getUpperBounds();
158                }
159    
160                @NotNull
161                @Override
162                public List<TypeParameterDescriptor> getParameters() {
163                    return Collections.emptyList();
164                }
165    
166                @Override
167                public boolean isSealed() {
168                    return false;
169                }
170    
171                @Override
172                public boolean isDenotable() {
173                    return true;
174                }
175    
176                @Override
177                public ClassifierDescriptor getDeclarationDescriptor() {
178                    return AbstractLazyTypeParameterDescriptor.this;
179                }
180    
181                @Override
182                public List<AnnotationDescriptor> getAnnotations() {
183                    return AbstractLazyTypeParameterDescriptor.this.getAnnotations();
184                }
185    
186                @Override
187                public String toString() {
188                    return getName().toString();
189                }
190            };
191        }
192    
193        @NotNull
194        @Override
195        public JetType getDefaultType() {
196            return defaultType.compute();
197        }
198    
199        @NotNull
200        private JetType createDefaultType() {
201            return new JetTypeImpl(getTypeConstructor(), new LazyScopeAdapter(new RecursionIntolerantLazyValue<JetScope>() {
202                            @Override
203                            protected JetScope compute() {
204                                return getUpperBoundsAsType().getMemberScope();
205                            }
206                        }));
207        }
208    
209        @Override
210        public JetType getClassObjectType() {
211            return null;
212        }
213    
214        @NotNull
215        @Override
216        public DeclarationDescriptor getOriginal() {
217            return this;
218        }
219    
220        @NotNull
221        @Override
222        public DeclarationDescriptor getContainingDeclaration() {
223            return containingDeclaration;
224        }
225    
226        @NotNull
227        @Override
228        @Deprecated
229        public TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
230            throw new UnsupportedOperationException("Don't call substitute() on type parameters");
231        }
232    
233        @Override
234        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
235            return visitor.visitTypeParameterDescriptor(this, data);
236        }
237    
238        @Override
239        public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
240            visitor.visitTypeParameterDescriptor(this, null);
241        }
242    
243        @Override
244        public int getIndex() {
245            return index;
246        }
247    
248        @Override
249        public List<AnnotationDescriptor> getAnnotations() {
250            return Collections.emptyList(); // TODO
251        }
252    
253        @NotNull
254        @Override
255        public Name getName() {
256            return name;
257        }
258    
259        @Override
260        public String toString() {
261            try {
262                return DescriptorRenderer.DEBUG_TEXT.render(this);
263            }
264            catch (Exception e) {
265                return this.getClass().getName() + "@" + System.identityHashCode(this);
266            }
267        }
268    }