[SLC] avoid redundant empty array allocation and add new array creation
we should instantiate a new array on each request to avoid unexpected mutation from a usage side ^KT-56046
This commit is contained in:
committed by
Space Team
parent
3b9318bd3a
commit
347dc83773
+1
-1
@@ -9,7 +9,7 @@ import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiModifierList
|
||||
|
||||
internal sealed interface AnnotationsBox {
|
||||
fun annotations(owner: PsiModifierList): Array<PsiAnnotation>
|
||||
fun annotationsArray(owner: PsiModifierList): Array<PsiAnnotation>
|
||||
fun findAnnotation(owner: PsiModifierList, qualifiedName: String): PsiAnnotation?
|
||||
fun hasAnnotation(owner: PsiModifierList, qualifiedName: String): Boolean = findAnnotation(owner, qualifiedName) != null
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@ import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiModifierList
|
||||
|
||||
internal object EmptyAnnotationsBox : AnnotationsBox {
|
||||
override fun annotations(owner: PsiModifierList): Array<PsiAnnotation> = PsiAnnotation.EMPTY_ARRAY
|
||||
override fun annotationsArray(owner: PsiModifierList): Array<PsiAnnotation> = PsiAnnotation.EMPTY_ARRAY
|
||||
override fun findAnnotation(owner: PsiModifierList, qualifiedName: String): PsiAnnotation? = null
|
||||
}
|
||||
|
||||
+16
-18
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations
|
||||
|
||||
import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiModifierList
|
||||
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
@@ -17,10 +18,10 @@ internal class LazyAnnotationsBox(
|
||||
private val additionalAnnotationsProvider: AdditionalAnnotationsProvider = EmptyAdditionalAnnotationsProvider,
|
||||
private val annotationFilter: AnnotationFilter = AlwaysAllowedAnnotationFilter,
|
||||
) : AnnotationsBox {
|
||||
private val annotationsArray: AtomicReference<Array<PsiAnnotation>?> = AtomicReference()
|
||||
private val cachedCollection: AtomicReference<Collection<PsiAnnotation>?> = AtomicReference()
|
||||
|
||||
override fun annotations(owner: PsiModifierList): Array<PsiAnnotation> {
|
||||
annotationsArray.get()?.let { return it }
|
||||
private fun getOrComputeCachedAnnotations(owner: PsiModifierList): Collection<PsiAnnotation> {
|
||||
cachedCollection.get()?.let { return it }
|
||||
|
||||
val annotations = annotationsProvider.annotationInfos().mapNotNullTo(SmartList<PsiAnnotation>()) { applicationInfo ->
|
||||
applicationInfo.classId?.let { _ ->
|
||||
@@ -32,17 +33,14 @@ internal class LazyAnnotationsBox(
|
||||
additionalAnnotationsProvider.addAllAnnotations(annotations, foundQualifiers, owner)
|
||||
|
||||
val resultAnnotations = annotationFilter.filtered(annotations)
|
||||
return setAnnotationsArray(
|
||||
if (resultAnnotations.isNotEmpty()) resultAnnotations.toTypedArray<PsiAnnotation>() else PsiAnnotation.EMPTY_ARRAY
|
||||
)
|
||||
cachedCollection.compareAndSet(null, resultAnnotations)
|
||||
|
||||
return getOrComputeCachedAnnotations(owner)
|
||||
}
|
||||
|
||||
private fun setAnnotationsArray(array: Array<PsiAnnotation>): Array<PsiAnnotation> =
|
||||
if (annotationsArray.compareAndSet(null, array)) {
|
||||
array
|
||||
} else {
|
||||
annotationsArray.get() ?: error("Unexpected state")
|
||||
}
|
||||
override fun annotationsArray(owner: PsiModifierList): Array<PsiAnnotation> {
|
||||
return getOrComputeCachedAnnotations(owner).toArrayIfNotEmptyOrDefault(PsiAnnotation.EMPTY_ARRAY)
|
||||
}
|
||||
|
||||
override fun findAnnotation(
|
||||
owner: PsiModifierList,
|
||||
@@ -52,8 +50,8 @@ internal class LazyAnnotationsBox(
|
||||
fun findAnnotation(owner: PsiModifierList, qualifiedName: String, withAdditionalAnnotations: Boolean): PsiAnnotation? {
|
||||
if (!annotationFilter.isAllowed(qualifiedName)) return null
|
||||
|
||||
annotationsArray.get()?.let { array ->
|
||||
return array.find { it.qualifiedName == qualifiedName }
|
||||
cachedCollection.get()?.let { annotations ->
|
||||
return annotations.find { it.qualifiedName == qualifiedName }
|
||||
}
|
||||
|
||||
val specialAnnotationClassId = specialAnnotationsList[qualifiedName]
|
||||
@@ -66,21 +64,21 @@ internal class LazyAnnotationsBox(
|
||||
null
|
||||
}
|
||||
|
||||
return specialAnnotation ?: annotations(owner).find { it.qualifiedName == qualifiedName }
|
||||
return specialAnnotation ?: getOrComputeCachedAnnotations(owner).find { it.qualifiedName == qualifiedName }
|
||||
}
|
||||
|
||||
override fun hasAnnotation(owner: PsiModifierList, qualifiedName: String): Boolean {
|
||||
if (!annotationFilter.isAllowed(qualifiedName)) return false
|
||||
|
||||
annotationsArray.get()?.let { array ->
|
||||
return array.any { it.qualifiedName == qualifiedName }
|
||||
cachedCollection.get()?.let { annotations ->
|
||||
return annotations.any { it.qualifiedName == qualifiedName }
|
||||
}
|
||||
|
||||
val specialAnnotationClassId = specialAnnotationsList[qualifiedName]
|
||||
return if (specialAnnotationClassId != null) {
|
||||
specialAnnotationClassId in annotationsProvider
|
||||
} else {
|
||||
annotations(owner).any { it.qualifiedName == qualifiedName }
|
||||
getOrComputeCachedAnnotations(owner).any { it.qualifiedName == qualifiedName }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-10
@@ -7,24 +7,23 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations
|
||||
|
||||
import com.intellij.psi.PsiAnnotation
|
||||
import com.intellij.psi.PsiModifierList
|
||||
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
internal class SimpleAnnotationsBox(private val annotationsComputer: (PsiModifierList) -> Collection<PsiAnnotation>) : AnnotationsBox {
|
||||
private val annotations: AtomicReference<Array<PsiAnnotation>?> = AtomicReference()
|
||||
private val cachedCollection: AtomicReference<Collection<PsiAnnotation>?> = AtomicReference()
|
||||
|
||||
private fun getOrComputeAnnotations(owner: PsiModifierList): Array<PsiAnnotation> {
|
||||
annotations.get()?.let { return it }
|
||||
private fun getOrComputeAnnotations(owner: PsiModifierList): Collection<PsiAnnotation> {
|
||||
cachedCollection.get()?.let { return it }
|
||||
|
||||
val nonCachedAnnotations = annotationsComputer(owner)
|
||||
val resultArray = if (nonCachedAnnotations.isEmpty()) PsiAnnotation.EMPTY_ARRAY else nonCachedAnnotations.toTypedArray()
|
||||
return if (annotations.compareAndSet(null, resultArray)) {
|
||||
resultArray
|
||||
} else {
|
||||
getOrComputeAnnotations(owner)
|
||||
}
|
||||
cachedCollection.compareAndSet(null, nonCachedAnnotations)
|
||||
return getOrComputeAnnotations(owner)
|
||||
}
|
||||
|
||||
override fun annotations(owner: PsiModifierList): Array<PsiAnnotation> = getOrComputeAnnotations(owner)
|
||||
override fun annotationsArray(
|
||||
owner: PsiModifierList,
|
||||
): Array<PsiAnnotation> = getOrComputeAnnotations(owner).toArrayIfNotEmptyOrDefault(PsiAnnotation.EMPTY_ARRAY)
|
||||
|
||||
override fun findAnnotation(
|
||||
owner: PsiModifierList,
|
||||
|
||||
+4
-3
@@ -8,18 +8,19 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations
|
||||
import com.intellij.psi.PsiNameValuePair
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
|
||||
|
||||
internal class SymbolLightLazyAnnotationParameterList(
|
||||
parent: SymbolLightAbstractAnnotation,
|
||||
private val lazyArguments: Lazy<List<KtNamedAnnotationValue>>,
|
||||
) : SymbolLightAbstractAnnotationParameterList(parent) {
|
||||
private val _attributes: Array<PsiNameValuePair> by lazyPub {
|
||||
private val _attributes: Collection<PsiNameValuePair> by lazyPub {
|
||||
val attributes = lazyArguments.value.map {
|
||||
SymbolNameValuePairForAnnotationArgument(it, this)
|
||||
}
|
||||
|
||||
if (attributes.isEmpty()) PsiNameValuePair.EMPTY_ARRAY else attributes.toTypedArray()
|
||||
attributes
|
||||
}
|
||||
|
||||
override fun getAttributes(): Array<PsiNameValuePair> = _attributes
|
||||
override fun getAttributes(): Array<PsiNameValuePair> = _attributes.toArrayIfNotEmptyOrDefault(PsiNameValuePair.EMPTY_ARRAY)
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ internal class SymbolLightClassForEnumEntry(
|
||||
|
||||
override fun getContainingClass(): PsiClass = enumClass
|
||||
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
|
||||
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
||||
|
||||
override fun getQualifiedName(): String = "${enumConstant.containingClass.qualifiedName}.${enumConstant.name}"
|
||||
|
||||
+1
-2
@@ -236,8 +236,7 @@ class SymbolLightClassForFacade(
|
||||
return JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope)
|
||||
}
|
||||
|
||||
override fun getSupers(): Array<PsiClass> =
|
||||
superClass?.let { arrayOf(it) } ?: arrayOf()
|
||||
override fun getSupers(): Array<PsiClass> = superClass?.let { arrayOf(it) } ?: PsiClass.EMPTY_ARRAY
|
||||
|
||||
override fun getSuperTypes(): Array<PsiClassType> =
|
||||
arrayOf(PsiType.getJavaLangObject(manager, resolveScope))
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ internal class SymbolLightClassForInterfaceDefaultImpls(private val containingCl
|
||||
override fun hashCode(): Int = containingClass.hashCode()
|
||||
|
||||
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
|
||||
|
||||
override fun computeModifierList(): PsiModifierList = SymbolLightClassModifierList(
|
||||
containingDeclaration = this,
|
||||
|
||||
+3
-4
@@ -12,12 +12,11 @@ internal abstract class SymbolLightPsiJavaCodeReferenceElementBase(private val k
|
||||
PsiElement by ktElement,
|
||||
PsiJavaCodeReferenceElement {
|
||||
|
||||
override fun multiResolve(incompleteCode: Boolean): Array<JavaResolveResult> = emptyArray()
|
||||
override fun multiResolve(incompleteCode: Boolean): Array<JavaResolveResult> = JavaResolveResult.EMPTY_ARRAY
|
||||
|
||||
override fun processVariants(processor: PsiScopeProcessor) {}
|
||||
|
||||
override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult =
|
||||
JavaResolveResult.EMPTY
|
||||
override fun advancedResolve(incompleteCode: Boolean): JavaResolveResult = JavaResolveResult.EMPTY
|
||||
|
||||
override fun getQualifier(): PsiElement? = null
|
||||
|
||||
@@ -27,7 +26,7 @@ internal abstract class SymbolLightPsiJavaCodeReferenceElementBase(private val k
|
||||
|
||||
override fun getParameterList(): PsiReferenceParameterList? = null
|
||||
|
||||
override fun getTypeParameters(): Array<PsiType> = emptyArray()
|
||||
override fun getTypeParameters(): Array<PsiType> = PsiType.EMPTY_ARRAY
|
||||
|
||||
override fun isQualified(): Boolean = false
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ internal sealed class SymbolLightModifierList<out T : KtLightElement<KtModifierL
|
||||
override fun hasExplicitModifier(name: String) = hasModifierProperty(name)
|
||||
override fun hasModifierProperty(name: String): Boolean = modifiersBox.hasModifier(name)
|
||||
|
||||
override fun getAnnotations(): Array<PsiAnnotation> = annotationsBox.annotations(this)
|
||||
override fun getAnnotations(): Array<PsiAnnotation> = annotationsBox.annotationsArray(this)
|
||||
override fun getApplicableAnnotations(): Array<PsiAnnotation> = annotations
|
||||
override fun findAnnotation(qualifiedName: String): PsiAnnotation? = annotationsBox.findAnnotation(this, qualifiedName)
|
||||
override fun hasAnnotation(qualifiedName: String): Boolean = annotationsBox.hasAnnotation(this, qualifiedName)
|
||||
|
||||
+4
-3
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.light.classes.symbol.basicIsEquivalentTo
|
||||
import org.jetbrains.kotlin.light.classes.symbol.compareSymbolPointers
|
||||
import org.jetbrains.kotlin.light.classes.symbol.toArrayIfNotEmptyOrDefault
|
||||
import org.jetbrains.kotlin.light.classes.symbol.withSymbol
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||
|
||||
@@ -39,7 +40,7 @@ internal class SymbolLightTypeParameterList(
|
||||
place: PsiElement
|
||||
): Boolean = typeParameters.all { processor.execute(it, state) }
|
||||
|
||||
private val _typeParameters: Array<PsiTypeParameter> by lazyPub {
|
||||
private val _typeParameters: Collection<PsiTypeParameter> by lazyPub {
|
||||
symbolWithTypeParameterPointer.withSymbol(ktModule) {
|
||||
it.typeParameters.mapIndexed { index, parameter ->
|
||||
SymbolLightTypeParameter(
|
||||
@@ -48,11 +49,11 @@ internal class SymbolLightTypeParameterList(
|
||||
index = index,
|
||||
typeParameterSymbol = parameter,
|
||||
)
|
||||
}.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameters
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameters.toArrayIfNotEmptyOrDefault(PsiTypeParameter.EMPTY_ARRAY)
|
||||
|
||||
override fun getTypeParameterIndex(typeParameter: PsiTypeParameter?): Int = _typeParameters.indexOf(typeParameter)
|
||||
|
||||
|
||||
+4
@@ -271,3 +271,7 @@ internal inline fun <T : KtSymbol, R> KtSymbolPointer<T>.withSymbol(
|
||||
internal val KtPropertySymbol.isConstOrJvmField: Boolean get() = isConst || hasJvmFieldAnnotation()
|
||||
internal val KtPropertySymbol.isConst: Boolean get() = (this as? KtKotlinPropertySymbol)?.isConst == true
|
||||
internal val KtPropertySymbol.isLateInit: Boolean get() = (this as? KtKotlinPropertySymbol)?.isLateInit == true
|
||||
|
||||
internal inline fun <reified T> Collection<T>.toArrayIfNotEmptyOrDefault(default: Array<T>): Array<T> {
|
||||
return if (isNotEmpty()) toTypedArray() else default
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user