From 890d18e7bee44a5e6714f18760edb867c8149959 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 13 Apr 2015 17:25:52 +0300 Subject: [PATCH] Support external annotations in IDE when approximating flexible types --- .../lazy/descriptors/LazyAnnotations.kt | 26 +++---- .../load/java/lazy/LazyJavaAnnotations.kt | 13 +++- .../descriptors/annotations/Annotations.kt | 4 ++ .../annotations/AnnotationsImpl.java | 68 ------------------- .../annotations/AnnotationsImpl.kt | 36 ++++++++++ .../descriptors/DeserializedAnnotations.kt | 10 +-- .../jetbrains/kotlin/idea/util/TypeUtils.kt | 23 +++---- 7 files changed, 78 insertions(+), 102 deletions(-) delete mode 100644 core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.java create mode 100644 core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt index 72fbdf7b44b..327b0e1f45e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyAnnotations.kt @@ -16,20 +16,20 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.resolve.lazy.LazyEntity -import org.jetbrains.kotlin.psi.JetAnnotationEntry -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetAnnotationEntry +import org.jetbrains.kotlin.resolve.AnnotationResolver +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil -import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.resolve.AnnotationResolver -import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.lazy.LazyEntity import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.storage.StorageManager abstract class LazyAnnotationsContext( val annotationResolver: AnnotationResolver, @@ -75,9 +75,9 @@ public class LazyAnnotations( return null } - override fun iterator(): Iterator { - return annotationEntries.stream().map(annotation).iterator() - } + override fun findExternalAnnotation(fqName: FqName) = null + + override fun iterator(): Iterator = annotationEntries.sequence().map(annotation).iterator() override fun forceResolveAllContents() { // To resolve all entries diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt index 03bb1e0e57d..169f631dffa 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt @@ -32,9 +32,14 @@ class LazyJavaAnnotations( c.resolveAnnotation(annotation) } - override fun findAnnotation(fqName: FqName) = annotationOwner.findAnnotation(fqName)?.let(annotationDescriptors) + override fun findAnnotation(fqName: FqName) = + annotationOwner.findAnnotation(fqName)?.let(annotationDescriptors) - override fun iterator() = annotationOwner.getAnnotations().sequence().map(annotationDescriptors).filterNotNull().iterator() + override fun findExternalAnnotation(fqName: FqName) = + c.externalAnnotationResolver.findExternalAnnotation(annotationOwner, fqName)?.let(annotationDescriptors) + + override fun iterator() = + annotationOwner.getAnnotations().sequence().map(annotationDescriptors).filterNotNull().iterator() override fun isEmpty() = !iterator().hasNext() } @@ -47,6 +52,10 @@ class FilteredAnnotations( if (fqNameFilter(fqName)) delegate.findAnnotation(fqName) else null + override fun findExternalAnnotation(fqName: FqName) = + if (fqNameFilter(fqName)) delegate.findExternalAnnotation(fqName) + else null + override fun iterator() = delegate.sequence() .filter { annotation -> val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor() diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt index 20d862f1bf2..c008c9559d3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/Annotations.kt @@ -24,12 +24,16 @@ public trait Annotations : Iterable { public fun findAnnotation(fqName: FqName): AnnotationDescriptor? + public fun findExternalAnnotation(fqName: FqName): AnnotationDescriptor? + companion object { public val EMPTY: Annotations = object : Annotations { override fun isEmpty() = true override fun findAnnotation(fqName: FqName) = null + override fun findExternalAnnotation(fqName: FqName) = null + override fun iterator() = emptyList().iterator() override fun toString() = "EMPTY" diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.java deleted file mode 100644 index 18ab45c918c..00000000000 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2010-2015 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.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.resolve.DescriptorUtils; - -import java.util.Iterator; -import java.util.List; - -public class AnnotationsImpl implements Annotations { - private final List annotations; - - public AnnotationsImpl(@NotNull List annotations) { - this.annotations = annotations; - } - - @NotNull - public List getAnnotationDescriptors() { - return annotations; - } - - @Override - public boolean isEmpty() { - return getAnnotationDescriptors().isEmpty(); - } - - @Nullable - @Override - public AnnotationDescriptor findAnnotation(@NotNull FqName fqName) { - for (AnnotationDescriptor annotation : annotations) { - ClassifierDescriptor descriptor = annotation.getType().getConstructor().getDeclarationDescriptor(); - if (descriptor instanceof ClassDescriptor && fqName.toUnsafe().equals(DescriptorUtils.getFqName(descriptor))) { - return annotation; - } - } - return null; - } - - @NotNull - @Override - public Iterator iterator() { - return getAnnotationDescriptors().iterator(); - } - - @Override - public String toString() { - return annotations.toString(); - } -} diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.kt new file mode 100644 index 00000000000..f033e132ce4 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationsImpl.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2015 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.descriptors.ClassDescriptor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.DescriptorUtils + +public class AnnotationsImpl(private val annotations: List) : Annotations { + override fun isEmpty() = annotations.isEmpty() + + override fun findAnnotation(fqName: FqName) = annotations.firstOrNull { + val descriptor = it.getType().getConstructor().getDeclarationDescriptor() + descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor) + } + + override fun findExternalAnnotation(fqName: FqName) = null + + override fun iterator() = annotations.iterator() + + override fun toString() = annotations.toString() +} diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedAnnotations.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedAnnotations.kt index bce7146675b..0889e0b8b4f 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedAnnotations.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedAnnotations.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors -import org.jetbrains.kotlin.utils.toReadOnlyList -import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.utils.toReadOnlyList class DeserializedAnnotations( storageManager: StorageManager, @@ -32,11 +32,13 @@ class DeserializedAnnotations( override fun isEmpty(): Boolean = annotations().isEmpty() - override fun findAnnotation(fqName: FqName): AnnotationDescriptor? = annotations().firstOrNull { + override fun findAnnotation(fqName: FqName) = annotations().firstOrNull { annotation -> val descriptor = annotation.getType().getConstructor().getDeclarationDescriptor() descriptor is ClassDescriptor && fqName.equalsTo(DescriptorUtils.getFqName(descriptor)) } + override fun findExternalAnnotation(fqName: FqName) = null + override fun iterator(): Iterator = annotations().iterator() } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt index 31652de14e3..8c0b5fe3706 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/TypeUtils.kt @@ -20,12 +20,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport -import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.load.java.JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION +import org.jetbrains.kotlin.load.java.JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.substitute -import java.util.LinkedHashSet fun JetType.makeNullable() = TypeUtils.makeNullable(this) fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this) @@ -63,20 +64,12 @@ public fun approximateFlexibleTypes(jetType: JetType, outermost: Boolean = true) ) } -private fun JetType.isMarkedReadOnly() = getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null -private fun JetType.isMarkedNotNull() = getAnnotations().findAnnotation(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null +private fun JetType.isMarkedReadOnly() = hasAnnotationMaybeExternal(JETBRAINS_READONLY_ANNOTATION) +private fun JetType.isMarkedNotNull() = hasAnnotationMaybeExternal(JETBRAINS_NOT_NULL_ANNOTATION) -public fun JetType.getAllReferencedTypes(): Set { - val types = LinkedHashSet() - - fun addType(type: JetType) { - types.add(type) - type.getArguments().forEach { addType(it.getType()) } - } - - addType(this) - return types -} +private fun JetType.hasAnnotationMaybeExternal(fqName: FqName) = with (getAnnotations()) { + findAnnotation(fqName) ?: findExternalAnnotation(fqName) +} != null public enum class TypeNullability { NOT_NULL