Add serialization/deserialization of definitely-not-null types

^KT-26245 In Progress
This commit is contained in:
Denis.Zharkov
2021-04-06 17:42:56 +03:00
committed by TeamCityServer
parent 6ca6bb2d45
commit 30eb9ad32f
19 changed files with 98 additions and 11 deletions
@@ -0,0 +1 @@
public final fun <T> foo(x: R|T!!|, y: R|kotlin/collections/List<T!!>|, z: R|(T!!) -> T!!|): R|T!!|
@@ -132,9 +132,16 @@ class FirTypeDeserializer(
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> = fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
(fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty() (fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty()
fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeLookupTagBasedType? { fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeSimpleKotlinType? {
val constructor = typeSymbol(proto) ?: return null val constructor = typeSymbol(proto) ?: return null
if (constructor is ConeTypeParameterLookupTag) return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable) if (constructor is ConeTypeParameterLookupTag) {
return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable).let {
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(proto.flags))
ConeDefinitelyNotNullType.create(it)
else
it
}
}
if (constructor !is ConeClassLikeLookupTag) return null if (constructor !is ConeClassLikeLookupTag) return null
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> = fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
@@ -598,10 +598,16 @@ class FirElementSerializer private constructor(
} }
} }
private fun typeProto(type: ConeKotlinType, toSuper: Boolean = false, correspondingTypeRef: FirTypeRef? = null): ProtoBuf.Type.Builder { private fun typeProto(
type: ConeKotlinType,
toSuper: Boolean = false,
correspondingTypeRef: FirTypeRef? = null,
isDefinitelyNotNullType: Boolean = false,
): ProtoBuf.Type.Builder {
val builder = ProtoBuf.Type.newBuilder() val builder = ProtoBuf.Type.newBuilder()
when (type) { when (type) {
is ConeDefinitelyNotNullType -> return typeProto(type, toSuper, correspondingTypeRef, isDefinitelyNotNullType = true)
is ConeKotlinErrorType -> { is ConeKotlinErrorType -> {
extension.serializeErrorType(type, builder) extension.serializeErrorType(type, builder)
return builder return builder
@@ -623,7 +629,7 @@ class FirElementSerializer private constructor(
session, CONTINUATION_INTERFACE_CLASS_ID session, CONTINUATION_INTERFACE_CLASS_ID
) )
val functionType = typeProto(runtimeFunctionType) val functionType = typeProto(runtimeFunctionType)
functionType.flags = Flags.getTypeFlags(true) functionType.flags = Flags.getTypeFlags(true, false)
return functionType return functionType
} }
fillFromPossiblyInnerType(builder, type) fillFromPossiblyInnerType(builder, type)
@@ -640,8 +646,11 @@ class FirElementSerializer private constructor(
} else { } else {
builder.typeParameter = getTypeParameterId(typeParameter) builder.typeParameter = getTypeParameterId(typeParameter)
} }
if (isDefinitelyNotNullType) {
builder.flags = Flags.getTypeFlags(false, isDefinitelyNotNullType)
}
} }
is ConeDefinitelyNotNullType,
is ConeIntersectionType -> { is ConeIntersectionType -> {
val approximatedType = if (toSuper) { val approximatedType = if (toSuper) {
typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.PublicDeclaration) typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.PublicDeclaration)
@@ -584,7 +584,7 @@ class DescriptorSerializer private constructor(
if (type.isSuspendFunctionType) { if (type.isSuspendFunctionType) {
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines())) val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines()))
functionType.flags = Flags.getTypeFlags(true) functionType.flags = Flags.getTypeFlags(true, false)
return functionType return functionType
} }
@@ -600,6 +600,8 @@ class DescriptorSerializer private constructor(
builder.typeParameter = getTypeParameterId(descriptor) builder.typeParameter = getTypeParameterId(descriptor)
} }
builder.flags = Flags.getTypeFlags(false, type is DefinitelyNotNullType)
assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" } assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" }
} }
} }
@@ -0,0 +1,5 @@
// !LANGUAGE: +DefinitelyNotNullTypeParameters
// COMPILER_ARGUMENTS: -XXLanguage:+DefinitelyNotNullTypeParameters
package test
fun <T> foo(x: T!!, y: List<T!!>, z: (T!!) -> T!!): T!! = x
@@ -0,0 +1,3 @@
package test
public fun </*0*/ T> foo(/*0*/ x: T!!, /*1*/ y: kotlin.collections.List<T!!>, /*2*/ z: (T!!) -> T!!): T!!
@@ -2116,6 +2116,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -438,6 +438,11 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -2117,6 +2117,11 @@ public class IrLoadJavaTestGenerated extends AbstractIrLoadJavaTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -2116,6 +2116,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.descriptors.runtime.components.ReflectKotlinClass
import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeModuleData import org.jetbrains.kotlin.descriptors.runtime.components.RuntimeModuleData
import org.jetbrains.kotlin.descriptors.runtime.structure.classId import org.jetbrains.kotlin.descriptors.runtime.structure.classId
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest
import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
@@ -131,6 +132,9 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() {
val environment = KotlinTestUtils.createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea( val environment = KotlinTestUtils.createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(
testRootDisposable, ConfigurationKind.ALL, jdkKind testRootDisposable, ConfigurationKind.ALL, jdkKind
) )
AbstractLoadJavaTest.updateConfigurationWithDirectives(file.readText(), environment.configuration)
for (root in environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) { for (root in environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) {
LOG.info("root: $root") LOG.info("root: $root")
} }
@@ -440,6 +440,11 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -101,7 +101,12 @@ class TypeDeserializer(
Flags.SUSPEND_TYPE.get(proto.flags) -> Flags.SUSPEND_TYPE.get(proto.flags) ->
createSuspendFunctionType(annotations, constructor, arguments, proto.nullable) createSuspendFunctionType(annotations, constructor, arguments, proto.nullable)
else -> else ->
KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable).let {
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(proto.flags))
DefinitelyNotNullType.makeDefinitelyNotNull(it) ?: error("null DefinitelyNotNullType for '$it'")
else
it
}
} }
val computedType = proto.abbreviatedType(c.typeTable)?.let { val computedType = proto.abbreviatedType(c.typeTable)?.let {
@@ -15,6 +15,7 @@ public class Flags {
// Types // Types
public static final BooleanFlagField SUSPEND_TYPE = FlagField.booleanFirst(); public static final BooleanFlagField SUSPEND_TYPE = FlagField.booleanFirst();
public static final BooleanFlagField DEFINITELY_NOT_NULL_TYPE = FlagField.booleanAfter(SUSPEND_TYPE);
// Common for declarations // Common for declarations
@@ -85,8 +86,8 @@ public class Flags {
// --- // ---
public static int getTypeFlags(boolean isSuspend) { public static int getTypeFlags(boolean isSuspend, boolean isDefinitelyNotNull) {
return SUSPEND_TYPE.toFlags(isSuspend); return SUSPEND_TYPE.toFlags(isSuspend) | DEFINITELY_NOT_NULL_TYPE.toFlags(isDefinitelyNotNull);
} }
public static int getClassFlags( public static int getClassFlags(
@@ -74,7 +74,14 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) { private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
createTypeAnnotationStubs(parent, type, annotations) createTypeAnnotationStubs(parent, type, annotations)
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableTypeParent(parent, type)) val nullableParentWrapper = nullableTypeParent(parent, type)
val definitelyNotNullTypeWrapper =
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(type.flags))
KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.DEFINITELY_NOT_NULL_TYPE)
else
nullableParentWrapper
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), definitelyNotNullTypeWrapper)
} }
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) { private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
import org.jetbrains.kotlin.idea.decompiler.classFile.KotlinClsStubBuilder import org.jetbrains.kotlin.idea.decompiler.classFile.KotlinClsStubBuilder
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
import org.jetbrains.kotlin.jvm.compiler.AbstractLoadJavaTest
import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil
import org.jetbrains.kotlin.psi.stubs.elements.KtFileStubBuilder import org.jetbrains.kotlin.psi.stubs.elements.KtFileStubBuilder
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
@@ -43,6 +44,9 @@ abstract class AbstractLoadJavaClsStubTest : TestCaseWithTmpdir() {
if (useTypeTableInSerializer) { if (useTypeTableInSerializer) {
configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true) configuration.put(JVMConfigurationKeys.USE_TYPE_TABLE, true)
} }
AbstractLoadJavaTest.updateConfigurationWithDirectives(ktFile.readText(), configuration)
val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
environment.projectEnvironment.environment.application.registerService( environment.projectEnvironment.environment.application.registerService(
IDEKotlinBinaryClassCache::class.java, IDEKotlinBinaryClassCache::class.java,
@@ -438,6 +438,11 @@ public class LoadJavaClsStubTestGenerated extends AbstractLoadJavaClsStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.test.AstAccessControl import org.jetbrains.kotlin.idea.test.AstAccessControl
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.withCustomCompilerOptions
import org.jetbrains.kotlin.load.java.descriptors.PossiblyExternalAnnotationDescriptor import org.jetbrains.kotlin.load.java.descriptors.PossiblyExternalAnnotationDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -33,7 +34,10 @@ abstract class AbstractResolveByStubTest : KotlinLightCodeInsightFixtureTestCase
myFixture.configureByFile(fileName) myFixture.configureByFile(fileName)
val shouldFail = getTestName(false) == "ClassWithConstVal" val shouldFail = getTestName(false) == "ClassWithConstVal"
AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) { AstAccessControl.testWithControlledAccessToAst(shouldFail, project, testRootDisposable) {
performTest(testPath()) val path = testPath()
withCustomCompilerOptions(File(path).readText(), project, module) {
performTest(path)
}
} }
} }
@@ -438,6 +438,11 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ClassLiteralArgument.kt");
} }
@TestMetadata("DefinitelyNotNull.kt")
public void testDefinitelyNotNull() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/DefinitelyNotNull.kt");
}
@TestMetadata("ReceiverParameter.kt") @TestMetadata("ReceiverParameter.kt")
public void testReceiverParameter() throws Exception { public void testReceiverParameter() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt"); runTest("compiler/testData/loadJava/compiledKotlin/annotations/types/ReceiverParameter.kt");