From af1264a46d5ee2dc6bbd1a58124f3929136408c8 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 28 Oct 2016 11:20:29 +0300 Subject: [PATCH] Support platform/impl modifiers for functions Also add a new capability for ModuleDescriptor, which is used to obtain the platform in the multi-platform scenario in tests. Suppress the following errors for platform functions: "function has no body" and "nothing to inline". Also do not report redeclaration between platform and non-platform functions because this is the case when the common + platform-specific code are analyzed together. Note that some diagnostics reported in tests are not yet implemented in this commit, they appear in subsequent commits --- .../jetbrains/kotlin/diagnostics/Errors.java | 5 ++ .../rendering/DefaultErrorMessages.java | 3 + .../kotlin/resolve/DeclarationsChecker.kt | 18 +++- .../resolve/FunctionDescriptorResolver.kt | 10 +++ .../kotlin/resolve/MultiTargetPlatform.kt | 38 +++++++++ .../kotlin/resolve/OverloadResolver.kt | 14 ++++ .../resolve/inline/InlineAnalyzerExtension.kt | 24 ++---- .../topLevelFun/callPlatformFun.kt | 25 ++++++ .../topLevelFun/callPlatformFun.txt | 21 +++++ .../conflictingPlatformDeclarations.kt | 8 ++ .../conflictingPlatformDeclarations.txt | 5 ++ .../conflictingPlatformDefinitions.kt | 17 ++++ .../conflictingPlatformDefinitions.txt | 18 ++++ ...arationAndDefinitionInDIfferentPackages.kt | 18 ++++ ...rationAndDefinitionInDIfferentPackages.txt | 28 +++++++ .../declarationWithoutDefinition.kt | 5 ++ .../declarationWithoutDefinition.txt | 3 + .../topLevelFun/defaultArguments.kt | 5 ++ .../topLevelFun/defaultArguments.txt | 3 + .../definitionWithoutDeclaration.kt | 5 ++ .../definitionWithoutDeclaration.txt | 3 + .../multiplatform/topLevelFun/inlineFun.kt | 18 ++++ .../multiplatform/topLevelFun/inlineFun.txt | 19 +++++ .../platformDeclarationWithBody.kt | 9 ++ .../platformDeclarationWithBody.txt | 5 ++ .../platformDefinitionWithoutBody.kt | 12 +++ .../platformDefinitionWithoutBody.txt | 11 +++ .../topLevelFun/simplePlatformFun.kt | 12 +++ .../topLevelFun/simplePlatformFun.txt | 16 ++++ .../checkers/AbstractDiagnosticsTest.java | 20 ++++- .../AbstractDiagnosticsTestWithJsStdLib.java | 4 +- .../checkers/DiagnosticsTestGenerated.java | 84 +++++++++++++++++++ 32 files changed, 463 insertions(+), 23 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/MultiTargetPlatform.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.txt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 835f63b119e..f2daef45815 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -489,6 +489,11 @@ public interface Errors { DiagnosticFactory0 DATA_CLASS_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 DATA_CLASS_NOT_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR); + // Multi-platform projects + + DiagnosticFactory0 PLATFORM_DECLARATION_WITH_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Errors/warnings inside code blocks diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 1e8dbd2585f..3c2a408f60e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -257,6 +257,9 @@ public class DefaultErrorMessages { MAP.put(USELESS_VARARG_ON_PARAMETER, "Vararg on this parameter is useless"); MAP.put(MULTIPLE_VARARG_PARAMETERS, "Multiple vararg-parameters are prohibited"); + MAP.put(PLATFORM_DECLARATION_WITH_BODY, "Platform declaration must not have a body"); + MAP.put(PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER, "Platform declaration cannot have parameters with default values"); + MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here"); MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index e58187b8f8a..939a3cdf67e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -732,10 +732,26 @@ class DeclarationsChecker( } } else /* top-level only */ { - if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) { + if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier && !functionDescriptor.isPlatform) { trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)) } } + + if (functionDescriptor.isPlatform) { + checkPlatformFunction(function) + } + } + + private fun checkPlatformFunction(function: KtNamedFunction) { + if (function.hasBody()) { + trace.report(PLATFORM_DECLARATION_WITH_BODY.on(function)) + } + + for (parameter in function.valueParameters) { + if (parameter.hasDefaultValue()) { + trace.report(PLATFORM_DECLARATION_WITH_DEFAULT_PARAMETER.on(parameter)) + } + } } private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index cfe15d628cc..326e2df139e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -184,6 +184,10 @@ class FunctionDescriptorResolver( functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD) functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD) functionDescriptor.isSuspend = function.hasModifier(KtTokens.SUSPEND_KEYWORD) + functionDescriptor.isPlatform = function.hasModifier(KtTokens.PLATFORM_KEYWORD) || + containingDescriptor is ClassDescriptor && containingDescriptor.isPlatform + functionDescriptor.isImpl = function.hasModifier(KtTokens.IMPL_KEYWORD) + receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.annotations) } for (valueParameterDescriptor in valueParameterDescriptors) { ForceResolveUtil.forceResolveAllContents(valueParameterDescriptor.type.annotations) @@ -293,6 +297,12 @@ class FunctionDescriptorResolver( isPrimary, declarationToTrace.toSourceElement() ) + if (classDescriptor.isPlatform) { + constructorDescriptor.isPlatform = true + } + if (classDescriptor.isImpl) { + constructorDescriptor.isImpl = true + } trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor) val parameterScope = LexicalWritableScope( scope, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/MultiTargetPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/MultiTargetPlatform.kt new file mode 100644 index 00000000000..4309fe13367 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/MultiTargetPlatform.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2016 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.kotlin.descriptors.MemberDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +sealed class MultiTargetPlatform { + object Common : MultiTargetPlatform() + + data class Specific(val platform: String) : MultiTargetPlatform() + + companion object { + @JvmField + val CAPABILITY = ModuleDescriptor.Capability("MULTI_TARGET_PLATFORM") + } +} + +fun ModuleDescriptor.getMultiTargetPlatform(): MultiTargetPlatform? = + module.getCapability(MultiTargetPlatform.CAPABILITY) + +fun MemberDescriptor.getMultiTargetPlatform(): String? = + (module.getMultiTargetPlatform() as? MultiTargetPlatform.Specific)?.platform diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadResolver.kt index aff68980102..8e4c939f321 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadResolver.kt @@ -252,6 +252,8 @@ class OverloadResolver( if (member1 == member2) continue if (isConstructorsOfDifferentRedeclaredClasses(member1, member2)) continue if (isTopLevelMainInDifferentFiles(member1, member2)) continue + if (isDefinitionsForDifferentPlatforms(member1, member2)) continue + if (isPlatformDeclarationAndDefinition(member1, member2) || isPlatformDeclarationAndDefinition(member2, member1)) continue if (!overloadChecker.isOverloadable(member1, member2)) { redeclarations.add(member1) @@ -281,6 +283,18 @@ class OverloadResolver( return file1 == null || file2 == null || file1 !== file2 } + private fun isPlatformDeclarationAndDefinition(declaration: DeclarationDescriptor, definition: DeclarationDescriptor): Boolean { + return declaration is MemberDescriptor && declaration.isPlatform && + definition is MemberDescriptor && !definition.isPlatform + } + + private fun isDefinitionsForDifferentPlatforms(member1: DeclarationDescriptorNonRoot, member2: DeclarationDescriptorNonRoot): Boolean { + if (member1 !is MemberDescriptor || member2 !is MemberDescriptor) return false + + return member1.isImpl && member2.isImpl && + member1.getMultiTargetPlatform() != member2.getMultiTargetPlatform() + } + private fun reportRedeclarations(redeclarations: Collection) { if (redeclarations.isEmpty()) return diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt index 2c04e79c245..cec502d16c2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt @@ -134,25 +134,17 @@ object InlineAnalyzerExtension : AnalyzerExtensions.AnalyzerExtension { containingDeclaration is ClassDescriptor && containingDeclaration.modality == Modality.FINAL } - private fun checkHasInlinableAndNullability( - functionDescriptor: FunctionDescriptor, - function: KtFunction, - trace: BindingTrace) { - var hasInlinable = false - val parameters = functionDescriptor.valueParameters - var index = 0 - for (parameter in parameters) { - hasInlinable = hasInlinable or checkInlinableParameter(parameter, function.valueParameters[index++], functionDescriptor, trace) + private fun checkHasInlinableAndNullability(functionDescriptor: FunctionDescriptor, function: KtFunction, trace: BindingTrace) { + for ((parameter, descriptor) in function.valueParameters.zip(functionDescriptor.valueParameters)) { + if (checkInlinableParameter(descriptor, parameter, functionDescriptor, trace)) return } - hasInlinable = hasInlinable or InlineUtil.containsReifiedTypeParameters(functionDescriptor) + if (InlineUtil.containsReifiedTypeParameters(functionDescriptor) || + functionDescriptor.isInlineOnlyOrReified() || + functionDescriptor.isPlatform) return - if (!hasInlinable && !functionDescriptor.isInlineOnlyOrReified()) { - val modifierList = function.modifierList - val inlineModifier = modifierList?.getModifier(KtTokens.INLINE_KEYWORD) - val reportOn = inlineModifier ?: function - trace.report(Errors.NOTHING_TO_INLINE.on(reportOn, functionDescriptor)) - } + val reportOn = function.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?: function + trace.report(Errors.NOTHING_TO_INLINE.on(reportOn, functionDescriptor)) } fun checkInlinableParameter( diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.kt new file mode 100644 index 00000000000..c70119b7208 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.kt @@ -0,0 +1,25 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo(x: Int): Int + +fun callFromCommonCode(x: Int) = foo(x) + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl fun foo(x: Int): Int { + return x + 1 +} + +fun callFromJVM(x: Int) = foo(x) + +// MODULE: m3-js(m1-common) +// FILE: js.kt + +impl fun foo(x: Int): Int { + return x - 1 +} + +fun callFromJS(x: Int) = foo(x) diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.txt new file mode 100644 index 00000000000..2270fe4fd6b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.txt @@ -0,0 +1,21 @@ +// -- Module: -- +package + +public fun callFromCommonCode(/*0*/ x: kotlin.Int): kotlin.Int +public platform fun foo(/*0*/ x: kotlin.Int): kotlin.Int + + +// -- Module: -- +package + +public fun callFromCommonCode(/*0*/ x: kotlin.Int): kotlin.Int +public fun callFromJVM(/*0*/ x: kotlin.Int): kotlin.Int +public impl fun foo(/*0*/ x: kotlin.Int): kotlin.Int + + +// -- Module: -- +package + +public fun callFromCommonCode(/*0*/ x: kotlin.Int): kotlin.Int +public fun callFromJS(/*0*/ x: kotlin.Int): kotlin.Int +public impl fun foo(/*0*/ x: kotlin.Int): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.kt new file mode 100644 index 00000000000..6009179e011 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo() +platform fun foo() + +platform fun foo(x: Int) diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.txt new file mode 100644 index 00000000000..10e92e8f7d6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.txt @@ -0,0 +1,5 @@ +package + +public platform fun foo(): kotlin.Unit +public platform fun foo(): kotlin.Unit +public platform fun foo(/*0*/ x: kotlin.Int): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.kt new file mode 100644 index 00000000000..6cb49d3df9c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo() + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl fun foo() {} +impl fun foo() {} + +// MODULE: m3-js(m1-common) +// FILE: js.kt + +impl fun foo() {} +impl fun foo() {} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.txt new file mode 100644 index 00000000000..2c17bb85349 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.txt @@ -0,0 +1,18 @@ +// -- Module: -- +package + +public platform fun foo(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun foo(): kotlin.Unit +public impl fun foo(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun foo(): kotlin.Unit +public impl fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.kt new file mode 100644 index 00000000000..5994dc9e601 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +package common + +platform fun foo() + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +package jvm + +impl fun foo() {} + +// MODULE: m3-js(m1-common) +// FILE: js.kt +package js + +impl fun foo() {} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.txt new file mode 100644 index 00000000000..c9d9abdf67f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.txt @@ -0,0 +1,28 @@ +// -- Module: -- +package + +package common { + public platform fun foo(): kotlin.Unit +} + + +// -- Module: -- +package + +package common { +} + +package jvm { + public impl fun foo(): kotlin.Unit +} + + +// -- Module: -- +package + +package common { +} + +package js { + public impl fun foo(): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.kt new file mode 100644 index 00000000000..74aef4fb1a7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.kt @@ -0,0 +1,5 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo() diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.txt new file mode 100644 index 00000000000..fd68685000d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.txt @@ -0,0 +1,3 @@ +package + +public platform fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt new file mode 100644 index 00000000000..0378f9d5ef1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt @@ -0,0 +1,5 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo(x: Int, y: String = "") diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt new file mode 100644 index 00000000000..24b83d32390 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.txt @@ -0,0 +1,3 @@ +package + +public platform fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ...): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.kt new file mode 100644 index 00000000000..08c93317122 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.kt @@ -0,0 +1,5 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-jvm +// FILE: jvm.kt + +impl fun foo() { } diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.txt new file mode 100644 index 00000000000..4a9b7153232 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.txt @@ -0,0 +1,3 @@ +package + +public impl fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt new file mode 100644 index 00000000000..03d50bc88c1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +inline platform fun inlineFun() +platform fun nonInlineFun() + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl fun inlineFun() { } +impl fun nonInlineFun() { } + +// MODULE: m3-js(m1-common) +// FILE: js.kt + +impl inline fun inlineFun() { } +impl inline fun nonInlineFun() { } diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.txt new file mode 100644 index 00000000000..9869d58c471 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.txt @@ -0,0 +1,19 @@ +// -- Module: -- +package + +public inline platform fun inlineFun(): kotlin.Unit +public platform fun nonInlineFun(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun inlineFun(): kotlin.Unit +public impl fun nonInlineFun(): kotlin.Unit + + +// -- Module: -- +package + +public inline impl fun inlineFun(): kotlin.Unit +public inline impl fun nonInlineFun(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.kt new file mode 100644 index 00000000000..5642d64c1b5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo() + +platform fun foo() {} + +platform fun bar() {} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.txt new file mode 100644 index 00000000000..4b2d2d96cd0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.txt @@ -0,0 +1,5 @@ +package + +public platform fun bar(): kotlin.Unit +public platform fun foo(): kotlin.Unit +public platform fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.kt new file mode 100644 index 00000000000..b3b694e2907 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +platform fun foo() + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +impl fun foo() + +impl fun bar() diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.txt new file mode 100644 index 00000000000..7343d4c5ba1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.txt @@ -0,0 +1,11 @@ +// -- Module: -- +package + +public platform fun foo(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun bar(): kotlin.Unit +public impl fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.kt new file mode 100644 index 00000000000..8d8bc53110d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt +platform fun foo() + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt +impl fun foo() {} + +// MODULE: m3-js(m1-common) +// FILE: js.kt +impl fun foo() {} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.txt new file mode 100644 index 00000000000..bb3d7a94b32 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.txt @@ -0,0 +1,16 @@ +// -- Module: -- +package + +public platform fun foo(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun foo(): kotlin.Unit + + +// -- Module: -- +package + +public impl fun foo(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java index f57e5303ada..13acd88b9c4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java @@ -25,6 +25,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import kotlin.collections.CollectionsKt; import kotlin.jvm.functions.Function1; +import kotlin.text.StringsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalysisResult; @@ -148,7 +149,7 @@ public abstract class AbstractDiagnosticsTest extends BaseDiagnosticsTest { LanguageVersionSettings languageVersionSettings = loadLanguageVersionSettings(testFilesInModule); ModuleContext moduleContext = ContextKt.withModule(ContextKt.withProject(context, getProject()), module); - boolean separateModules = groupedByModule.size() == 1; + boolean separateModules = groupedByModule.size() == 1 && groupedByModule.keySet().iterator().next() == null; AnalysisResult result = analyzeModuleContents(moduleContext, jetFiles, moduleTrace, languageVersionSettings, separateModules); if (separateModules) { modules.put(testModule, (ModuleDescriptorImpl) result.getModuleDescriptor()); @@ -448,7 +449,7 @@ public abstract class AbstractDiagnosticsTest extends BaseDiagnosticsTest { ModuleDescriptorImpl module = testModule == null ? createSealedModule(storageManager) : - createModule("<" + testModule.getName() + ">", storageManager); + createModule(testModule.getName(), storageManager); modules.put(testModule, module); } @@ -471,13 +472,24 @@ public abstract class AbstractDiagnosticsTest extends BaseDiagnosticsTest { } @NotNull + @SuppressWarnings("unchecked") protected ModuleDescriptorImpl createModule(@NotNull String moduleName, @NotNull StorageManager storageManager) { - return new ModuleDescriptorImpl(Name.special(moduleName), storageManager, new JvmBuiltIns(storageManager)); + String nameSuffix = StringsKt.substringAfterLast(moduleName, "-", ""); + MultiTargetPlatform platform = + nameSuffix.isEmpty() ? null : + nameSuffix.equals("common") ? MultiTargetPlatform.Common.INSTANCE : new MultiTargetPlatform.Specific(nameSuffix); + Map capabilities = + platform == null + ? Collections.emptyMap() + : Collections.singletonMap(MultiTargetPlatform.CAPABILITY, platform); + return new ModuleDescriptorImpl( + Name.special("<" + moduleName + ">"), storageManager, new JvmBuiltIns(storageManager), capabilities + ); } @NotNull protected ModuleDescriptorImpl createSealedModule(@NotNull StorageManager storageManager) { - ModuleDescriptorImpl moduleDescriptor = createModule("", storageManager); + ModuleDescriptorImpl moduleDescriptor = createModule("test-module", storageManager); moduleDescriptor.setDependencies(moduleDescriptor, moduleDescriptor.getBuiltIns().getBuiltInsModule()); return moduleDescriptor; } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.java b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.java index c1ce3f8f44d..691390b304d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTestWithJsStdLib.java @@ -88,13 +88,13 @@ public abstract class AbstractDiagnosticsTestWithJsStdLib extends AbstractDiagno @NotNull @Override protected ModuleDescriptorImpl createModule(@NotNull String moduleName, @NotNull StorageManager storageManager) { - return new ModuleDescriptorImpl(Name.special(moduleName), storageManager, JsPlatform.INSTANCE.getBuiltIns()); + return new ModuleDescriptorImpl(Name.special("<" + moduleName + ">"), storageManager, JsPlatform.INSTANCE.getBuiltIns()); } @NotNull @Override protected ModuleDescriptorImpl createSealedModule(@NotNull StorageManager storageManager) { - ModuleDescriptorImpl module = createModule("", storageManager); + ModuleDescriptorImpl module = createModule("kotlin-js-test-module", storageManager); List dependencies = new ArrayList(); dependencies.add(module); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f5a05302e69..20dd56fe326 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -12548,6 +12548,90 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multiplatform extends AbstractDiagnosticsTest { + public void testAllFilesPresentInMultiplatform() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class TopLevelFun extends AbstractDiagnosticsTest { + public void testAllFilesPresentInTopLevelFun() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/topLevelFun"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("callPlatformFun.kt") + public void testCallPlatformFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callPlatformFun.kt"); + doTest(fileName); + } + + @TestMetadata("conflictingPlatformDeclarations.kt") + public void testConflictingPlatformDeclarations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDeclarations.kt"); + doTest(fileName); + } + + @TestMetadata("conflictingPlatformDefinitions.kt") + public void testConflictingPlatformDefinitions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/conflictingPlatformDefinitions.kt"); + doTest(fileName); + } + + @TestMetadata("declarationAndDefinitionInDIfferentPackages.kt") + public void testDeclarationAndDefinitionInDIfferentPackages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationAndDefinitionInDIfferentPackages.kt"); + doTest(fileName); + } + + @TestMetadata("declarationWithoutDefinition.kt") + public void testDeclarationWithoutDefinition() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/declarationWithoutDefinition.kt"); + doTest(fileName); + } + + @TestMetadata("defaultArguments.kt") + public void testDefaultArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/defaultArguments.kt"); + doTest(fileName); + } + + @TestMetadata("definitionWithoutDeclaration.kt") + public void testDefinitionWithoutDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/definitionWithoutDeclaration.kt"); + doTest(fileName); + } + + @TestMetadata("inlineFun.kt") + public void testInlineFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt"); + doTest(fileName); + } + + @TestMetadata("platformDeclarationWithBody.kt") + public void testPlatformDeclarationWithBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDeclarationWithBody.kt"); + doTest(fileName); + } + + @TestMetadata("platformDefinitionWithoutBody.kt") + public void testPlatformDefinitionWithoutBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/platformDefinitionWithoutBody.kt"); + doTest(fileName); + } + + @TestMetadata("simplePlatformFun.kt") + public void testSimplePlatformFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/simplePlatformFun.kt"); + doTest(fileName); + } + } + } + @TestMetadata("compiler/testData/diagnostics/tests/namedArguments") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)