Support deserialized contracts in common code

#KT-26687 Fixed
This commit is contained in:
Denis Zharkov
2018-09-16 23:58:11 +03:00
parent ed8aad6149
commit 956f8ad5e9
11 changed files with 126 additions and 2 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
@@ -165,6 +166,7 @@ object CommonAnalyzerFacade : ResolverForModuleFactory() {
useInstance(metadataPartProvider)
useInstance(declarationProviderFactory)
useImpl<MetadataPackageFragmentProvider>()
useImpl<ContractDeserializerImpl>()
val metadataFinderFactory = ServiceManager.getService(moduleContext.project, MetadataFinderFactory::class.java)
?: error("No MetadataFinderFactory in project")
+15
View File
@@ -0,0 +1,15 @@
// WITH_RUNTIME
package common
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
+15
View File
@@ -0,0 +1,15 @@
// WITH_RUNTIME
package js
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
+15
View File
@@ -0,0 +1,15 @@
// WITH_RUNTIME
package jvm
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
+11
View File
@@ -0,0 +1,11 @@
-- Common --
Exit code: OK
Output:
-- JVM --
Exit code: OK
Output:
-- JS --
Exit code: OK
Output:
@@ -39,6 +39,11 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform
runTest("compiler/testData/multiplatform/compilerArguments/");
}
@TestMetadata("contracts")
public void testContracts() throws Exception {
runTest("compiler/testData/multiplatform/contracts/");
}
@TestMetadata("createImplClassInPlatformModule")
public void testCreateImplClassInPlatformModule() throws Exception {
runTest("compiler/testData/multiplatform/createImplClassInPlatformModule/");
@@ -335,6 +340,19 @@ public class MultiPlatformIntegrationTestGenerated extends AbstractMultiPlatform
}
}
@TestMetadata("compiler/testData/multiplatform/contracts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Contracts extends AbstractMultiPlatformIntegrationTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInContracts() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/multiplatform/contracts"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
}
@TestMetadata("compiler/testData/multiplatform/createImplClassInPlatformModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -40,7 +40,8 @@ class MetadataPackageFragmentProvider(
finder: KotlinMetadataFinder,
moduleDescriptor: ModuleDescriptor,
notFoundClasses: NotFoundClasses,
private val metadataPartProvider: MetadataPartProvider
private val metadataPartProvider: MetadataPartProvider,
contractDeserializer: ContractDeserializer
) : AbstractDeserializedPackageFragmentProvider(storageManager, finder, moduleDescriptor) {
init {
components = DeserializationComponents(
@@ -56,7 +57,7 @@ class MetadataPackageFragmentProvider(
FlexibleTypeDeserializer.ThrowException,
emptyList(),
notFoundClasses,
ContractDeserializer.DEFAULT,
contractDeserializer,
AdditionalClassPartsProvider.None, PlatformDependentDeclarationFilter.All,
BuiltInSerializerProtocol.extensionRegistry
)
@@ -0,0 +1,14 @@
package test.common
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
@@ -0,0 +1,14 @@
package test.js
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
@@ -0,0 +1,14 @@
package test.jvm
fun test(x: List<Int>?) {
// If the function returns false, the value is definitely not null:
if (!x.isNullOrEmpty()) {
println(x.size) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type List<Int>?
}
}
fun test(x: Any?) {
// If the function returns (does not throw), then the argument is true:
require(x is String)
println(x.length) // Unresolved reference: length
}
@@ -44,6 +44,11 @@ public class MultiPlatformHighlightingTestGenerated extends AbstractMultiPlatfor
runTest("idea/testData/multiModuleHighlighting/multiplatform/catchHeaderExceptionInPlatformModule/");
}
@TestMetadata("contracts")
public void testContracts() throws Exception {
runTest("idea/testData/multiModuleHighlighting/multiplatform/contracts/");
}
@TestMetadata("depends")
public void testDepends() throws Exception {
runTest("idea/testData/multiModuleHighlighting/multiplatform/depends/");