/*
* 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;
}
}