/* * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.resolve.lazy.descriptors; import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.LazyClassContext; import org.jetbrains.kotlin.resolve.lazy.LazyEntity; import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinTypeKt; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescriptor implements LazyEntity { private final LazyClassContext c; private final KtTypeParameter typeParameter; public LazyTypeParameterDescriptor( @NotNull LazyClassContext c, @NotNull LazyClassDescriptor containingDeclaration, @NotNull KtTypeParameter typeParameter, int index ) { super( c.getStorageManager(), containingDeclaration, typeParameter.getNameAsSafeName(), typeParameter.getVariance(), typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD), index, KotlinSourceElementKt.toSourceElement(typeParameter), c.getSupertypeLoopChecker()); this.c = c; this.typeParameter = typeParameter; this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this); } @Override protected void reportSupertypeLoopError(@NotNull KotlinType type) { for (KtTypeReference typeReference : getAllUpperBounds()) { if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) { c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference)); return; } } } @NotNull @Override protected List<KotlinType> resolveUpperBounds() { List<KotlinType> upperBounds = new ArrayList<>(1); for (KtTypeReference typeReference : getAllUpperBounds()) { KotlinType resolvedType = resolveBoundType(typeReference); if (!KotlinTypeKt.isError(resolvedType)) { upperBounds.add(resolvedType); } } if (upperBounds.isEmpty()) { upperBounds.add(c.getModuleDescriptor().getBuiltIns().getDefaultBound()); } return upperBounds; } private Collection<KtTypeReference> getAllUpperBounds() { return CollectionsKt.plus( typeParameter.getExtendsBound() != null ? Collections.singletonList(typeParameter.getExtendsBound()) : Collections.emptyList(), getUpperBoundsFromWhereClause() ); } private Collection<KtTypeReference> getUpperBoundsFromWhereClause() { Collection<KtTypeReference> result = new ArrayList<>(); KtClassOrObject classOrObject = KtStubbedPsiUtil.getPsiOrStubParent(typeParameter, KtClassOrObject.class, true); if (classOrObject instanceof KtClass) { for (KtTypeConstraint typeConstraint : classOrObject.getTypeConstraints()) { KtSimpleNameExpression constrainedParameterName = typeConstraint.getSubjectTypeParameterName(); if (constrainedParameterName != null) { if (getName().equals(constrainedParameterName.getReferencedNameAsName())) { c.getTrace().record(BindingContext.REFERENCE_TARGET, constrainedParameterName, this); KtTypeReference boundTypeReference = typeConstraint.getBoundTypeReference(); if (boundTypeReference != null) { result.add(boundTypeReference); } } } } } return result; } @NotNull private KotlinType resolveBoundType(@NotNull KtTypeReference boundTypeReference) { return c.getTypeResolver().resolveType( getContainingDeclaration().getScopeForClassHeaderResolution(), boundTypeReference, c.getTrace(), false ); } @NotNull @Override public LazyClassDescriptor getContainingDeclaration() { return (LazyClassDescriptor) super.getContainingDeclaration(); } @Override public void forceResolveAllContents() { ForceResolveUtil.forceResolveAllContents(getAnnotations()); getContainingDeclaration(); getDefaultType(); getIndex(); getOriginal(); ForceResolveUtil.forceResolveAllContents(getTypeConstructor()); ForceResolveUtil.forceResolveAllContents(getUpperBounds()); getVariance(); } }