001    /*
002     * Copyright 2010-2015 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.kotlin.resolve.lazy.descriptors;
018    
019    import kotlin.collections.CollectionsKt;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker;
022    import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor;
023    import org.jetbrains.kotlin.diagnostics.Errors;
024    import org.jetbrains.kotlin.lexer.KtTokens;
025    import org.jetbrains.kotlin.psi.*;
026    import org.jetbrains.kotlin.resolve.BindingContext;
027    import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
028    import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
029    import org.jetbrains.kotlin.resolve.lazy.LazyEntity;
030    import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
031    import org.jetbrains.kotlin.types.KotlinType;
032    
033    import java.util.ArrayList;
034    import java.util.Collection;
035    import java.util.Collections;
036    import java.util.List;
037    
038    public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescriptor implements LazyEntity {
039        private final LazyClassContext c;
040        private final KtTypeParameter typeParameter;
041    
042        public LazyTypeParameterDescriptor(
043                @NotNull LazyClassContext c,
044                @NotNull LazyClassDescriptor containingDeclaration,
045                @NotNull KtTypeParameter typeParameter,
046                int index
047        ) {
048            super(
049                    c.getStorageManager(),
050                    containingDeclaration,
051                    typeParameter.getNameAsSafeName(),
052                    typeParameter.getVariance(),
053                    typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD),
054                    index,
055                    KotlinSourceElementKt.toSourceElement(typeParameter),
056                    c.getSupertypeLoopChecker());
057            this.c = c;
058            this.typeParameter = typeParameter;
059    
060            this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this);
061        }
062    
063        @Override
064        protected void reportSupertypeLoopError(@NotNull KotlinType type) {
065            for (KtTypeReference typeReference : getAllUpperBounds()) {
066                if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) {
067                    c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference));
068                    return;
069                }
070            }
071        }
072    
073        @NotNull
074        @Override
075        protected List<KotlinType> resolveUpperBounds() {
076            List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
077    
078            for (KtTypeReference typeReference : getAllUpperBounds()) {
079                KotlinType resolvedType = resolveBoundType(typeReference);
080                if (!resolvedType.isError()) {
081                    upperBounds.add(resolvedType);
082                }
083            }
084    
085            if (upperBounds.isEmpty()) {
086                upperBounds.add(c.getModuleDescriptor().getBuiltIns().getDefaultBound());
087            }
088    
089            return upperBounds;
090        }
091    
092        private Collection<KtTypeReference> getAllUpperBounds() {
093            return CollectionsKt.plus(
094                    typeParameter.getExtendsBound() != null
095                    ? Collections.singletonList(typeParameter.getExtendsBound())
096                    : Collections.<KtTypeReference>emptyList(),
097                    getUpperBoundsFromWhereClause()
098            );
099        }
100    
101        private Collection<KtTypeReference> getUpperBoundsFromWhereClause() {
102            Collection<KtTypeReference> result = new ArrayList<KtTypeReference>();
103    
104            KtClassOrObject classOrObject = KtStubbedPsiUtil.getPsiOrStubParent(typeParameter, KtClassOrObject.class, true);
105            if (classOrObject instanceof KtClass) {
106                for (KtTypeConstraint typeConstraint : classOrObject.getTypeConstraints()) {
107                    KtSimpleNameExpression constrainedParameterName = typeConstraint.getSubjectTypeParameterName();
108                    if (constrainedParameterName != null) {
109                        if (getName().equals(constrainedParameterName.getReferencedNameAsName())) {
110                            c.getTrace().record(BindingContext.REFERENCE_TARGET, constrainedParameterName, this);
111    
112                            KtTypeReference boundTypeReference = typeConstraint.getBoundTypeReference();
113                            if (boundTypeReference != null) {
114                                result.add(boundTypeReference);
115                            }
116                        }
117                    }
118                }
119            }
120    
121            return result;
122        }
123    
124        @NotNull
125        private KotlinType resolveBoundType(@NotNull KtTypeReference boundTypeReference) {
126            return c.getTypeResolver().resolveType(
127                    getContainingDeclaration().getScopeForClassHeaderResolution(), boundTypeReference, c.getTrace(), false
128            );
129        }
130    
131        @NotNull
132        @Override
133        public LazyClassDescriptor getContainingDeclaration() {
134            return (LazyClassDescriptor) super.getContainingDeclaration();
135        }
136    
137        @Override
138        public void forceResolveAllContents() {
139            ForceResolveUtil.forceResolveAllContents(getAnnotations());
140            getContainingDeclaration();
141            getDefaultType();
142            getIndex();
143            getOriginal();
144            ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
145            ForceResolveUtil.forceResolveAllContents(getUpperBounds());
146            getVariance();
147        }
148    }