/* * 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.descriptors.impl; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.KotlinTypeKt; import org.jetbrains.kotlin.types.Variance; import java.util.ArrayList; import java.util.List; import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns; public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor { @Nullable private final Function1<KotlinType, Void> reportCycleError; @NotNull public static TypeParameterDescriptor createWithDefaultBound( @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, boolean reified, @NotNull Variance variance, @NotNull Name name, int index ) { TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, SourceElement.NO_SOURCE); typeParameterDescriptor.addUpperBound(getBuiltIns(containingDeclaration).getDefaultBound()); typeParameterDescriptor.setInitialized(); return typeParameterDescriptor; } public static TypeParameterDescriptorImpl createForFurtherModification( @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, boolean reified, @NotNull Variance variance, @NotNull Name name, int index, @NotNull SourceElement source ) { return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source, /* reportSupertypeLoopError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE); } public static TypeParameterDescriptorImpl createForFurtherModification( @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, boolean reified, @NotNull Variance variance, @NotNull Name name, int index, @NotNull SourceElement source, @Nullable Function1<KotlinType, Void> reportCycleError, @NotNull SupertypeLoopChecker supertypeLoopsResolver ) { return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source, reportCycleError, supertypeLoopsResolver); } private final List<KotlinType> upperBounds = new ArrayList<KotlinType>(1); private boolean initialized = false; private TypeParameterDescriptorImpl( @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, boolean reified, @NotNull Variance variance, @NotNull Name name, int index, @NotNull SourceElement source, @Nullable Function1<KotlinType, Void> reportCycleError, @NotNull SupertypeLoopChecker supertypeLoopsChecker ) { super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source, supertypeLoopsChecker); this.reportCycleError = reportCycleError; } private void checkInitialized() { if (!initialized) { throw new IllegalStateException("Type parameter descriptor is not initialized: " + nameForAssertions()); } } private void checkUninitialized() { if (initialized) { throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions()); } } private String nameForAssertions() { return getName() + " declared in " + DescriptorUtils.getFqName(getContainingDeclaration()); } public void setInitialized() { checkUninitialized(); initialized = true; } public void addUpperBound(@NotNull KotlinType bound) { checkUninitialized(); doAddUpperBound(bound); } private void doAddUpperBound(KotlinType bound) { if (KotlinTypeKt.isError(bound)) return; upperBounds.add(bound); // TODO : Duplicates? } public void addDefaultUpperBound() { checkUninitialized(); if (upperBounds.isEmpty()) { doAddUpperBound(getBuiltIns(getContainingDeclaration()).getDefaultBound()); } } @Override protected void reportSupertypeLoopError(@NotNull KotlinType type) { if (reportCycleError == null) return; reportCycleError.invoke(type); } @NotNull @Override protected List<KotlinType> resolveUpperBounds() { checkInitialized(); return upperBounds; } }