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.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 );
057 this.c = c;
058 this.typeParameter = typeParameter;
059
060 this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this);
061 }
062
063 @NotNull
064 @Override
065 protected SupertypeLoopChecker getSupertypeLoopChecker() {
066 return c.getSupertypeLoopChecker();
067 }
068
069 @Override
070 protected void reportCycleError(@NotNull KotlinType type) {
071 for (KtTypeReference typeReference : getAllUpperBounds()) {
072 if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) {
073 c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference));
074 return;
075 }
076 }
077 }
078
079 @NotNull
080 @Override
081 protected List<KotlinType> resolveUpperBounds() {
082 List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
083
084 for (KtTypeReference typeReference : getAllUpperBounds()) {
085 upperBounds.add(resolveBoundType(typeReference));
086 }
087
088 if (upperBounds.isEmpty()) {
089 upperBounds.add(c.getModuleDescriptor().getBuiltIns().getDefaultBound());
090 }
091
092 return upperBounds;
093 }
094
095 private Collection<KtTypeReference> getAllUpperBounds() {
096 return CollectionsKt.plus(
097 typeParameter.getExtendsBound() != null
098 ? Collections.singletonList(typeParameter.getExtendsBound())
099 : Collections.<KtTypeReference>emptyList(),
100 getUpperBoundsFromWhereClause()
101 );
102 }
103
104 private Collection<KtTypeReference> getUpperBoundsFromWhereClause() {
105 Collection<KtTypeReference> result = new ArrayList<KtTypeReference>();
106
107 KtClassOrObject classOrObject = KtStubbedPsiUtil.getPsiOrStubParent(typeParameter, KtClassOrObject.class, true);
108 if (classOrObject instanceof KtClass) {
109 for (KtTypeConstraint typeConstraint : classOrObject.getTypeConstraints()) {
110 KtSimpleNameExpression constrainedParameterName = typeConstraint.getSubjectTypeParameterName();
111 if (constrainedParameterName != null) {
112 if (getName().equals(constrainedParameterName.getReferencedNameAsName())) {
113 c.getTrace().record(BindingContext.REFERENCE_TARGET, constrainedParameterName, this);
114
115 KtTypeReference boundTypeReference = typeConstraint.getBoundTypeReference();
116 if (boundTypeReference != null) {
117 result.add(boundTypeReference);
118 }
119 }
120 }
121 }
122 }
123
124 return result;
125 }
126
127 @NotNull
128 private KotlinType resolveBoundType(@NotNull KtTypeReference boundTypeReference) {
129 return c.getTypeResolver().resolveType(
130 getContainingDeclaration().getScopeForClassHeaderResolution(), boundTypeReference, c.getTrace(), false
131 );
132 }
133
134 @NotNull
135 @Override
136 public LazyClassDescriptor getContainingDeclaration() {
137 return (LazyClassDescriptor) super.getContainingDeclaration();
138 }
139
140 @Override
141 public void forceResolveAllContents() {
142 ForceResolveUtil.forceResolveAllContents(getAnnotations());
143 getContainingDeclaration();
144 getDefaultType();
145 getIndex();
146 ForceResolveUtil.forceResolveAllContents(getLowerBounds());
147 getOriginal();
148 ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
149 ForceResolveUtil.forceResolveAllContents(getUpperBounds());
150 getVariance();
151 }
152 }