From db64d9c528f58519568b333ca800f3fb5bcb8f46 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Fri, 20 May 2016 12:07:02 +0300 Subject: [PATCH] Fixed visibility checks for annotation usage on top-level declarations #KT-12429 Fixed --- .../lazy/descriptors/LazyAnnotations.kt | 37 +++++++++++++++---- .../tests/privateInFile/kt12429.kt | 4 ++ .../tests/privateInFile/kt12429.txt | 4 ++ .../privateInFile/topLevelAnnotationCall.kt | 27 ++++++++++++++ .../privateInFile/topLevelAnnotationCall.txt | 31 ++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 12 ++++++ 6 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/privateInFile/kt12429.kt create mode 100644 compiler/testData/diagnostics/tests/privateInFile/kt12429.txt create mode 100644 compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.kt create mode 100644 compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt index d0a2be74139..5360a39533c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,13 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtAnnotationUseSiteTarget import org.jetbrains.kotlin.resolve.AnnotationResolver import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace @@ -35,6 +33,7 @@ import org.jetbrains.kotlin.resolve.lazy.LazyEntity import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.types.TypeSubstitutor abstract class LazyAnnotationsContext( val annotationResolver: AnnotationResolver, @@ -120,7 +119,7 @@ class LazyAnnotationDescriptor( private val type = c.storageManager.createLazyValue { c.annotationResolver.resolveAnnotationType( - c.scope, + scope, annotationEntry, c.trace ) @@ -132,12 +131,18 @@ class LazyAnnotationDescriptor( private val source = annotationEntry.toSourceElement() + val scope = if (c.scope.ownerDescriptor is PackageFragmentDescriptor) { + LexicalScope.Companion.empty(c.scope, FileDescriptorForVisibilityChecks(source, c.scope.ownerDescriptor)) + } else { + c.scope + } + override fun getType() = type() override fun getAllValueArguments() = valueArguments() private fun computeValueArguments(): Map> { - val resolutionResults = c.annotationResolver.resolveAnnotationCall(annotationEntry, c.scope, c.trace) + val resolutionResults = c.annotationResolver.resolveAnnotationCall(annotationEntry, scope, c.trace) AnnotationResolver.checkAnnotationType(annotationEntry, c.trace, resolutionResults) if (!resolutionResults.isSingleResult) return mapOf() @@ -157,4 +162,22 @@ class LazyAnnotationDescriptor( ForceResolveUtil.forceResolveAllContents(getType()) allValueArguments } + + private class FileDescriptorForVisibilityChecks( + private val source: SourceElement, + private val containingDeclaration: DeclarationDescriptor + ) : DeclarationDescriptorWithSource { + override val annotations: Annotations get() = Annotations.EMPTY + override fun getContainingDeclaration() = containingDeclaration + override fun getSource() = source + override fun getOriginal() = this + override fun getName() = Name.special("< file descriptor for annotation resolution >") + + private fun error(): Nothing = error("This method should not be called") + override fun substitute(substitutor: TypeSubstitutor): DeclarationDescriptor? = error() + override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = error() + override fun acceptVoid(visitor: DeclarationDescriptorVisitor?) = error() + + override fun toString(): String = "${name.asString()} declared in LazyAnnotations.kt" + } } diff --git a/compiler/testData/diagnostics/tests/privateInFile/kt12429.kt b/compiler/testData/diagnostics/tests/privateInFile/kt12429.kt new file mode 100644 index 00000000000..9cc707d89e9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/privateInFile/kt12429.kt @@ -0,0 +1,4 @@ +private const val a = "" + +@Deprecated("$a") +fun test() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/privateInFile/kt12429.txt b/compiler/testData/diagnostics/tests/privateInFile/kt12429.txt new file mode 100644 index 00000000000..775fc36a8a5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/privateInFile/kt12429.txt @@ -0,0 +1,4 @@ +package + +private const val a: kotlin.String = "" +@kotlin.Deprecated(message = "") public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.kt b/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.kt new file mode 100644 index 00000000000..ddb17d56242 --- /dev/null +++ b/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.kt @@ -0,0 +1,27 @@ +// FILE: 1.kt +package pp + +private annotation class A(val s: String) +private const val foo = "O" + +@A(foo) +fun f1() {} + +@A(foo) +val p1 = "" + +@A(foo) +class C1 + + +// FILE: 2.kt +package pp + +@A(foo) +fun f2() {} + +@A(foo) +val p2 = "" + +@A(foo) +class C2 diff --git a/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.txt b/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.txt new file mode 100644 index 00000000000..ce33ca74da9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.txt @@ -0,0 +1,31 @@ +package + +package pp { + private const val foo: kotlin.String = "O" + @pp.A(s = "O") public val p1: kotlin.String = "" + @pp.A(s = "O") public val p2: kotlin.String = "" + @pp.A(s = "O") public fun f1(): kotlin.Unit + @pp.A(s = "O") public fun f2(): kotlin.Unit + + private final annotation class A : kotlin.Annotation { + public constructor A(/*0*/ s: kotlin.String) + public final val s: kotlin.String + 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 + } + + @pp.A(s = "O") public final class C1 { + public constructor C1() + 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 + } + + @pp.A(s = "O") public final class C2 { + public constructor C2() + 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 881594861e4..30e65cd4418 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13257,6 +13257,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/privateInFile"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("kt12429.kt") + public void testKt12429() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/privateInFile/kt12429.kt"); + doTest(fileName); + } + + @TestMetadata("topLevelAnnotationCall.kt") + public void testTopLevelAnnotationCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/privateInFile/topLevelAnnotationCall.kt"); + doTest(fileName); + } + @TestMetadata("visibility.kt") public void testVisibility() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/privateInFile/visibility.kt");