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 }