From f1d8838bbd3b5725d7487b54c8527371a344ee32 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 29 May 2015 15:51:33 +0300 Subject: [PATCH] Removed code duplication for getting annotation argument --- .../kotlin/resolve/AnnotationUtil.kt | 11 ++++++++ .../validation/DeprecatedSymbolValidator.kt | 19 +++---------- .../DeprecatedAnnotationVisitor.java | 27 ++----------------- .../quickfix/DeprecatedSymbolUsageFixBase.kt | 13 ++++----- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt index ee88fa73598..787fffb3c24 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt @@ -19,7 +19,9 @@ package org.jetbrains.kotlin.resolve.annotations import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils public fun DeclarationDescriptor.hasInlineAnnotation(): Boolean { @@ -49,3 +51,12 @@ private fun CallableDescriptor.isPlatformStaticIn(predicate: (DeclarationDescrip } else -> predicate(getContainingDeclaration()) && hasPlatformStaticAnnotation() } + +public fun AnnotationDescriptor.argumentValue(parameterName: String): Any? { + return getAllValueArguments().entrySet() + .singleOrNull { it.key.getName().asString() == parameterName } + ?.value?.getValue() +} + +public fun AnnotationDescriptor.deprecatedAnnotationMessage(): String? + = argumentValue("value") as? String diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt index b207c771560..18edc230859 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/validation/DeprecatedSymbolValidator.kt @@ -30,6 +30,8 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.annotations.argumentValue +import org.jetbrains.kotlin.resolve.annotations.deprecatedAnnotationMessage public class DeprecatedSymbolValidator : SymbolUsageValidator { private val JAVA_DEPRECATED = FqName(javaClass().getName()) @@ -89,28 +91,13 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator { } private fun createDeprecationDiagnostic(element: PsiElement, descriptor: DeclarationDescriptor, deprecated: AnnotationDescriptor): Diagnostic { - val message = getMessageFromAnnotationDescriptor(deprecated) + val message = deprecated.deprecatedAnnotationMessage() return if (message == null) Errors.DEPRECATED_SYMBOL.on(element, descriptor) else Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.on(element, descriptor, message) } - private fun getMessageFromAnnotationDescriptor(descriptor: AnnotationDescriptor): String? { - val parameterName = Name.identifier("value") - for ((parameterDescriptor, argument) in descriptor.getAllValueArguments()) { - if (parameterDescriptor.getName() == parameterName) { - val parameterValue = argument.getValue() - if (parameterValue is String) { - return parameterValue - } - else - return null - } - } - return null - } - private val PROPERTY_SET_OPERATIONS = TokenSet.create(JetTokens.EQ, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS) fun propertyGetterWorkaround(propertyDescriptor: PropertyDescriptor, trace: BindingTrace, expression: PsiElement) { // property getters do not come as callable yet, so we analyse surroundings to check for deprecation annotation on getter diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/DeprecatedAnnotationVisitor.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/DeprecatedAnnotationVisitor.java index 86fe3843fe3..67e7e55ba6c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/DeprecatedAnnotationVisitor.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/DeprecatedAnnotationVisitor.java @@ -29,19 +29,15 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.lexer.JetTokens; -import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorUtils; +import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall; -import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; -import org.jetbrains.kotlin.types.TypeUtils; - -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME; public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisitor { @@ -226,29 +222,10 @@ public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisito private static String composeTooltipString(@NotNull DeclarationDescriptor declarationDescriptor, @NotNull AnnotationDescriptor descriptor) { String fact = "'" + getDescriptorString(declarationDescriptor) + "' is deprecated."; - String message = getMessageFromAnnotationDescriptor(descriptor); + String message = AnnotationsPackage.deprecatedAnnotationMessage(descriptor); return message == null ? fact : fact + " " + message; } - @Nullable - private static String getMessageFromAnnotationDescriptor(@NotNull AnnotationDescriptor descriptor) { - ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(descriptor.getType()); - if (classDescriptor != null) { - ValueParameterDescriptor parameter = - DescriptorResolverUtils.getAnnotationParameterByName(DEFAULT_ANNOTATION_MEMBER_NAME, classDescriptor); - if (parameter != null) { - CompileTimeConstant valueArgument = descriptor.getAllValueArguments().get(parameter); - if (valueArgument != null) { - Object value = valueArgument.getValue(); - if (value instanceof String) { - return String.valueOf(value); - } - } - } - } - return null; - } - private static String getDescriptorString(@NotNull DeclarationDescriptor descriptor) { if (descriptor instanceof ClassDescriptor) { return DescriptorUtils.getFqName(descriptor).asString(); diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt index b4bb3cf83b7..097d084a474 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt @@ -47,6 +47,7 @@ import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall @@ -109,15 +110,11 @@ public abstract class DeprecatedSymbolUsageFixBase( val annotationClass = descriptor.builtIns.getDeprecatedAnnotation() val annotation = descriptor.getAnnotations().findAnnotation(DescriptorUtils.getFqNameSafe(annotationClass)) ?: return null //TODO: code duplication - val replaceWithValue = annotation.getAllValueArguments().entrySet() - .singleOrNull { it.key.getName().asString() == "replaceWith"/*TODO*/ } - ?.value?.getValue() as? AnnotationDescriptor ?: return null - val pattern = replaceWithValue.getAllValueArguments().entrySet() - .singleOrNull { it.key.getName().asString() == "expression"/*TODO*/ } - ?.value?.getValue() as? String ?: return null + val replaceWithValue = annotation.argumentValue("replaceWith"/*TODO*/) as? AnnotationDescriptor ?: return null + val pattern = replaceWithValue.argumentValue("expression"/*TODO*/) as? String ?: return null if (pattern.isEmpty()) return null - val argument = replaceWithValue.getAllValueArguments().entrySet().singleOrNull { it.key.getName().asString() == "imports"/*TODO*/ }?.value - val imports = (argument?.getValue() as? List>)?.map { it.getValue() } ?: emptyList() + val imports = (replaceWithValue.argumentValue("imports"/*TODO*/) as? List>) + ?.map { it.getValue() } ?: emptyList() // should not be available for descriptors with optional parameters if we cannot fetch default values for them (currently for library with no sources) if (descriptor is CallableDescriptor &&