diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index cb25a3c7ad9..dbe4d46b633 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -120,6 +120,7 @@ public interface Errors { DiagnosticFactory1 WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR); DiagnosticFactory0 REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 NON_SOURCE_ANNOTATION_ON_INLINED_FUNCTION_LITERAL = DiagnosticFactory0.create(ERROR); // Annotations 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 3bbea8e2d08..2da965a47cb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -127,6 +127,7 @@ public class DefaultErrorMessages { MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING); MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING); MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable"); + MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_FUNCTION_LITERAL, "Function literal here is an inlined argument so this annotation cannot be stored anywhere"); MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}'' annotations could be applied only to property declarations", TO_STRING); MAP.put(INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD, "Property has neither a backing field nor a delegate"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java index ac6ecbcc2e6..894f94f9c09 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java @@ -874,7 +874,7 @@ public class JetPsiUtil { else if (parent instanceof JetValueArgument || parent instanceof JetValueArgumentList) { parent = parent.getParent(); } - else if (parent instanceof JetFunctionLiteralExpression) { + else if (parent instanceof JetFunctionLiteralExpression || parent instanceof JetAnnotatedExpression) { parent = parent.getParent(); } else { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 56f5b54c034..0c20e4cd409 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -28,7 +28,10 @@ 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) { @@ -92,11 +95,28 @@ public class AnnotationChecker(private val additionalCheckers: Iterable Int) = arg() +inline fun fast(arg: () -> Int) = arg() + +inline fun fast2(x: Int, arg: () -> Int) = x + arg() + @FunAnn fun gav() = 13 fun foo(arg: Int) { // Literal is annotatable bar @FunAnn { arg } + // Annotatable in principle but useless, fast is inline + fast @FunAnn { arg } + fast2(1, @FunAnn { arg }) + // Source annotation, ok + fast @SourceAnn { arg } + fast2(1, @SourceAnn { arg }) + // Expression annotation, ok + fast @ExprAnn { arg } + fast2(1, @ExprAnn { arg }) // Function expression too val f = @FunAnn fun(): Int { return 42 } // But here, f and gav should be annotated instead bar(@FunAnn f) bar(@FunAnn ::gav) + // Function expression, ok + fast(f) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/options/functions.txt b/compiler/testData/diagnostics/tests/annotations/options/functions.txt index 82735a9a431..b2ede3bdbdb 100644 --- a/compiler/testData/diagnostics/tests/annotations/options/functions.txt +++ b/compiler/testData/diagnostics/tests/annotations/options/functions.txt @@ -1,12 +1,28 @@ package public fun bar(/*0*/ arg: () -> kotlin.Int): kotlin.Int +@kotlin.inline() public fun fast(/*0*/ arg: () -> kotlin.Int): kotlin.Int +@kotlin.inline() public fun fast2(/*0*/ x: kotlin.Int, /*1*/ arg: () -> kotlin.Int): kotlin.Int public fun foo(/*0*/ arg: kotlin.Int): kotlin.Unit @FunAnn() public fun gav(): 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 } + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.annotation() public final class SourceAnn : kotlin.Annotation { + public constructor SourceAnn() + 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 +}