Prohibit initializer blocks inside inline classes

This commit is contained in:
Mikhail Zarechenskiy
2018-05-06 03:52:22 +03:00
parent 6a120d2f85
commit d3c1c11dc5
7 changed files with 43 additions and 3 deletions
@@ -316,6 +316,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtElement> INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtElement> INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtParameter> INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtParameter> INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INLINE_CLASS_WITH_INITIALIZER = DiagnosticFactory0.create(ERROR);
// Secondary constructors // Secondary constructors
@@ -630,6 +630,7 @@ public class DefaultErrorMessages {
MAP.put(NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS, "Primary constructor of inline class must be public"); MAP.put(NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS, "Primary constructor of inline class must be public");
MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter"); MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter");
MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Inline class primary constructor must have only final read-only (val) property parameter"); MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Inline class primary constructor must have only final read-only (val) property parameter");
MAP.put(INLINE_CLASS_WITH_INITIALIZER, "Inline class cannot have initializer block");
MAP.put(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, "Variance annotations are only allowed for type parameters of classes and interfaces"); MAP.put(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, "Variance annotations are only allowed for type parameters of classes and interfaces");
MAP.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters"); MAP.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters");
@@ -10,13 +10,11 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassInitializer
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.getModificationStamp
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.psi.psiUtil.modalityModifier import org.jetbrains.kotlin.psi.psiUtil.modalityModifier
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -66,6 +64,17 @@ object InlineClassDeclarationChecker : DeclarationChecker {
trace.report(Errors.INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER.on(baseParameter)) trace.report(Errors.INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER.on(baseParameter))
return return
} }
val anonymousInitializers = declaration.getAnonymousInitializers()
if (anonymousInitializers.isNotEmpty()) {
for (anonymousInitializer in anonymousInitializers) {
if (anonymousInitializer is KtClassInitializer) {
trace.report(Errors.INLINE_CLASS_WITH_INITIALIZER.on(anonymousInitializer.initKeyword))
}
}
return
}
} }
private fun isParameterAcceptableForInlineClass(parameter: KtParameter): Boolean { private fun isParameterAcceptableForInlineClass(parameter: KtParameter): Boolean {
@@ -0,0 +1,10 @@
// !LANGUAGE: +InlineClasses
// !DIAGNOSTICS: -UNUSED_VARIABLE
inline class Foo(val x: Int) {
<!INLINE_CLASS_WITH_INITIALIZER!>init<!> {}
<!INLINE_CLASS_WITH_INITIALIZER!>init<!> {
val f = 1
}
}
@@ -0,0 +1,9 @@
package
public final inline class Foo {
public constructor Foo(/*0*/ x: kotlin.Int)
public final val x: kotlin.Int
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
}
@@ -10683,6 +10683,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt");
} }
@TestMetadata("presenceOfInitializerBlockInsideInlineClass.kt")
public void testPresenceOfInitializerBlockInsideInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfInitializerBlockInsideInlineClass.kt");
}
@TestMetadata("presenceOfPublicPrimaryConstructorForInlineClass.kt") @TestMetadata("presenceOfPublicPrimaryConstructorForInlineClass.kt")
public void testPresenceOfPublicPrimaryConstructorForInlineClass() throws Exception { public void testPresenceOfPublicPrimaryConstructorForInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt");
@@ -10683,6 +10683,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.kt");
} }
@TestMetadata("presenceOfInitializerBlockInsideInlineClass.kt")
public void testPresenceOfInitializerBlockInsideInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfInitializerBlockInsideInlineClass.kt");
}
@TestMetadata("presenceOfPublicPrimaryConstructorForInlineClass.kt") @TestMetadata("presenceOfPublicPrimaryConstructorForInlineClass.kt")
public void testPresenceOfPublicPrimaryConstructorForInlineClass() throws Exception { public void testPresenceOfPublicPrimaryConstructorForInlineClass() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/presenceOfPublicPrimaryConstructorForInlineClass.kt");