From 40ec794c662070ffcf38588dbc09423c6312709b Mon Sep 17 00:00:00 2001 From: Vladimir Ilmov Date: Mon, 8 Jun 2020 21:32:32 +0200 Subject: [PATCH] (UltraLightClasses) fast-path for Deprecated.HIDDEN annotation --- .../kotlin/asJava/classes/ultraLightUtils.kt | 35 ++++++++-- .../kotlin/asJava/KtLightAnnotationTest.kt | 64 +++++++++++++++++++ 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index 6286ad643f8..650712b4663 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -311,11 +311,38 @@ private fun packMethodFlags(access: Int, isInterface: Boolean): Int { } internal fun KtModifierListOwner.isHiddenByDeprecation(support: KtUltraLightSupport): Boolean { - val jetModifierList = this.modifierList ?: return false - if (jetModifierList.annotationEntries.isEmpty()) return false + if (annotationEntries.isEmpty()) return false + val annotations = annotationEntries.filter { annotation -> + annotation.looksLikeDeprecated() + } + if (annotations.isNotEmpty()) { // some candidates found + val deprecated = support.findAnnotation(this, KotlinBuiltIns.FQ_NAMES.deprecated)?.second + return (deprecated?.argumentValue("level") as? EnumValue)?.enumEntryName?.asString() == "HIDDEN" + } else { + return false + } +} - val deprecated = support.findAnnotation(this, KotlinBuiltIns.FQ_NAMES.deprecated)?.second - return (deprecated?.argumentValue("level") as? EnumValue)?.enumEntryName?.asString() == "HIDDEN" +fun KtAnnotationEntry.looksLikeDeprecated(): Boolean { + val arguments = valueArguments.filterIsInstance().filterIndexed { index, valueArgument -> + index == 2 || valueArgument.looksLikeLevelArgument() // for named/not named arguments + } + for (argument in arguments) { + val hiddenByDotQualifiedCandidates = argument.children.filterIsInstance().filter { + val lastChild = it.children.last() + lastChild.text == "HIDDEN" + } + val hiddenByNameReferenceExpressionCandidates = argument.children.filterIsInstance().filter { + it.text == "HIDDEN" + } + if (hiddenByDotQualifiedCandidates.isNotEmpty() || hiddenByNameReferenceExpressionCandidates.isNotEmpty()) + return true + } + return false +} + +fun KtValueArgument.looksLikeLevelArgument(): Boolean { + return children.filterIsInstance().any { it.asName.asString() == "level" } } internal fun KtAnnotated.isJvmStatic(support: KtUltraLightSupport): Boolean = diff --git a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt b/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt index d187c433e1c..08ba470514c 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt @@ -33,6 +33,70 @@ class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { override fun getProjectDescriptor(): LightProjectDescriptor = KotlinJdkAndLibraryProjectDescriptor(ForTestCompileRuntime.runtimeJarForTests()) + fun testIsHiddenByDeprecated() { + myFixture.configureByText( + "test.kt", """ + import kotlin.DeprecationLevel.WARNING + import kotlin.DeprecationLevel.HIDDEN + import java.lang.annotation.ElementType + import kotlin.DeprecationLevel + import kotlin.annotation.AnnotationTarget + + @kotlin.annotation.Target(kotlin.annotation.AnnotationTarget.FUNCTION) + annotation class Dep( + val message: String = "", + val message1: String = "", + val level: DeprecationLevel = DeprecationLevel.WARNING + ) + + typealias LOL = Deprecated + typealias DL = DeprecationLevel + + class A { + @Deprecated("", ReplaceWith("a"), HIDDEN) + fun a() {} + + @Deprecated(message = "", level = HIDDEN) + fun b() {} + + @Deprecated(message = "", replaceWith = ReplaceWith(""), level = DeprecationLevel.HIDDEN) + fun c() {} + + @Deprecated(message = "", replaceWith = ReplaceWith(""), level = DeprecationLevel.WARNING) + fun d() {} + + @Deprecated(message = "", replaceWith = ReplaceWith(""), level = WARNING) + fun e() {} + + @Deprecated(message = "", replaceWith = ReplaceWith("")) + fun f() {} + + @Deprecated("") + fun g() {} + + @Deprecated(message = "", level = WARNING) + fun h() {} + + @Dep(level = DeprecationLevel.HIDDEN) + fun i() {} + + @Dep("", "", DeprecationLevel.HIDDEN) + fun j() {} + + @LOL(level = HIDDEN, message="") + fun k() {} + + @Deprecated(level = DL.HIDDEN, message="") + fun l() {} + } + """.trimIndent() + ) + myFixture.testHighlighting("test.kt") + + val methods = myFixture.findClass("A").methods.map { it.name }.sorted() + TestCase.assertEquals(listOf("A","d","e","f","g","h","i","j"), methods) + } + fun testBooleanAnnotationDefaultValue() { myFixture.addClass( """