Prohibit OptionalExpectation on nested annotation classes

Because the new generation scheme based on module metadata does not
support them, and we don't plan to have them in the standard library
yet.
This commit is contained in:
Alexander Udalov
2020-05-11 20:36:06 +02:00
parent 012ffa2993
commit 4597fff18a
8 changed files with 59 additions and 31 deletions
@@ -681,6 +681,7 @@ public interface Errors {
DiagnosticFactory0<KtNamedDeclaration> ACTUAL_MISSING = DiagnosticFactory0.create(ERROR, ACTUAL_DECLARATION_NAME);
DiagnosticFactory0<PsiElement> OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> NESTED_OPTIONAL_EXPECTATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR);
@@ -306,6 +306,7 @@ public class DefaultErrorMessages {
MAP.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'");
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
MAP.put(NESTED_OPTIONAL_EXPECTATION, "'@OptionalExpectation' cannot be used on a nested class");
MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry");
MAP.put(OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, "Declaration annotated with '@OptionalExpectation' can only be used in common module sources");
@@ -276,7 +276,7 @@ public class ModifiersChecker {
}
OperatorModifierChecker.INSTANCE.check(declaration, descriptor, trace, languageVersionSettings);
PublishedApiUsageChecker.INSTANCE.check(declaration, descriptor, trace);
OptionalExpectationTargetChecker.INSTANCE.check(declaration, descriptor, trace);
OptionalExpectationChecker.INSTANCE.check(declaration, descriptor, trace);
}
public void checkTypeParametersModifiers(@NotNull KtModifierListOwner modifierListOwner) {
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorUtils
object OptionalExpectationChecker {
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
val isExpect = descriptor is MemberDescriptor && descriptor.isExpect
if (isExpect) {
if (DescriptorUtils.isAnnotationClass(descriptor) && descriptor.containingDeclaration !is PackageFragmentDescriptor) {
getOptionalExpectationEntry(declaration, trace)?.let {
trace.report(Errors.NESTED_OPTIONAL_EXPECTATION.on(it))
}
}
} else {
getOptionalExpectationEntry(declaration, trace)?.let {
trace.report(Errors.OPTIONAL_EXPECTATION_NOT_ON_EXPECTED.on(it))
}
}
}
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
declaration.annotationEntries.find { entry ->
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry)
annotationDescriptor?.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME
}
}
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
object OptionalExpectationTargetChecker {
fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
trace: BindingTrace
) {
if (descriptor is MemberDescriptor && descriptor.isExpect) return
for (entry in declaration.annotationEntries) {
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry) ?: continue
if (annotationDescriptor.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME) {
trace.report(Errors.OPTIONAL_EXPECTATION_NOT_ON_EXPECTED.on(entry))
}
}
}
}
@@ -18,3 +18,10 @@ annotation class InOtherAnnotation(val a: A)
@InOtherAnnotation(A())
fun useInOtherAnnotation() {}
expect class C {
@OptionalExpectation
annotation class Nested
}
@@ -4,3 +4,7 @@ annotation class AnotherAnnotation(val a: A)
@AnotherAnnotation(A())
fun useInAnotherAnnotation() {}
actual class C {
actual annotation class Nested
}
@@ -16,6 +16,9 @@ annotation class InOtherAnnotation(val a: A)
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:19:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
@InOtherAnnotation(A())
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:25:5: error: '@OptionalExpectation' cannot be used on a nested class
@OptionalExpectation
^
-- JVM --
Exit code: COMPILATION_ERROR
@@ -38,6 +41,9 @@ annotation class InOtherAnnotation(val a: A)
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:19:20: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
@InOtherAnnotation(A())
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/common.kt:25:5: error: '@OptionalExpectation' cannot be used on a nested class
@OptionalExpectation
^
compiler/testData/multiplatform/optionalExpectationIncorrectUse/jvm.kt:1:24: error: declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry
fun useInReturnType(): A? = null
^