Introduce optimized BuiltInAnnotationDescriptor for built-in annotations

It's built on a FQ name and avoids resolution of the annotation class
descriptor as much as possible
This commit is contained in:
Alexander Udalov
2017-07-04 17:22:33 +03:00
parent f39106f75c
commit 541b9dab52
6 changed files with 61 additions and 41 deletions
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
import org.jetbrains.kotlin.descriptors.annotations.createUnsafeVarianceAnnotation
import org.jetbrains.kotlin.types.*
internal class UnsafeVarianceTypeSubstitution(kotlinBuiltIns: KotlinBuiltIns) : TypeSubstitution() {
private val unsafeVarianceAnnotations = AnnotationsImpl(listOf(kotlinBuiltIns.createUnsafeVarianceAnnotation()))
internal class UnsafeVarianceTypeSubstitution(builtIns: KotlinBuiltIns) : TypeSubstitution() {
private val unsafeVarianceAnnotations = AnnotationsImpl(listOf(
BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.unsafeVariance, emptyMap())
))
override fun get(key: KotlinType) = null
@@ -563,11 +563,6 @@ public abstract class KotlinBuiltIns {
return getBuiltInClassByName("Throwable");
}
@NotNull
public ClassDescriptor getDeprecatedAnnotation() {
return getBuiltInClassByName(FQ_NAMES.deprecated.shortName());
}
@Nullable
private static ClassDescriptor getEnumEntry(@NotNull ClassDescriptor enumDescriptor, @NotNull String entryName) {
ClassifierDescriptor result = enumDescriptor.getUnsubstitutedInnerClassesScope().getContributedClassifier(
@@ -20,10 +20,9 @@ import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFac
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
@@ -164,12 +163,10 @@ fun getFunctionTypeArgumentProjections(
parameterTypes.mapIndexedTo(arguments) { index, type ->
val name = parameterNames?.get(index)?.takeUnless { it.isSpecial }
val typeToUse = if (name != null) {
val annotationClass = builtIns.getBuiltInClassByName(KotlinBuiltIns.FQ_NAMES.parameterName.shortName())
val nameValue = ConstantValueFactory(builtIns).createStringValue(name.asString())
val parameterNameAnnotation = AnnotationDescriptorImpl(
annotationClass.defaultType,
mapOf(Name.identifier("name") to nameValue),
SourceElement.NO_SOURCE
val parameterNameAnnotation = BuiltInAnnotationDescriptor(
builtIns,
KotlinBuiltIns.FQ_NAMES.parameterName,
mapOf(Name.identifier("name") to ConstantValueFactory(builtIns).createStringValue(name.asString()))
)
type.replaceAnnotations(AnnotationsImpl(type.annotations + parameterNameAnnotation))
}
@@ -199,18 +196,14 @@ fun createFunctionType(
val parameterCount = if (receiverType == null) size else size + 1
val classDescriptor = if (suspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
// TODO: preserve laziness of given annotations
val typeAnnotations =
if (receiverType == null || annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) != null) {
annotations
}
else {
val extensionFunctionAnnotation = AnnotationDescriptorImpl(
builtIns.getBuiltInClassByName(KotlinBuiltIns.FQ_NAMES.extensionFunctionType.shortName()).defaultType,
emptyMap(), SourceElement.NO_SOURCE
)
// TODO: preserve laziness of given annotations
AnnotationsImpl(annotations + extensionFunctionAnnotation)
AnnotationsImpl(annotations +
BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.extensionFunctionType, emptyMap()))
}
return KotlinTypeFactory.simpleNotNullType(typeAnnotations, classDescriptor, arguments)
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.descriptors.annotations
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.types.KotlinType
import kotlin.LazyThreadSafetyMode.PUBLICATION
class BuiltInAnnotationDescriptor(
private val builtIns: KotlinBuiltIns,
override val fqName: FqName,
override val allValueArguments: Map<Name, ConstantValue<*>>
) : AnnotationDescriptor {
override val type: KotlinType by lazy(PUBLICATION) {
builtIns.getBuiltInClassByFqName(fqName).defaultType
}
override val source: SourceElement
get() = SourceElement.NO_SOURCE
}
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -36,23 +35,23 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
replaceWith: String = "",
level: String = "WARNING"
): AnnotationDescriptor {
val replaceWithAnnotation = AnnotationDescriptorImpl(
getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.replaceWith).defaultType,
val replaceWithAnnotation = BuiltInAnnotationDescriptor(
this,
KotlinBuiltIns.FQ_NAMES.replaceWith,
mapOf(
REPLACE_WITH_EXPRESSION_NAME to StringValue(replaceWith, this),
REPLACE_WITH_IMPORTS_NAME to ArrayValue(emptyList(), getArrayType(Variance.INVARIANT, stringType), this)
),
SourceElement.NO_SOURCE
)
)
return AnnotationDescriptorImpl(
deprecatedAnnotation.defaultType,
return BuiltInAnnotationDescriptor(
this,
KotlinBuiltIns.FQ_NAMES.deprecated,
mapOf(
DEPRECATED_MESSAGE_NAME to StringValue(message, this),
DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
DEPRECATED_LEVEL_NAME to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found"))
),
SourceElement.NO_SOURCE
)
)
}
@@ -62,11 +61,6 @@ private val DEPRECATED_LEVEL_NAME = Name.identifier("level")
private val REPLACE_WITH_EXPRESSION_NAME = Name.identifier("expression")
private val REPLACE_WITH_IMPORTS_NAME = Name.identifier("imports")
fun KotlinBuiltIns.createUnsafeVarianceAnnotation(): AnnotationDescriptor {
val unsafeVarianceAnnotation = getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.unsafeVariance)
return AnnotationDescriptorImpl(unsafeVarianceAnnotation.defaultType, emptyMap(), SourceElement.NO_SOURCE)
}
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
fun MemberDescriptor.isInlineOnlyOrReifiable(): Boolean =
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.quickfix.replaceWith
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
@@ -37,12 +38,10 @@ import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.resolve.DescriptorUtils
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.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -73,8 +72,7 @@ abstract class DeprecatedSymbolUsageFixBase(
companion object {
fun fetchReplaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? {
val annotationClass = descriptor.builtIns.deprecatedAnnotation
val annotation = descriptor.annotations.findAnnotation(DescriptorUtils.getFqNameSafe(annotationClass)) ?: 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 pattern = replaceWithValue.argumentValue(kotlin.ReplaceWith::expression.name) as? String ?: return null
if (pattern.isEmpty()) return null