From 956f8ad5e9e229828af6773197df8723f139a65c Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Sun, 16 Sep 2018 23:58:11 +0300 Subject: [PATCH] Support deserialized contracts in common code #KT-26687 Fixed --- .../analyzer/common/CommonAnalyzerFacade.kt | 2 ++ .../testData/multiplatform/contracts/common.kt | 15 +++++++++++++++ .../testData/multiplatform/contracts/js.kt | 15 +++++++++++++++ .../testData/multiplatform/contracts/jvm.kt | 15 +++++++++++++++ .../multiplatform/contracts/output.txt | 11 +++++++++++ .../MultiPlatformIntegrationTestGenerated.java | 18 ++++++++++++++++++ .../MetadataPackageFragmentProvider.kt | 5 +++-- .../base_common_dep(stdlib)/common.kt | 14 ++++++++++++++ .../contracts/base_js_dep(stdlib)/js.kt | 14 ++++++++++++++ .../base_jvm_dep(stdlib)_dep(fulljdk)/jvm.kt | 14 ++++++++++++++ ...MultiPlatformHighlightingTestGenerated.java | 5 +++++ 11 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/multiplatform/contracts/common.kt create mode 100644 compiler/testData/multiplatform/contracts/js.kt create mode 100644 compiler/testData/multiplatform/contracts/jvm.kt create mode 100644 compiler/testData/multiplatform/contracts/output.txt create mode 100644 idea/testData/multiModuleHighlighting/multiplatform/contracts/base_common_dep(stdlib)/common.kt create mode 100644 idea/testData/multiModuleHighlighting/multiplatform/contracts/base_js_dep(stdlib)/js.kt create mode 100644 idea/testData/multiModuleHighlighting/multiplatform/contracts/base_jvm_dep(stdlib)_dep(fulljdk)/jvm.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonAnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonAnalyzerFacade.kt index 389ec5c0a2f..8e088978b0a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonAnalyzerFacade.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/common/CommonAnalyzerFacade.kt @@ -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() + useImpl() val metadataFinderFactory = ServiceManager.getService(moduleContext.project, MetadataFinderFactory::class.java) ?: error("No MetadataFinderFactory in project") diff --git a/compiler/testData/multiplatform/contracts/common.kt b/compiler/testData/multiplatform/contracts/common.kt new file mode 100644 index 00000000000..407a77b3dfd --- /dev/null +++ b/compiler/testData/multiplatform/contracts/common.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME +package common + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/compiler/testData/multiplatform/contracts/js.kt b/compiler/testData/multiplatform/contracts/js.kt new file mode 100644 index 00000000000..861bd6540c5 --- /dev/null +++ b/compiler/testData/multiplatform/contracts/js.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME +package js + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/compiler/testData/multiplatform/contracts/jvm.kt b/compiler/testData/multiplatform/contracts/jvm.kt new file mode 100644 index 00000000000..ca40a7839a8 --- /dev/null +++ b/compiler/testData/multiplatform/contracts/jvm.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME +package jvm + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/compiler/testData/multiplatform/contracts/output.txt b/compiler/testData/multiplatform/contracts/output.txt new file mode 100644 index 00000000000..ac1ad3921a5 --- /dev/null +++ b/compiler/testData/multiplatform/contracts/output.txt @@ -0,0 +1,11 @@ +-- Common -- +Exit code: OK +Output: + +-- JVM -- +Exit code: OK +Output: + +-- JS -- +Exit code: OK +Output: diff --git a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java index b2e18dab20f..df008e9f3ac 100644 --- a/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/multiplatform/MultiPlatformIntegrationTestGenerated.java @@ -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) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt index 98749f7df18..94ec6f32819 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt @@ -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 ) diff --git a/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_common_dep(stdlib)/common.kt b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_common_dep(stdlib)/common.kt new file mode 100644 index 00000000000..67f4c130160 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_common_dep(stdlib)/common.kt @@ -0,0 +1,14 @@ +package test.common + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_js_dep(stdlib)/js.kt b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_js_dep(stdlib)/js.kt new file mode 100644 index 00000000000..2de85dbfbfa --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_js_dep(stdlib)/js.kt @@ -0,0 +1,14 @@ +package test.js + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_jvm_dep(stdlib)_dep(fulljdk)/jvm.kt b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_jvm_dep(stdlib)_dep(fulljdk)/jvm.kt new file mode 100644 index 00000000000..89ad4f6f9e6 --- /dev/null +++ b/idea/testData/multiModuleHighlighting/multiplatform/contracts/base_jvm_dep(stdlib)_dep(fulljdk)/jvm.kt @@ -0,0 +1,14 @@ +package test.jvm + +fun test(x: List?) { + // 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? + } +} + +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 +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTestGenerated.java index f6ef438463c..a58816b06a4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/MultiPlatformHighlightingTestGenerated.java @@ -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/");