Forbid private 'expect' declarations

#KT-19170 Fixed
This commit is contained in:
Alexander Udalov
2017-09-20 14:24:55 +03:00
parent 87b85ce978
commit ecfea9e340
15 changed files with 188 additions and 58 deletions
@@ -571,6 +571,7 @@ public interface Errors {
DiagnosticFactory0<KtPropertyDelegate> EXPECTED_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> EXPECTED_LATEINIT_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> EXPECTED_PRIVATE_DECLARATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDelegatedSuperTypeEntry> IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS = DiagnosticFactory0.create(ERROR);
@@ -273,6 +273,7 @@ public class DefaultErrorMessages {
MAP.put(EXPECTED_DELEGATED_PROPERTY, "Expected property cannot be delegated");
MAP.put(EXPECTED_LATEINIT_PROPERTY, "Expected property cannot be lateinit");
MAP.put(SUPERTYPE_INITIALIZED_IN_EXPECTED_CLASS, "Expected classes cannot initialize supertypes");
MAP.put(EXPECTED_PRIVATE_DECLARATION, "Expected declaration cannot be private");
MAP.put(IMPLEMENTATION_BY_DELEGATION_IN_EXPECT_CLASS, "Implementation by delegation in expected classes is prohibited");
@@ -78,22 +78,7 @@ class DeclarationsChecker(
}
for ((classOrObject, classDescriptor) in bodiesResolveContext.declaredClasses.entries) {
checkSupertypesForConsistency(classDescriptor, classOrObject)
checkTypesInClassHeader(classOrObject)
when (classOrObject) {
is KtClass -> {
checkClassButNotObject(classOrObject, classDescriptor)
descriptorResolver.checkNamesInConstraints(
classOrObject, classDescriptor, classDescriptor.scopeForClassHeaderResolution, trace)
}
is KtObjectDeclaration -> {
checkObject(classOrObject, classDescriptor)
}
}
checkPrimaryConstructor(classOrObject, classDescriptor)
checkClass(classDescriptor, classOrObject)
modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor)
identifierChecker.checkDeclaration(classOrObject, trace)
exposedChecker.checkClassHeader(classOrObject, classDescriptor)
@@ -303,6 +288,26 @@ class DeclarationsChecker(
ModifierCheckerCore.check(packageDirective, trace, descriptor = null, languageVersionSettings = languageVersionSettings)
}
private fun checkClass(classDescriptor: ClassDescriptorWithResolutionScopes, classOrObject: KtClassOrObject) {
checkSupertypesForConsistency(classDescriptor, classOrObject)
checkTypesInClassHeader(classOrObject)
when (classOrObject) {
is KtClass -> {
checkClassButNotObject(classOrObject, classDescriptor)
descriptorResolver.checkNamesInConstraints(
classOrObject, classDescriptor, classDescriptor.scopeForClassHeaderResolution, trace)
}
is KtObjectDeclaration -> {
checkObject(classOrObject, classDescriptor)
}
}
checkPrimaryConstructor(classOrObject, classDescriptor)
checkPrivateExpectedDeclaration(classOrObject, classDescriptor)
}
private fun checkTypesInClassHeader(classOrObject: KtClassOrObject) {
fun KtTypeReference.type(): KotlinType? = trace.bindingContext.get(TYPE, this)
@@ -548,6 +553,13 @@ class DeclarationsChecker(
shadowedExtensionChecker.checkDeclaration(property, propertyDescriptor)
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
checkImplicitCallableType(property, propertyDescriptor)
checkPrivateExpectedDeclaration(property, propertyDescriptor)
}
private fun checkPrivateExpectedDeclaration(declaration: KtDeclaration, descriptor: MemberDescriptor) {
if (descriptor.isExpect && Visibilities.isPrivate(descriptor.visibility)) {
trace.report(EXPECTED_PRIVATE_DECLARATION.on(declaration.modifierList?.getModifier(KtTokens.PRIVATE_KEYWORD) ?: declaration))
}
}
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
@@ -579,7 +591,8 @@ class DeclarationsChecker(
private fun checkMemberProperty(
property: KtProperty,
propertyDescriptor: PropertyDescriptor,
classDescriptor: ClassDescriptor) {
classDescriptor: ClassDescriptor
) {
val modifierList = property.modifierList
if (modifierList != null) {
@@ -731,13 +744,13 @@ class DeclarationsChecker(
}
if (functionDescriptor.isExpect) {
checkExpectedFunction(function)
checkExpectedFunction(function, functionDescriptor)
}
shadowedExtensionChecker.checkDeclaration(function, functionDescriptor)
}
private fun checkExpectedFunction(function: KtNamedFunction) {
private fun checkExpectedFunction(function: KtNamedFunction, functionDescriptor: FunctionDescriptor) {
if (function.hasBody()) {
trace.report(EXPECTED_DECLARATION_WITH_BODY.on(function))
}
@@ -747,6 +760,8 @@ class DeclarationsChecker(
trace.report(EXPECTED_DECLARATION_WITH_DEFAULT_PARAMETER.on(parameter))
}
}
checkPrivateExpectedDeclaration(function, functionDescriptor)
}
private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) {
@@ -0,0 +1,22 @@
// !LANGUAGE: +MultiPlatformProjects
// MODULE: m1-common
// FILE: common.kt
expect class A {
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> fun foo()
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> val bar: String
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> fun Int.memExt(): Any
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> class Nested
}
// MODULE: m1-jvm(m1-common)
// FILE: jvm.kt
actual class A {
private fun <!ACTUAL_MISSING!>foo<!>() {}
private val <!ACTUAL_MISSING!>bar<!>: String = ""
actual private fun Int.memExt(): Any = 0
actual private class Nested
}
@@ -0,0 +1,38 @@
// -- Module: <m1-common> --
package
public final expect class A {
private expect final val bar: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
private final expect fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
private final expect fun kotlin.Int.memExt(): kotlin.Any
private final expect class Nested {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
// -- Module: <m1-jvm> --
package
public final actual class A {
public constructor A()
private final val bar: kotlin.String = ""
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
private final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
private final actual fun kotlin.Int.memExt(): kotlin.Any
private final actual class Nested {
public constructor Nested()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,18 @@
// !LANGUAGE: +MultiPlatformProjects
// MODULE: m1-common
// FILE: common.kt
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> expect fun foo()
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> expect val bar: String
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> expect fun Int.memExt(): Any
<!EXPECTED_PRIVATE_DECLARATION, JVM:EXPECTED_PRIVATE_DECLARATION!>private<!> expect class Foo
// MODULE: m2-jvm(m1-common)
// FILE: jvm.kt
private actual fun foo() {}
private actual val bar: String = ""
private actual fun Int.memExt(): Any = 0
private actual class Foo
@@ -0,0 +1,27 @@
// -- Module: <m1-common> --
package
private expect val bar: kotlin.String
private expect fun foo(): kotlin.Unit
private expect fun kotlin.Int.memExt(): kotlin.Any
private final expect class Foo {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
// -- Module: <m2-jvm> --
package
private actual val bar: kotlin.String = ""
private actual fun foo(): kotlin.Unit
private actual fun kotlin.Int.memExt(): kotlin.Any
private final actual class Foo {
public constructor Foo()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -14,7 +14,6 @@ expect fun f6(p1: String, p2: Int)
expect fun <T> f7()
internal expect fun f8()
private expect fun f9()
public expect fun f10()
expect fun <T : Number> f11()
@@ -14,8 +14,7 @@ actual fun f6(p2: Int) {}
actual fun <K, V> f7() {}
public actual fun f8() {}
internal actual fun f9() {}
private actual fun f10() {}
internal actual fun f10() {}
actual fun <T : Annotation> f11() {}
actual fun <U : MutableList<out String>> f12() {}
@@ -1,7 +1,7 @@
-- Common --
Exit code: OK
Output:
compiler/testData/multiplatform/incompatibleCallables/common.kt:33:19: warning: the feature "coroutines" is experimental (see: https://kotlinlang.org/docs/diagnostics/experimental-coroutines)
compiler/testData/multiplatform/incompatibleCallables/common.kt:32:19: warning: the feature "coroutines" is experimental (see: https://kotlinlang.org/docs/diagnostics/experimental-coroutines)
expect fun f21(c: suspend Unit.() -> Unit)
^
@@ -62,61 +62,55 @@ The following declaration is incompatible because visibility is different:
public actual fun f8() {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:17:1: error: actual function 'f9' has no corresponding expected declaration
The following declaration is incompatible because visibility is different:
private expect fun f9(): Unit
internal actual fun f9() {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:18:1: error: actual function 'f10' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:17:1: error: actual function 'f10' has no corresponding expected declaration
The following declaration is incompatible because visibility is different:
public expect fun f10(): Unit
private actual fun f10() {}
internal actual fun f10() {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:24:19: error: actual function 'f14' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:23:19: error: actual function 'f14' has no corresponding expected declaration
The following declaration is incompatible because some type parameter is reified in one declaration and non-reified in the other:
public expect inline fun <X> f14(): Unit
actual inline fun <reified X> f14() {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:27:15: error: actual function 'f16' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:26:15: error: actual function 'f16' has no corresponding expected declaration
The following declaration is incompatible because some parameters have default values:
public expect fun f16(s: String): Unit
actual fun f16(s: String = "") {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:29:15: error: actual function 'f17' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:28:15: error: actual function 'f17' has no corresponding expected declaration
The following declaration is incompatible because some value parameter is vararg in one declaration and non-vararg in the other:
public expect fun f17(vararg s: String): Unit
actual fun f17(s: Array<out String>) {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:30:15: error: actual function 'f18' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:29:15: error: actual function 'f18' has no corresponding expected declaration
The following declaration is incompatible because some value parameter is vararg in one declaration and non-vararg in the other:
public expect fun f18(s: Array<out String>): Unit
actual fun f18(vararg s: String) {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:31:22: error: actual function 'f19' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:30:22: error: actual function 'f19' has no corresponding expected declaration
The following declaration is incompatible because some value parameter is crossinline in one declaration and not crossinline in the other:
public expect inline fun f19(s: () -> Unit): Unit
actual inline fun f19(crossinline s: () -> Unit) {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:32:22: error: actual function 'f20' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:31:22: error: actual function 'f20' has no corresponding expected declaration
The following declaration is incompatible because some value parameter is noinline in one declaration and not noinline in the other:
public expect inline fun f20(s: () -> Unit): Unit
actual inline fun f20(noinline s: () -> Unit) {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:33:15: error: actual function 'f21' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:32:15: error: actual function 'f21' has no corresponding expected declaration
The following declaration is incompatible because parameter types are different:
public expect fun f21(c: suspend Unit.() -> Unit): Unit
actual fun f21(c: Unit.() -> Unit) {}
^
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:34:15: error: actual function 'f22' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:33:15: error: actual function 'f22' has no corresponding expected declaration
The following declaration is incompatible because parameter types are different:
public expect fun f22(c: Unit.() -> Unit): Unit
@@ -6,7 +6,6 @@ expect annotation class PAnnotationClass
internal expect object InternalObject
public expect object PublicObject
private expect object PrivateObject
open expect class OpenClass
abstract expect class AbstractClass
+1 -2
View File
@@ -4,9 +4,8 @@ actual enum class PObject
actual annotation class PEnumClass
actual class PAnnotationClass
private actual object InternalObject
internal actual object PublicObject
public actual object PrivateObject
public actual object InternalObject
final actual class OpenClass
open actual class AbstractClass
@@ -35,55 +35,49 @@ The following declaration is incompatible because class kinds are different (cla
actual class PAnnotationClass
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:7:1: error: actual object 'InternalObject' has no corresponding expected declaration
The following declaration is incompatible because visibility is different:
internal expect object InternalObject
private actual object InternalObject
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:8:1: error: actual object 'PublicObject' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:7:1: error: actual object 'PublicObject' has no corresponding expected declaration
The following declaration is incompatible because visibility is different:
public expect object PublicObject
internal actual object PublicObject
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:9:1: error: actual object 'PrivateObject' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:8:1: error: actual object 'InternalObject' has no corresponding expected declaration
The following declaration is incompatible because visibility is different:
private expect object PrivateObject
internal expect object InternalObject
public actual object PrivateObject
public actual object InternalObject
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:11:1: error: actual class 'OpenClass' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:10:1: error: actual class 'OpenClass' has no corresponding expected declaration
The following declaration is incompatible because modality is different:
public open expect class OpenClass
final actual class OpenClass
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:12:1: error: actual class 'AbstractClass' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:11:1: error: actual class 'AbstractClass' has no corresponding expected declaration
The following declaration is incompatible because modality is different:
public abstract expect class AbstractClass
open actual class AbstractClass
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:13:1: error: actual class 'FinalClass' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:12:1: error: actual class 'FinalClass' has no corresponding expected declaration
The following declaration is incompatible because modality is different:
public final expect class FinalClass
abstract actual class FinalClass
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:15:16: error: actual class 'C1' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:14:16: error: actual class 'C1' has no corresponding expected declaration
The following declaration is incompatible because number of type parameters is different:
public final expect class C1<A>
actual class C1<A, Extra>
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:16:16: error: actual class 'C2' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:15:16: error: actual class 'C2' has no corresponding expected declaration
The following declaration is incompatible because declaration-site variances of type parameters are different:
public final expect class C2<B>
actual class C2<out B>
^
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:22:39: error: actual class 'ExtendsNumber' has no corresponding expected declaration
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:21:39: error: actual class 'ExtendsNumber' has no corresponding expected declaration
The following declaration is incompatible because some supertypes are missing in the actual declaration:
public abstract expect class ExtendsNumber : Number
@@ -13972,6 +13972,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("privateTopLevelDeclarations.kt")
public void testPrivateTopLevelDeclarations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/privateTopLevelDeclarations.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/deprecated")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -14163,6 +14169,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("privateMembers.kt")
public void testPrivateMembers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/privateMembers.kt");
doTest(fileName);
}
@TestMetadata("simpleHeaderClass.kt")
public void testSimpleHeaderClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/simpleHeaderClass.kt");
@@ -13972,6 +13972,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
doTest(fileName);
}
@TestMetadata("privateTopLevelDeclarations.kt")
public void testPrivateTopLevelDeclarations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/privateTopLevelDeclarations.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/deprecated")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -14163,6 +14169,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
doTest(fileName);
}
@TestMetadata("privateMembers.kt")
public void testPrivateMembers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/privateMembers.kt");
doTest(fileName);
}
@TestMetadata("simpleHeaderClass.kt")
public void testSimpleHeaderClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/simpleHeaderClass.kt");