Improve "firstArgumentValue" and "argumentValue" extension functions

Using the argument value, which is of type "Any?", is more implicit and
thus difficult to read than using the ConstantValue instance and casting
it to the needed constant value implementation before taking the value
This commit is contained in:
Alexander Udalov
2017-12-29 16:54:04 +01:00
parent 899002b681
commit 9290d58ed0
9 changed files with 42 additions and 35 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ErrorValue import org.jetbrains.kotlin.resolve.constants.ErrorValue
val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic") val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
@@ -43,6 +44,6 @@ private val STRICTFP_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.Strictfp")
fun DeclarationDescriptor.findStrictfpAnnotation() = fun DeclarationDescriptor.findStrictfpAnnotation() =
DescriptorUtils.getAnnotationByFqName(annotations, STRICTFP_ANNOTATION_FQ_NAME) DescriptorUtils.getAnnotationByFqName(annotations, STRICTFP_ANNOTATION_FQ_NAME)
fun AnnotationDescriptor.argumentValue(parameterName: String): Any? { fun AnnotationDescriptor.argumentValue(parameterName: String): ConstantValue<*>? {
return allValueArguments[Name.identifier(parameterName)].takeUnless { it is ErrorValue }?.value return allValueArguments[Name.identifier(parameterName)].takeUnless { it is ErrorValue }
} }
@@ -33,6 +33,9 @@ import org.jetbrains.kotlin.resolve.DeprecationLevelValue.*
import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.calls.checkers.isOperatorMod import org.jetbrains.kotlin.resolve.calls.checkers.isOperatorMod
import org.jetbrains.kotlin.resolve.calls.checkers.shouldWarnAboutDeprecatedModFromBuiltIns import org.jetbrains.kotlin.resolve.calls.checkers.shouldWarnAboutDeprecatedModFromBuiltIns
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
@@ -42,6 +45,7 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val JAVA_DEPRECATED = FqName("java.lang.Deprecated") private val JAVA_DEPRECATED = FqName("java.lang.Deprecated")
@@ -55,27 +59,22 @@ fun Deprecation.deprecatedByOverriddenMessage(): String? = (this as? DeprecatedB
fun Deprecation.deprecatedByAnnotationReplaceWithExpression(): String? { fun Deprecation.deprecatedByAnnotationReplaceWithExpression(): String? {
val annotation = (this as? DeprecatedByAnnotation)?.annotation ?: return null val annotation = (this as? DeprecatedByAnnotation)?.annotation ?: return null
val replaceWithAnnotation = annotation.argumentValue(kotlin.Deprecated::replaceWith.name) val replaceWithAnnotation =
as? AnnotationDescriptor ?: return null annotation.argumentValue(kotlin.Deprecated::replaceWith.name)?.safeAs<AnnotationValue>()?.value ?: return null
return replaceWithAnnotation.argumentValue(kotlin.ReplaceWith::expression.name)?.safeAs<StringValue>()?.value
return replaceWithAnnotation.argumentValue(kotlin.ReplaceWith::expression.name) as String
} }
private data class DeprecatedByAnnotation(val annotation: AnnotationDescriptor, override val target: DeclarationDescriptor) : Deprecation { private data class DeprecatedByAnnotation(val annotation: AnnotationDescriptor, override val target: DeclarationDescriptor) : Deprecation {
override val deprecationLevel: DeprecationLevelValue override val deprecationLevel: DeprecationLevelValue
get() { get() = when (annotation.argumentValue("level")?.safeAs<EnumValue>()?.enumEntryName?.asString()) {
val level = annotation.argumentValue("level") as? ClassDescriptor "WARNING" -> WARNING
"ERROR" -> ERROR
return when (level?.name?.asString()) { "HIDDEN" -> HIDDEN
"WARNING" -> WARNING else -> WARNING
"ERROR" -> ERROR
"HIDDEN" -> HIDDEN
else -> WARNING
}
} }
override val message: String? override val message: String?
get() = annotation.argumentValue("message") as? String get() = annotation.argumentValue("message")?.safeAs<StringValue>()?.value
} }
private data class DeprecatedByOverridden(private val deprecations: Collection<Deprecation>) : Deprecation { private data class DeprecatedByOverridden(private val deprecations: Collection<Deprecation>) : Deprecation {
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Jsr305State import org.jetbrains.kotlin.utils.Jsr305State
@@ -148,7 +148,7 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
} }
private fun ClassDescriptor.migrationAnnotationStatus(): ReportLevel? { private fun ClassDescriptor.migrationAnnotationStatus(): ReportLevel? {
val stateDescriptor = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgumentValue()?.safeAs<ClassDescriptor>() val stateDescriptor = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgument()?.safeAs<EnumValue>()?.value
?: return null ?: return null
jsr305State.migration?.let { return jsr305State.migration } jsr305State.migration?.let { return jsr305State.migration }
@@ -24,7 +24,8 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -78,7 +79,7 @@ fun DeserializedMemberDescriptor.isFromJvmPackagePart(): Boolean =
fun ValueParameterDescriptor.getParameterNameAnnotation(): AnnotationDescriptor? { fun ValueParameterDescriptor.getParameterNameAnnotation(): AnnotationDescriptor? {
val annotation = annotations.findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME) ?: return null val annotation = annotations.findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME) ?: return null
if (annotation.firstArgumentValue()?.safeAs<String>()?.isEmpty() != false) { if (annotation.firstArgument()?.safeAs<StringValue>()?.value?.isEmpty() != false) {
return null return null
} }
@@ -91,8 +92,8 @@ object NullDefaultValue : AnnotationDefaultValue()
fun ValueParameterDescriptor.getDefaultValueFromAnnotation(): AnnotationDefaultValue? { fun ValueParameterDescriptor.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
annotations.findAnnotation(JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME) annotations.findAnnotation(JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME)
?.firstArgumentValue() ?.firstArgument()
?.safeAs<String>() ?.safeAs<StringValue>()?.value
?.let { return StringDefaultValue(it) } ?.let { return StringDefaultValue(it) }
if (annotations.hasAnnotation(JvmAnnotationNames.DEFAULT_NULL_FQ_NAME)) { if (annotations.hasAnnotation(JvmAnnotationNames.DEFAULT_NULL_FQ_NAME)) {
@@ -36,7 +36,8 @@ import org.jetbrains.kotlin.load.java.structure.JavaMethod
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
import org.jetbrains.kotlin.resolve.retainMostSpecificInEachOverridableGroup import org.jetbrains.kotlin.resolve.retainMostSpecificInEachOverridableGroup
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude.NonExtensions
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -174,8 +175,8 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
val typeUsage = TypeUsage.COMMON.toAttributes() val typeUsage = TypeUsage.COMMON.toAttributes()
val parameterName = annotations val parameterName = annotations
.findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME) .findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME)
?.firstArgumentValue() ?.firstArgument()
?.safeAs<String>() ?.safeAs<StringValue>()?.value
val (outType, varargElementType) = val (outType, varargElementType) =
if (javaParameter.isVararg) { if (javaParameter.isVararg) {
@@ -30,7 +30,8 @@ import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgumentValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -49,12 +50,10 @@ class SignatureEnhancement(
) { ) {
private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? { private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? {
val enumEntryDescriptor = firstArgumentValue() val enumEntryDescriptor = firstArgument().safeAs<EnumValue>()?.value
// if no argument is specified, use default value: NOT_NULL // if no argument is specified, use default value: NOT_NULL
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) ?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
if (enumEntryDescriptor !is ClassDescriptor) return null
return when (enumEntryDescriptor.name.asString()) { return when (enumEntryDescriptor.name.asString()) {
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) "ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
"MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) "MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.getContainingClass import org.jetbrains.kotlin.resolve.DescriptorUtils.getContainingClass
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -416,7 +417,7 @@ fun ClassDescriptor.isSubclassOf(superclass: ClassDescriptor): Boolean = Descrip
val AnnotationDescriptor.annotationClass: ClassDescriptor? val AnnotationDescriptor.annotationClass: ClassDescriptor?
get() = type.constructor.declarationDescriptor as? ClassDescriptor get() = type.constructor.declarationDescriptor as? ClassDescriptor
fun AnnotationDescriptor.firstArgumentValue() = allValueArguments.values.firstOrNull()?.value fun AnnotationDescriptor.firstArgument(): ConstantValue<*>? = allValueArguments.values.firstOrNull()
fun MemberDescriptor.isEffectivelyExternal(): Boolean { fun MemberDescriptor.isEffectivelyExternal(): Boolean {
if (isExternal) return true if (isExternal) return true
@@ -54,10 +54,12 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.util.aliasImportMap import org.jetbrains.kotlin.util.aliasImportMap
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KotlinLanguageInjector( class KotlinLanguageInjector(
private val configuration: Configuration, private val configuration: Configuration,
@@ -334,7 +336,7 @@ class KotlinLanguageInjector(
val parameterDescriptor = functionDescriptor.valueParameters.getOrNull(argumentIndex) ?: return null val parameterDescriptor = functionDescriptor.valueParameters.getOrNull(argumentIndex) ?: return null
val injectAnnotation = parameterDescriptor.annotations.findAnnotation(FqName(AnnotationUtil.LANGUAGE)) ?: return null val injectAnnotation = parameterDescriptor.annotations.findAnnotation(FqName(AnnotationUtil.LANGUAGE)) ?: return null
val languageId = injectAnnotation.argumentValue("value") as? String ?: return null val languageId = injectAnnotation.argumentValue("value")?.safeAs<StringValue>()?.value ?: return null
return InjectionInfo(languageId, null, null) return InjectionInfo(languageId, null, null)
} }
@@ -24,7 +24,6 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
@@ -45,10 +44,13 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.util.constructors import org.jetbrains.kotlin.util.constructors
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
//TODO: different replacements for property accessors //TODO: different replacements for property accessors
@@ -77,10 +79,11 @@ abstract class DeprecatedSymbolUsageFixBase(
companion object { companion object {
fun fetchReplaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? { fun fetchReplaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? {
val annotation = descriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated) ?: return null val annotation = descriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated) ?: return null
val replaceWithValue = annotation.argumentValue(kotlin.Deprecated::replaceWith.name) as? AnnotationDescriptor ?: return null val replaceWithValue =
val pattern = replaceWithValue.argumentValue(kotlin.ReplaceWith::expression.name) as? String ?: return null annotation.argumentValue(kotlin.Deprecated::replaceWith.name)?.safeAs<AnnotationValue>()?.value ?: return null
val pattern = replaceWithValue.argumentValue(kotlin.ReplaceWith::expression.name)?.safeAs<StringValue>()?.value ?: return null
if (pattern.isEmpty()) return null if (pattern.isEmpty()) return null
val importValues = replaceWithValue.argumentValue(kotlin.ReplaceWith::imports.name) as? List<*> ?: return null val importValues = replaceWithValue.argumentValue(kotlin.ReplaceWith::imports.name)?.safeAs<ArrayValue>()?.value ?: return null
if (importValues.any { it !is StringValue }) return null if (importValues.any { it !is StringValue }) return null
val imports = importValues.map { (it as StringValue).value } val imports = importValues.map { (it as StringValue).value }