Extract TargetedAnnotations out of AnnotationsImpl

Minimize AnnotationsImpl to leave it usable in simple scenarios where
there's no use-site targeted annotations, and use TargetedAnnotations in
the only place in the frontend (AnnotationResolverImpl) where use-sites
were needed.

Also, delete kdoc on Annotations.isEmpty to prevent readers from putting
too much thought into how it works. With the exception of a few places
in the frontend where use-site targeted annotations are still accessed
via the Annotations object, it's now an implementation detail and users
(such as backends, IDE) should not care about them at all, and instead
should just deal with the correct element when processing annotations
This commit is contained in:
Alexander Udalov
2018-08-23 00:11:12 +02:00
parent c0b025b23d
commit eef11c669a
6 changed files with 38 additions and 51 deletions
@@ -108,11 +108,9 @@ class AnnotationSplitter(
other.add(annotation)
}
for ((annotation, useSiteTarget) in allAnnotations.getUseSiteTargetedAnnotations()) {
if (useSiteTarget == null) continue
if (useSiteTarget in applicableTargets) {
map.getOrPut(useSiteTarget) { arrayListOf() }.add(annotation)
for ((annotation, target) in allAnnotations.getUseSiteTargetedAnnotations()) {
if (target in applicableTargets) {
map.getOrPut(target) { arrayListOf() }.add(annotation)
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.descriptors.annotations
class TargetedAnnotations(
private val standardAnnotations: List<AnnotationDescriptor>,
private val targetedAnnotations: List<AnnotationWithTarget>
) : Annotations {
override fun isEmpty(): Boolean = standardAnnotations.isEmpty() && targetedAnnotations.isEmpty()
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = targetedAnnotations
override fun iterator(): Iterator<AnnotationDescriptor> = standardAnnotations.iterator()
override fun toString(): String = (standardAnnotations + targetedAnnotations).toString()
}
@@ -17,10 +17,14 @@
package org.jetbrains.kotlin.resolve;
import com.intellij.psi.util.PsiTreeUtil;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.annotations.TargetedAnnotations;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.CallResolver;
@@ -79,7 +83,9 @@ public class AnnotationResolverImpl extends AnnotationResolver {
boolean shouldResolveArguments
) {
if (annotationEntryElements.isEmpty()) return Annotations.Companion.getEMPTY();
List<AnnotationWithTarget> result = new ArrayList<>(0);
List<AnnotationDescriptor> standard = new ArrayList<>();
List<AnnotationWithTarget> targeted = new ArrayList<>();
for (KtAnnotationEntry entryElement : annotationEntryElements) {
AnnotationDescriptor descriptor = trace.get(BindingContext.ANNOTATION, entryElement);
@@ -92,13 +98,13 @@ public class AnnotationResolverImpl extends AnnotationResolver {
KtAnnotationUseSiteTarget target = entryElement.getUseSiteTarget();
if (target != null) {
result.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
targeted.add(new AnnotationWithTarget(descriptor, target.getAnnotationUseSiteTarget()));
}
else {
result.add(new AnnotationWithTarget(descriptor, null));
standard.add(descriptor);
}
}
return AnnotationsImpl.create(result);
return new TargetedAnnotations(CollectionsKt.toList(standard), CollectionsKt.toList(targeted));
}
@Override
@@ -16,4 +16,4 @@
package org.jetbrains.kotlin.descriptors.annotations
data class AnnotationWithTarget(val annotation: AnnotationDescriptor, val target: AnnotationUseSiteTarget?)
data class AnnotationWithTarget(val annotation: AnnotationDescriptor, val target: AnnotationUseSiteTarget)
@@ -23,12 +23,6 @@ interface Annotated {
}
interface Annotations : Iterable<AnnotationDescriptor> {
/**
* @return `true` iff there are no "direct" annotations applicable to this declaration. Note that even if [isEmpty] is `true`,
* there may be use-site-targeted annotations applicable to the declaration!
*
* @see getUseSiteTargetedAnnotations
*/
fun isEmpty(): Boolean
fun findAnnotation(fqName: FqName): AnnotationDescriptor? = firstOrNull { it.fqName == fqName }
@@ -16,40 +16,10 @@
package org.jetbrains.kotlin.descriptors.annotations
class AnnotationsImpl : Annotations {
private val annotations: List<AnnotationDescriptor>
private val targetedAnnotations: List<AnnotationWithTarget>
class AnnotationsImpl(private val annotations: List<AnnotationDescriptor>) : Annotations {
override fun isEmpty(): Boolean = annotations.isEmpty()
constructor(annotations: List<AnnotationDescriptor>) {
this.annotations = annotations
this.targetedAnnotations = annotations.map { AnnotationWithTarget(it, null) }
}
override fun iterator(): Iterator<AnnotationDescriptor> = annotations.iterator()
// List<AnnotationDescriptor> and List<AnnotationWithTarget> have the same signature
private constructor(
targetedAnnotations: List<AnnotationWithTarget>,
@Suppress("UNUSED_PARAMETER") i: Int
) {
this.targetedAnnotations = targetedAnnotations
this.annotations = targetedAnnotations.filter { it.target == null }.map { it.annotation }
}
override fun isEmpty() = targetedAnnotations.isEmpty()
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> {
return targetedAnnotations
.filter { it.target != null }
.map { AnnotationWithTarget(it.annotation, it.target!!) }
}
override fun iterator() = annotations.iterator()
override fun toString() = annotations.toString()
companion object {
@JvmStatic
fun create(annotationsWithTargets: List<AnnotationWithTarget>): AnnotationsImpl {
return AnnotationsImpl(annotationsWithTargets, 0)
}
}
override fun toString(): String = annotations.toString()
}