diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 3c05298eedb..c420be608ef 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* +import kotlin.platform.platformStatic public class AnnotationChecker(private val additionalCheckers: Iterable) { @@ -54,7 +55,7 @@ public class AnnotationChecker(private val additionalCheckers: Iterable) = targets.any { it in applicableTargets && (useSiteTarget == null || KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it) - }) return + } - if (useSiteTarget != null && actualTargets.useSite.any { + if (check(actualTargets.defaultTargets) || check(actualTargets.canBeSubstituted)) return + + if (useSiteTarget != null && actualTargets.onlyWithUseSiteTarget.any { it in applicableTargets && KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it }) return if (useSiteTarget != null) { trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on( - entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName)) + entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName)) } else { trace.report(Errors.WRONG_ANNOTATION_TARGET.on( - entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target")) + entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target")) } } companion object { - - private val PROPERTY_USE_SITE_TARGETS = listOf( - KotlinTarget.FIELD, KotlinTarget.PROPERTY_GETTER, KotlinTarget.PROPERTY_SETTER, KotlinTarget.VALUE_PARAMETER) - private val VALUE_PARAMETER_USE_SITE_TARGETS = PROPERTY_USE_SITE_TARGETS + KotlinTarget.PROPERTY - private fun applicableTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set { val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET // For descriptor with error type, all targets are considered as possible @@ -120,6 +118,12 @@ public class AnnotationChecker(private val additionalCheckers: Iterable { + val classDescriptor = descriptor.type.constructor.declarationDescriptor as? ClassDescriptor ?: return emptySet() + return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET + } + public fun applicableTargetSet(classDescriptor: ClassDescriptor): Set? { val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null @@ -131,70 +135,134 @@ public class AnnotationChecker(private val additionalCheckers: Iterable { - return getActualTargetList(annotated, descriptor).declarationSite + return getActualTargetList(annotated, descriptor).defaultTargets } private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList { return when (annotated) { - is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: targetList(CLASSIFIER) - is JetProperty -> - if (annotated.isLocal) { - extendedTargetList(PROPERTY_USE_SITE_TARGETS, LOCAL_VARIABLE) - } - else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { - extendedTargetList(PROPERTY_USE_SITE_TARGETS, MEMBER_PROPERTY, PROPERTY) - } - else { - extendedTargetList(PROPERTY_USE_SITE_TARGETS, TOP_LEVEL_PROPERTY, PROPERTY) - } + is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER + is JetProperty -> { + if (annotated.isLocal) + TargetLists.T_LOCAL_VARIABLE + else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) + TargetLists.T_MEMBER_PROPERTY + else + TargetLists.T_TOP_LEVEL_PROPERTY + } is JetParameter -> { - if (annotated.hasValOrVar()) { - extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY) - } - else { - extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, VALUE_PARAMETER) - } + if (annotated.hasValOrVar()) + TargetLists.T_VALUE_PARAMETER_WITH_VAL + else + TargetLists.T_VALUE_PARAMETER_WITHOUT_VAL } - is JetConstructor<*> -> targetList(CONSTRUCTOR) + is JetConstructor<*> -> TargetLists.T_CONSTRUCTOR is JetFunction -> { - val extendedTargets = listOf(KotlinTarget.VALUE_PARAMETER) - if (annotated.isLocal) { - extendedTargetList(extendedTargets, LOCAL_FUNCTION, FUNCTION) - } - else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { - extendedTargetList(extendedTargets, MEMBER_FUNCTION, FUNCTION) - } - else { - extendedTargetList(extendedTargets, TOP_LEVEL_FUNCTION, FUNCTION) - } + if (annotated.isLocal) + TargetLists.T_LOCAL_FUNCTION + else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) + TargetLists.T_MEMBER_FUNCTION + else + TargetLists.T_TOP_LEVEL_FUNCTION } - is JetPropertyAccessor -> if (annotated.isGetter) targetList(PROPERTY_GETTER) else targetList(PROPERTY_SETTER) - is JetPackageDirective -> targetList(PACKAGE) - is JetTypeReference -> extendedTargetList(listOf(VALUE_PARAMETER), TYPE) - is JetFile -> targetList(FILE) - is JetTypeParameter -> targetList(TYPE_PARAMETER) - is JetTypeProjection -> { - if (annotated.projectionKind == JetProjectionKind.STAR) { - targetList(STAR_PROJECTION) - } - else { - targetList(TYPE_PROJECTION) - } - } - is JetClassInitializer -> targetList(INITIALIZER) - else -> targetList() + is JetPropertyAccessor -> if (annotated.isGetter) TargetLists.T_PROPERTY_GETTER else TargetLists.T_PROPERTY_SETTER + is JetPackageDirective -> TargetLists.T_PACKAGE + is JetTypeReference -> TargetLists.T_TYPE_REFERENCE + is JetFile -> TargetLists.T_FILE + is JetTypeParameter -> TargetLists.T_TYPE_PARAMETER + is JetTypeProjection -> + if (annotated.projectionKind == JetProjectionKind.STAR) TargetLists.T_STAR_PROJECTION else TargetLists.T_TYPE_PROJECTION + is JetClassInitializer -> TargetLists.T_INITIALIZER + else -> TargetLists.EMPTY } } - private class TargetList(val declarationSite: List, val useSite: List = emptyList()) + private object TargetLists { + val T_CLASSIFIER = targetList(CLASSIFIER) - private fun targetList(vararg target: KotlinTarget): TargetList { - return TargetList(listOf(*target), emptyList()) + val T_LOCAL_VARIABLE = targetList(LOCAL_VARIABLE) { + onlyWithUseSiteTarget(PROPERTY, FIELD, PROPERTY_GETTER, PROPERTY_SETTER, VALUE_PARAMETER) + } + + val T_MEMBER_PROPERTY = targetList(MEMBER_PROPERTY, PROPERTY) { + canBeSubstituted(PROPERTY_GETTER, PROPERTY_SETTER, FIELD) + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_TOP_LEVEL_PROPERTY = targetList(TOP_LEVEL_PROPERTY, PROPERTY) { + canBeSubstituted(FIELD, PROPERTY_GETTER, PROPERTY_SETTER) + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_PROPERTY_GETTER = targetList(PROPERTY_GETTER) + val T_PROPERTY_SETTER = targetList(PROPERTY_SETTER) + + val T_VALUE_PARAMETER_WITHOUT_VAL = targetList(VALUE_PARAMETER) { + onlyWithUseSiteTarget(PROPERTY, FIELD, PROPERTY_GETTER, PROPERTY_SETTER) + } + + val T_VALUE_PARAMETER_WITH_VAL = targetList(VALUE_PARAMETER, PROPERTY, MEMBER_PROPERTY) { + canBeSubstituted(FIELD, PROPERTY_GETTER, PROPERTY_SETTER) + } + + val T_FILE = targetList(FILE) + val T_PACKAGE = targetList(PACKAGE) + + val T_CONSTRUCTOR = targetList(CONSTRUCTOR) + + val T_LOCAL_FUNCTION = targetList(LOCAL_FUNCTION, FUNCTION) { + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_MEMBER_FUNCTION = targetList(MEMBER_FUNCTION, FUNCTION) { + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_TOP_LEVEL_FUNCTION = targetList(TOP_LEVEL_FUNCTION, FUNCTION) { + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_EXPRESSION = targetList(EXPRESSION) + + val T_TYPE_REFERENCE = targetList(TYPE) { + onlyWithUseSiteTarget(VALUE_PARAMETER) + } + + val T_TYPE_PARAMETER = targetList(TYPE_PARAMETER) + + val T_STAR_PROJECTION = targetList(STAR_PROJECTION) + val T_TYPE_PROJECTION = targetList(TYPE_PROJECTION) + + val T_INITIALIZER = targetList(INITIALIZER) + + + private fun targetList(vararg target: KotlinTarget, otherTargets: TargetListBuilder.() -> Unit = {}): TargetList { + val builder = TargetListBuilder(*target) + builder.otherTargets() + return builder.build() + } + + val EMPTY = targetList() + + private class TargetListBuilder(vararg val defaultTargets: KotlinTarget) { + private var canBeSubstituted: List = listOf() + private var onlyWithUseSiteTarget: List = listOf() + + fun canBeSubstituted(vararg targets: KotlinTarget) { + canBeSubstituted = targets.toList() + } + + fun onlyWithUseSiteTarget(vararg targets: KotlinTarget) { + onlyWithUseSiteTarget = targets.toList() + } + + fun build() = TargetList(defaultTargets.toList(), canBeSubstituted, onlyWithUseSiteTarget) + } } - private fun extendedTargetList(extended: List, vararg target: KotlinTarget): TargetList { - return TargetList(listOf(*target), extended) - } + private class TargetList( + val defaultTargets: List, + val canBeSubstituted: List = emptyList(), + val onlyWithUseSiteTarget: List = emptyList()) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index cba290e776a..6d55381a438 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -20,12 +20,15 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; +import kotlin.KotlinPackage; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; import org.jetbrains.kotlin.descriptors.annotations.Annotations; +import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations; import org.jetbrains.kotlin.descriptors.impl.*; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; @@ -44,9 +47,11 @@ import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.JetTypeChecker; import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; +import org.jetbrains.kotlin.util.AnnotationSplitter; import java.util.*; +import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.lexer.JetTokens.OVERRIDE_KEYWORD; import static org.jetbrains.kotlin.lexer.JetTokens.VARARG_KEYWORD; @@ -328,11 +333,28 @@ public class DescriptorResolver { varargElementType = type; variableType = getVarargParameterType(type); } + + JetModifierList modifierList = valueParameter.getModifierList(); + + Annotations allAnnotations = + annotationResolver.resolveAnnotationsWithoutArguments(scope, valueParameter.getModifierList(), trace); + Annotations valueParameterAnnotations = Annotations.EMPTY; + + if (modifierList != null) { + if (valueParameter.hasValOrVar()) { + AnnotationSplitter annotationSplitter = new AnnotationSplitter(allAnnotations, KotlinPackage.setOf(CONSTRUCTOR_PARAMETER)); + valueParameterAnnotations = annotationSplitter.getAnnotationsForTarget(CONSTRUCTOR_PARAMETER); + } + else { + valueParameterAnnotations = allAnnotations; + } + } + ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl( owner, null, index, - annotationResolver.resolveAnnotationsWithoutArguments(scope, valueParameter.getModifierList(), trace), + valueParameterAnnotations, JetPsiUtil.safeName(valueParameter.getName()), variableType, valueParameter.hasDefaultValue(), @@ -645,13 +667,13 @@ public class DescriptorResolver { private static void initializeWithDefaultGetterSetter(PropertyDescriptorImpl propertyDescriptor) { PropertyGetterDescriptorImpl getter = propertyDescriptor.getGetter(); if (getter == null && !Visibilities.isPrivate(propertyDescriptor.getVisibility())) { - getter = DescriptorFactory.createDefaultGetter(propertyDescriptor); + getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY); getter.initialize(propertyDescriptor.getType()); } PropertySetterDescriptor setter = propertyDescriptor.getSetter(); if (setter == null && propertyDescriptor.isVar()) { - setter = DescriptorFactory.createDefaultSetter(propertyDescriptor); + setter = DescriptorFactory.createDefaultSetter(propertyDescriptor, Annotations.EMPTY); } propertyDescriptor.initialize(getter, setter); } @@ -691,9 +713,24 @@ public class DescriptorResolver { Modality modality = containingDeclaration instanceof ClassDescriptor ? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody)) : Modality.FINAL; + + JetPropertyAccessor propertyGetter = property.getGetter(); + + boolean hasBackingField = modality != Modality.ABSTRACT + && property.hasDelegateExpressionOrInitializer() + && (propertyGetter == null || !propertyGetter.hasBody()); + + Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace); + AnnotationSplitter annotationSplitter = AnnotationSplitter.create(allAnnotations, + /*parameter =*/ false, /*hasBackingField =*/ hasBackingField, /*isMutable =*/ isVar); + + Annotations propertyAnnotations = new CompositeAnnotations(KotlinPackage.listOf( + annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD), + annotationSplitter.getOtherAnnotations())); + PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create( containingDeclaration, - annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace), + propertyAnnotations, modality, visibility, isVar, @@ -742,8 +779,10 @@ public class DescriptorResolver { propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration), receiverDescriptor); - PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace); - PropertySetterDescriptor setter = resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace); + PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor( + scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace); + PropertySetterDescriptor setter = resolvePropertySetterDescriptor( + scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace); propertyDescriptor.initialize(getter, setter); @@ -923,13 +962,15 @@ public class DescriptorResolver { @NotNull LexicalScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor, + @NotNull AnnotationSplitter annotationSplitter, BindingTrace trace ) { JetPropertyAccessor setter = property.getSetter(); PropertySetterDescriptorImpl setterDescriptor = null; if (setter != null) { - Annotations annotations = - annotationResolver.resolveAnnotationsWithoutArguments(scope, setter.getModifierList(), trace); + Annotations annotations = new CompositeAnnotations(KotlinPackage.listOf( + annotationSplitter.getAnnotationsForTarget(PROPERTY_SETTER), + annotationResolver.resolveAnnotationsWithoutArguments(scope, setter.getModifierList(), trace))); JetParameter parameter = setter.getParameter(); setterDescriptor = new PropertySetterDescriptorImpl(propertyDescriptor, annotations, @@ -973,7 +1014,8 @@ public class DescriptorResolver { trace.record(BindingContext.PROPERTY_ACCESSOR, setter, setterDescriptor); } else if (property.isVar()) { - setterDescriptor = DescriptorFactory.createSetter(propertyDescriptor, !property.hasDelegate()); + Annotations setterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_SETTER); + setterDescriptor = DescriptorFactory.createSetter(propertyDescriptor, setterAnnotations, !property.hasDelegate()); } if (!property.isVar()) { @@ -990,13 +1032,16 @@ public class DescriptorResolver { @NotNull LexicalScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor, + @NotNull AnnotationSplitter annotationSplitter, BindingTrace trace ) { PropertyGetterDescriptorImpl getterDescriptor; JetPropertyAccessor getter = property.getGetter(); if (getter != null) { - Annotations annotations = - annotationResolver.resolveAnnotationsWithoutArguments(scope, getter.getModifierList(), trace); + Annotations getterAnnotations = new CompositeAnnotations(KotlinPackage.listOf( + annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER), + annotationSplitter.getOtherAnnotations(), + annotationResolver.resolveAnnotationsWithoutArguments(scope, getter.getModifierList(), trace))); JetType outType = propertyDescriptor.getType(); JetType returnType = outType; @@ -1008,7 +1053,7 @@ public class DescriptorResolver { } } - getterDescriptor = new PropertyGetterDescriptorImpl(propertyDescriptor, annotations, + getterDescriptor = new PropertyGetterDescriptorImpl(propertyDescriptor, getterAnnotations, resolveModalityFromModifiers(getter, propertyDescriptor.getModality()), resolveVisibilityFromModifiers(getter, propertyDescriptor.getVisibility()), getter.hasBody(), false, @@ -1017,7 +1062,8 @@ public class DescriptorResolver { trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); } else { - getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, !property.hasDelegate()); + Annotations getterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER); + getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !property.hasDelegate()); getterDescriptor.initialize(propertyDescriptor.getType()); } return getterDescriptor; @@ -1041,9 +1087,17 @@ public class DescriptorResolver { } } + Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, parameter.getModifierList(), trace); + AnnotationSplitter annotationSplitter = AnnotationSplitter.create(allAnnotations, + /*parameter =*/ true, /*hasBackingField =*/ true, /*isMutable =*/ isMutable); + + Annotations propertyAnnotations = new CompositeAnnotations( + annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD), + annotationSplitter.getOtherAnnotations()); + PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create( classDescriptor, - valueParameter.getAnnotations(), + propertyAnnotations, resolveModalityFromModifiers(parameter, Modality.FINAL), resolveVisibilityFromModifiers(parameter, getDefaultVisibility(parameter, classDescriptor)), isMutable, @@ -1054,9 +1108,13 @@ public class DescriptorResolver { propertyDescriptor.setType(type, Collections.emptyList(), getDispatchReceiverParameterIfNeeded(classDescriptor), (ReceiverParameterDescriptor) null); - PropertyGetterDescriptorImpl getter = DescriptorFactory.createDefaultGetter(propertyDescriptor); + Annotations setterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_SETTER); + Annotations getterAnnotations = new CompositeAnnotations(KotlinPackage.listOf( + annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER))); + + PropertyGetterDescriptorImpl getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, getterAnnotations); PropertySetterDescriptor setter = - propertyDescriptor.isVar() ? DescriptorFactory.createDefaultSetter(propertyDescriptor) : null; + propertyDescriptor.isVar() ? DescriptorFactory.createDefaultSetter(propertyDescriptor, setterAnnotations) : null; propertyDescriptor.initialize(getter, setter); getter.initialize(propertyDescriptor.getType()); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt index e7ba78b9ff9..2b74874f47c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/dynamicCalls.kt @@ -103,9 +103,9 @@ object DynamicCallableDescriptors { null: JetType? ) - val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor) + val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY) getter.initialize(propertyDescriptor.getType()) - val setter = DescriptorFactory.createDefaultSetter(propertyDescriptor) + val setter = DescriptorFactory.createDefaultSetter(propertyDescriptor, Annotations.EMPTY) propertyDescriptor.initialize(getter, setter) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/AnnotationSplitter.kt b/compiler/frontend/src/org/jetbrains/kotlin/util/AnnotationSplitter.kt new file mode 100644 index 00000000000..c174a34d1dc --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/AnnotationSplitter.kt @@ -0,0 +1,85 @@ +/* + * 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.util + +import org.jetbrains.kotlin.descriptors.annotations.* +import org.jetbrains.kotlin.resolve.AnnotationChecker +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* +import kotlin.platform.platformStatic + +public class AnnotationSplitter(original: Annotations, applicableTargets: Set) { + private val annotations: Map> + public val otherAnnotations: Annotations + + init { + val map = hashMapOf>() + val other = arrayListOf() + + outer@ for (annotationWithTarget in original.getAllAnnotations()) { + val useSiteTarget = annotationWithTarget.target + if (useSiteTarget != null) { + if (useSiteTarget in applicableTargets) + map.getOrPut(useSiteTarget, { arrayListOf() }).add(annotationWithTarget) + else + other.add(annotationWithTarget) + + continue@outer + } + + for (target in TARGET_PRIORITIES) { + if (target !in applicableTargets) continue + + val declarationSiteTargetForCurrentTarget = KotlinTarget.USE_SITE_MAPPING[target] ?: continue + val applicableTargetsForAnnotation = AnnotationChecker.applicableTargetSet(annotationWithTarget.annotation) + val applicable = applicableTargetsForAnnotation.any { it == declarationSiteTargetForCurrentTarget } + + if (applicable) { + map.getOrPut(target, { arrayListOf() }).add(annotationWithTarget) + continue@outer + } + } + + other.add(annotationWithTarget) + } + annotations = map + otherAnnotations = AnnotationsImpl.create(other) + } + + public fun getAnnotationsForTarget(target: AnnotationUseSiteTarget): Annotations { + val annotations = annotations[target] ?: return Annotations.EMPTY + return AnnotationsImpl.create(annotations) + } + + public fun getAnnotationsForTargets(vararg targets: AnnotationUseSiteTarget): Annotations { + return CompositeAnnotations(targets.map { getAnnotationsForTarget(it) }) + } + + public companion object { + private val TARGET_PRIORITIES = setOf(CONSTRUCTOR_PARAMETER, FIELD, PROPERTY, PROPERTY_SETTER, PROPERTY_GETTER) + + platformStatic + public fun create(original: Annotations, parameter: Boolean, hasBackingField: Boolean, isMutable: Boolean): AnnotationSplitter { + return AnnotationSplitter(original, with(hashSetOf(PROPERTY, PROPERTY_GETTER)) { + if (parameter) add(CONSTRUCTOR_PARAMETER) + if (hasBackingField) add(FIELD) + if (isMutable) add(PROPERTY_SETTER) + this + }) + } + } + +} \ No newline at end of file diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index eef27f819bf..bc8708ad862 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -107,7 +107,7 @@ public class LazyJavaClassMemberScope( ) // default getter is necessary because there is no real field in annotation - val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor) + val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY) propertyDescriptor.initialize(getter, null) val returnType = computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method)) diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java index 9b46d4884bf..51138daba43 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java @@ -44,14 +44,21 @@ public class DescriptorFactory { } @NotNull - public static PropertySetterDescriptorImpl createDefaultSetter(@NotNull PropertyDescriptor propertyDescriptor) { - return createSetter(propertyDescriptor, true); + public static PropertySetterDescriptorImpl createDefaultSetter( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull Annotations annotations + ) { + return createSetter(propertyDescriptor, annotations, true); } @NotNull - public static PropertySetterDescriptorImpl createSetter(@NotNull PropertyDescriptor propertyDescriptor, boolean isDefault) { + public static PropertySetterDescriptorImpl createSetter( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull Annotations annotations, + boolean isDefault + ) { PropertySetterDescriptorImpl setterDescriptor = - new PropertySetterDescriptorImpl(propertyDescriptor, Annotations.EMPTY, propertyDescriptor.getModality(), + new PropertySetterDescriptorImpl(propertyDescriptor, annotations, propertyDescriptor.getModality(), propertyDescriptor.getVisibility(), !isDefault, isDefault, CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE); setterDescriptor.initializeDefault(); @@ -59,13 +66,19 @@ public class DescriptorFactory { } @NotNull - public static PropertyGetterDescriptorImpl createDefaultGetter(@NotNull PropertyDescriptor propertyDescriptor) { - return createGetter(propertyDescriptor, true); + public static PropertyGetterDescriptorImpl createDefaultGetter( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull Annotations annotations + ) { + return createGetter(propertyDescriptor, annotations, true); } @NotNull - public static PropertyGetterDescriptorImpl createGetter(@NotNull PropertyDescriptor propertyDescriptor, boolean isDefault) { - return new PropertyGetterDescriptorImpl(propertyDescriptor, Annotations.EMPTY, propertyDescriptor.getModality(), + public static PropertyGetterDescriptorImpl createGetter( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull Annotations annotations, + boolean isDefault) { + return new PropertyGetterDescriptorImpl(propertyDescriptor, annotations, propertyDescriptor.getModality(), propertyDescriptor.getVisibility(), !isDefault, isDefault, CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE); } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt index fed8a825edf..378fc3c32a0 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MemberDeserializer.kt @@ -88,7 +88,7 @@ public class MemberDeserializer(private val c: DeserializationContext) { ) } else { - DescriptorFactory.createDefaultGetter(property) + DescriptorFactory.createDefaultGetter(property, Annotations.EMPTY) } getter.initialize(property.getReturnType()) getter @@ -116,7 +116,7 @@ public class MemberDeserializer(private val c: DeserializationContext) { setter } else { - DescriptorFactory.createDefaultSetter(property) + DescriptorFactory.createDefaultSetter(property, Annotations.EMPTY) } } else { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index ce902707872..7a27e7db248 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -17,6 +17,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.types.TypeUtils import java.lang.reflect.Field @@ -50,7 +51,7 @@ interface KPropertyImpl : KProperty, KCallableImpl { override val descriptor: PropertyGetterDescriptor by ReflectProperties.lazySoft { // TODO: default getter created this way won't have any source information - property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor) + property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor, Annotations.EMPTY) } override val caller: FunctionCaller<*> by ReflectProperties.lazySoft { @@ -72,7 +73,7 @@ interface KMutablePropertyImpl : KMutableProperty, KPropertyImpl { override val descriptor: PropertySetterDescriptor by ReflectProperties.lazySoft { // TODO: default setter created this way won't have any source information - property.descriptor.setter ?: DescriptorFactory.createDefaultSetter(property.descriptor) + property.descriptor.setter ?: DescriptorFactory.createDefaultSetter(property.descriptor, Annotations.EMPTY) } override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {