org.jetbrains.kotlin.resolve.PossiblyBareType Maven / Gradle / Ivy
/*
* 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;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.types.*;
/**
* Bare types are somewhat like raw types, but in Kotlin they are only allowed on the right-hand side of is/as.
* For example:
*
* fun foo(a: Any) {
* if (a is List) {
* // a is known to be List<*> here
* }
* }
*
* Another example:
*
* fun foo(a: Collection) {
* if (a is List) {
* // a is known to be List here
* }
* }
*
* One can call reconstruct(supertype) to get an actual type from a bare type
*/
public class PossiblyBareType {
@NotNull
public static PossiblyBareType bare(@NotNull TypeConstructor bareTypeConstructor, boolean nullable) {
return new PossiblyBareType(null, bareTypeConstructor, nullable);
}
@NotNull
public static PossiblyBareType type(@NotNull KotlinType actualType) {
return new PossiblyBareType(actualType, null, false);
}
private final KotlinType actualType;
private final TypeConstructor bareTypeConstructor;
private final boolean nullable;
private PossiblyBareType(@Nullable KotlinType actualType, @Nullable TypeConstructor bareTypeConstructor, boolean nullable) {
this.actualType = actualType;
this.bareTypeConstructor = bareTypeConstructor;
this.nullable = nullable;
}
public boolean isBare() {
return actualType == null;
}
@NotNull
public KotlinType getActualType() {
//noinspection ConstantConditions
return actualType;
}
@NotNull
public TypeConstructor getBareTypeConstructor() {
//noinspection ConstantConditions
return bareTypeConstructor;
}
private boolean isBareTypeNullable() {
return nullable;
}
public boolean isNullable() {
if (isBare()) return isBareTypeNullable();
return getActualType().isMarkedNullable();
}
public PossiblyBareType makeNullable() {
if (isBare()) {
return isBareTypeNullable() ? this : bare(getBareTypeConstructor(), true);
}
return type(TypeUtils.makeNullable(getActualType()));
}
@NotNull
public TypeReconstructionResult reconstruct(@NotNull KotlinType subjectType) {
if (!isBare()) return new TypeReconstructionResult(getActualType(), true);
TypeReconstructionResult reconstructionResult = CastDiagnosticsUtil.findStaticallyKnownSubtype(
TypeUtils.makeNotNullable(subjectType),
getBareTypeConstructor()
);
KotlinType type = reconstructionResult.getResultingType();
// No need to make an absent type nullable
if (type == null) return reconstructionResult;
KotlinType resultingType = TypeUtils.makeNullableAsSpecified(type, isBareTypeNullable());
return new TypeReconstructionResult(resultingType, reconstructionResult.isAllArgumentsInferred());
}
@Override
public String toString() {
return isBare() ? "bare " + bareTypeConstructor + (isBareTypeNullable() ? "?" : "") : getActualType().toString();
}
}