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.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ErrorValue
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() =
DescriptorUtils.getAnnotationByFqName(annotations, STRICTFP_ANNOTATION_FQ_NAME)
fun AnnotationDescriptor.argumentValue(parameterName: String): Any? {
return allValueArguments[Name.identifier(parameterName)].takeUnless { it is ErrorValue }?.value
fun AnnotationDescriptor.argumentValue(parameterName: String): ConstantValue<*>? {
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.calls.checkers.isOperatorMod
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.serialization.ProtoBuf
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.TypeUtils
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val JAVA_DEPRECATED = FqName("java.lang.Deprecated")
@@ -55,27 +59,22 @@ fun Deprecation.deprecatedByOverriddenMessage(): String? = (this as? DeprecatedB
fun Deprecation.deprecatedByAnnotationReplaceWithExpression(): String? {
val annotation = (this as? DeprecatedByAnnotation)?.annotation ?: return null
val replaceWithAnnotation = annotation.argumentValue(kotlin.Deprecated::replaceWith.name)
as? AnnotationDescriptor ?: return null
return replaceWithAnnotation.argumentValue(kotlin.ReplaceWith::expression.name) as String
val replaceWithAnnotation =
annotation.argumentValue(kotlin.Deprecated::replaceWith.name)?.safeAs<AnnotationValue>()?.value ?: return null
return replaceWithAnnotation.argumentValue(kotlin.ReplaceWith::expression.name)?.safeAs<StringValue>()?.value
}
private data class DeprecatedByAnnotation(val annotation: AnnotationDescriptor, override val target: DeclarationDescriptor) : Deprecation {
override val deprecationLevel: DeprecationLevelValue
get() {
val level = annotation.argumentValue("level") as? ClassDescriptor
return when (level?.name?.asString()) {
"WARNING" -> WARNING
"ERROR" -> ERROR
"HIDDEN" -> HIDDEN
else -> WARNING
}
get() = when (annotation.argumentValue("level")?.safeAs<EnumValue>()?.enumEntryName?.asString()) {
"WARNING" -> WARNING
"ERROR" -> ERROR
"HIDDEN" -> HIDDEN
else -> WARNING
}
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 {
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
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.storage.StorageManager
import org.jetbrains.kotlin.utils.Jsr305State
@@ -148,7 +148,7 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
}
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
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.lazy.descriptors.LazyJavaStaticClassScope
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.module
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -78,7 +79,7 @@ fun DeserializedMemberDescriptor.isFromJvmPackagePart(): Boolean =
fun ValueParameterDescriptor.getParameterNameAnnotation(): AnnotationDescriptor? {
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
}
@@ -91,8 +92,8 @@ object NullDefaultValue : AnnotationDefaultValue()
fun ValueParameterDescriptor.getDefaultValueFromAnnotation(): AnnotationDefaultValue? {
annotations.findAnnotation(JvmAnnotationNames.DEFAULT_VALUE_FQ_NAME)
?.firstArgumentValue()
?.safeAs<String>()
?.firstArgument()
?.safeAs<StringValue>()?.value
?.let { return StringDefaultValue(it) }
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.name.Name
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.scopes.DescriptorKindExclude.NonExtensions
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 parameterName = annotations
.findAnnotation(JvmAnnotationNames.PARAMETER_NAME_FQ_NAME)
?.firstArgumentValue()
?.safeAs<String>()
?.firstArgument()
?.safeAs<StringValue>()?.value
val (outType, varargElementType) =
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.name.FqName
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.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -49,12 +50,10 @@ class SignatureEnhancement(
) {
private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? {
val enumEntryDescriptor = firstArgumentValue()
val enumEntryDescriptor = firstArgument().safeAs<EnumValue>()?.value
// if no argument is specified, use default value: NOT_NULL
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
if (enumEntryDescriptor !is ClassDescriptor) return null
return when (enumEntryDescriptor.name.asString()) {
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
"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.resolve.DescriptorUtils
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.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -416,7 +417,7 @@ fun ClassDescriptor.isSubclassOf(superclass: ClassDescriptor): Boolean = Descrip
val AnnotationDescriptor.annotationClass: 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 {
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.psi.*
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.util.aliasImportMap
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KotlinLanguageInjector(
private val configuration: Configuration,
@@ -334,7 +336,7 @@ class KotlinLanguageInjector(
val parameterDescriptor = functionDescriptor.valueParameters.getOrNull(argumentIndex) ?: 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)
}
@@ -24,7 +24,6 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
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.calls.callUtil.getResolvedCall
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.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.util.constructors
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
//TODO: different replacements for property accessors
@@ -77,10 +79,11 @@ abstract class DeprecatedSymbolUsageFixBase(
companion object {
fun fetchReplaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? {
val annotation = descriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated) ?: return null
val replaceWithValue = annotation.argumentValue(kotlin.Deprecated::replaceWith.name) as? AnnotationDescriptor ?: return null
val pattern = replaceWithValue.argumentValue(kotlin.ReplaceWith::expression.name) as? String ?: return null
val replaceWithValue =
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
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
val imports = importValues.map { (it as StringValue).value }