Function expressions can be now annotated with expression-targeted annotation #KT-9323 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-09-28 13:49:23 +03:00
parent 4e91f2ffb7
commit f4ccb16c2e
6 changed files with 46 additions and 8 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.*
@@ -28,14 +29,12 @@ import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.inline.InlineUtil
public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: ClassDescriptor? = null) {
public fun check(annotated: JetAnnotated, trace: BindingTrace, descriptor: DeclarationDescriptor? = null) {
if (annotated is JetTypeParameter) return // TODO: support type parameter annotations
val actualTargets = getActualTargetList(annotated, descriptor)
checkEntries(annotated.annotationEntries, actualTargets, trace)
@@ -157,9 +156,10 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
return getActualTargetList(annotated, descriptor).defaultTargets
}
private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList {
private fun getActualTargetList(annotated: JetElement, descriptor: DeclarationDescriptor?): TargetList {
return when (annotated) {
is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
is JetClassOrObject ->
(descriptor as? ClassDescriptor)?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
is JetMultiDeclarationEntry -> TargetLists.T_LOCAL_VARIABLE
is JetProperty -> {
if (annotated.isLocal)
@@ -177,7 +177,9 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
}
is JetConstructor<*> -> TargetLists.T_CONSTRUCTOR
is JetFunction -> {
if (annotated.isLocal)
if (DescriptorUtils.isFunctionExpression(descriptor))
TargetLists.T_FUNCTION_EXPRESSION
else if (annotated.isLocal)
TargetLists.T_LOCAL_FUNCTION
else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody)
TargetLists.T_MEMBER_FUNCTION
@@ -250,6 +252,8 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
val T_FUNCTION_LITERAL = targetList(FUNCTION_LITERAL, FUNCTION, EXPRESSION)
val T_FUNCTION_EXPRESSION = targetList(FUNCTION_EXPRESSION, FUNCTION, EXPRESSION)
val T_OBJECT_LITERAL = targetList(OBJECT_LITERAL, CLASS, EXPRESSION)
val T_TYPE_REFERENCE = targetList(TYPE) {
@@ -182,8 +182,7 @@ public class ModifiersChecker {
private void checkModifierListCommon(@NotNull JetDeclaration modifierListOwner, @NotNull DeclarationDescriptor descriptor) {
AnnotationUseSiteTargetChecker.INSTANCE$.check(modifierListOwner, descriptor, trace);
runDeclarationCheckers(modifierListOwner, descriptor);
ClassDescriptor classDescriptor = descriptor instanceof ClassDescriptor ? (ClassDescriptor) descriptor : null;
annotationChecker.check(modifierListOwner, trace, classDescriptor);
annotationChecker.check(modifierListOwner, trace, descriptor);
ModifierCheckerCore.INSTANCE$.check(modifierListOwner, trace, descriptor);
}
@@ -0,0 +1,11 @@
@Target(AnnotationTarget.EXPRESSION)
annotation class ExprAnn
@Target(AnnotationTarget.FUNCTION)
annotation class FunAnn
fun foo(): Int {
val x = @ExprAnn fun() = 1
val y = @FunAnn fun() = 2
return x() + y()
}
@@ -0,0 +1,17 @@
package
public fun foo(): kotlin.Int
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) @kotlin.annotation.annotation() public final class ExprAnn : kotlin.Annotation {
public constructor ExprAnn()
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
}
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) @kotlin.annotation.annotation() public final class FunAnn : kotlin.Annotation {
public constructor FunAnn()
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
}
@@ -1052,6 +1052,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("functionExpression.kt")
public void testFunctionExpression() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/functionExpression.kt");
doTest(fileName);
}
@TestMetadata("functions.kt")
public void testFunctions() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/options/functions.kt");
@@ -62,6 +62,7 @@ public enum class KotlinTarget(val description: String, val isDefault: Boolean =
INITIALIZER("initializer", false),
MULTI_DECLARATION("multi declaration", false),
FUNCTION_LITERAL("function literal", false),
FUNCTION_EXPRESSION("function expression", false),
OBJECT_LITERAL("object literal", false)
;