Use target priorities to split annotations to different descriptors

This commit is contained in:
Yan Zhulanow
2015-08-07 03:26:19 +03:00
parent 9838f9c942
commit 3624c4e5dc
8 changed files with 318 additions and 93 deletions
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.* import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
import kotlin.platform.platformStatic
public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) { public class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnotationChecker>) {
@@ -54,7 +55,7 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
} }
public fun checkExpression(expression: JetExpression, trace: BindingTrace) { public fun checkExpression(expression: JetExpression, trace: BindingTrace) {
checkEntries(expression.getAnnotationEntries(), targetList(KotlinTarget.EXPRESSION), trace) checkEntries(expression.getAnnotationEntries(), TargetLists.T_EXPRESSION, trace)
if (expression is JetFunctionLiteralExpression) { if (expression is JetFunctionLiteralExpression) {
for (parameter in expression.valueParameters) { for (parameter in expression.valueParameters) {
parameter.typeReference?.let { check(it, trace) } parameter.typeReference?.let { check(it, trace) }
@@ -81,37 +82,34 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
existingTargetsForAnnotation.add(useSiteTarget) existingTargetsForAnnotation.add(useSiteTarget)
} }
additionalCheckers.forEach { it.checkEntries(entries, actualTargets.declarationSite, trace) } additionalCheckers.forEach { it.checkEntries(entries, actualTargets.defaultTargets, trace) }
} }
private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: TargetList, trace: BindingTrace) { private fun checkAnnotationEntry(entry: JetAnnotationEntry, actualTargets: TargetList, trace: BindingTrace) {
val applicableTargets = applicableTargetSet(entry, trace) val applicableTargets = applicableTargetSet(entry, trace)
val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget() val useSiteTarget = entry.useSiteTarget?.getAnnotationUseSiteTarget()
if (actualTargets.declarationSite.any { fun check(targets: List<KotlinTarget>) = targets.any {
it in applicableTargets && (useSiteTarget == null || KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it) 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 it in applicableTargets && KotlinTarget.USE_SITE_MAPPING[useSiteTarget] == it
}) return }) return
if (useSiteTarget != null) { if (useSiteTarget != null) {
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on( 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 { else {
trace.report(Errors.WRONG_ANNOTATION_TARGET.on( trace.report(Errors.WRONG_ANNOTATION_TARGET.on(
entry, actualTargets.declarationSite.firstOrNull()?.description ?: "unidentified target")) entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target"))
} }
} }
companion object { 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<KotlinTarget> { private fun applicableTargetSet(entry: JetAnnotationEntry, trace: BindingTrace): Set<KotlinTarget> {
val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET val descriptor = trace.get(BindingContext.ANNOTATION, entry) ?: return KotlinTarget.DEFAULT_TARGET_SET
// For descriptor with error type, all targets are considered as possible // For descriptor with error type, all targets are considered as possible
@@ -120,6 +118,12 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
} }
platformStatic
public fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> {
val classDescriptor = descriptor.type.constructor.declarationDescriptor as? ClassDescriptor ?: return emptySet()
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
}
public fun applicableTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? { public fun applicableTargetSet(classDescriptor: ClassDescriptor): Set<KotlinTarget>? {
val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target) val targetEntryDescriptor = classDescriptor.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.target)
?: return null ?: return null
@@ -131,70 +135,134 @@ public class AnnotationChecker(private val additionalCheckers: Iterable<Addition
} }
public fun getDeclarationSiteActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> { public fun getDeclarationSiteActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): List<KotlinTarget> {
return getActualTargetList(annotated, descriptor).declarationSite return getActualTargetList(annotated, descriptor).defaultTargets
} }
private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList { private fun getActualTargetList(annotated: JetElement, descriptor: ClassDescriptor?): TargetList {
return when (annotated) { return when (annotated) {
is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: targetList(CLASSIFIER) is JetClassOrObject -> descriptor?.let { TargetList(KotlinTarget.classActualTargets(it)) } ?: TargetLists.T_CLASSIFIER
is JetProperty -> is JetProperty -> {
if (annotated.isLocal) { if (annotated.isLocal)
extendedTargetList(PROPERTY_USE_SITE_TARGETS, LOCAL_VARIABLE) TargetLists.T_LOCAL_VARIABLE
} else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody)
else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { TargetLists.T_MEMBER_PROPERTY
extendedTargetList(PROPERTY_USE_SITE_TARGETS, MEMBER_PROPERTY, PROPERTY) else
} TargetLists.T_TOP_LEVEL_PROPERTY
else { }
extendedTargetList(PROPERTY_USE_SITE_TARGETS, TOP_LEVEL_PROPERTY, PROPERTY)
}
is JetParameter -> { is JetParameter -> {
if (annotated.hasValOrVar()) { if (annotated.hasValOrVar())
extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, PROPERTY_PARAMETER, MEMBER_PROPERTY, PROPERTY) TargetLists.T_VALUE_PARAMETER_WITH_VAL
} else
else { TargetLists.T_VALUE_PARAMETER_WITHOUT_VAL
extendedTargetList(VALUE_PARAMETER_USE_SITE_TARGETS, VALUE_PARAMETER)
}
} }
is JetConstructor<*> -> targetList(CONSTRUCTOR) is JetConstructor<*> -> TargetLists.T_CONSTRUCTOR
is JetFunction -> { is JetFunction -> {
val extendedTargets = listOf(KotlinTarget.VALUE_PARAMETER) if (annotated.isLocal)
if (annotated.isLocal) { TargetLists.T_LOCAL_FUNCTION
extendedTargetList(extendedTargets, LOCAL_FUNCTION, FUNCTION) else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody)
} TargetLists.T_MEMBER_FUNCTION
else if (annotated.parent is JetClassOrObject || annotated.parent is JetClassBody) { else
extendedTargetList(extendedTargets, MEMBER_FUNCTION, FUNCTION) TargetLists.T_TOP_LEVEL_FUNCTION
}
else {
extendedTargetList(extendedTargets, TOP_LEVEL_FUNCTION, FUNCTION)
}
} }
is JetPropertyAccessor -> if (annotated.isGetter) targetList(PROPERTY_GETTER) else targetList(PROPERTY_SETTER) is JetPropertyAccessor -> if (annotated.isGetter) TargetLists.T_PROPERTY_GETTER else TargetLists.T_PROPERTY_SETTER
is JetPackageDirective -> targetList(PACKAGE) is JetPackageDirective -> TargetLists.T_PACKAGE
is JetTypeReference -> extendedTargetList(listOf(VALUE_PARAMETER), TYPE) is JetTypeReference -> TargetLists.T_TYPE_REFERENCE
is JetFile -> targetList(FILE) is JetFile -> TargetLists.T_FILE
is JetTypeParameter -> targetList(TYPE_PARAMETER) is JetTypeParameter -> TargetLists.T_TYPE_PARAMETER
is JetTypeProjection -> { is JetTypeProjection ->
if (annotated.projectionKind == JetProjectionKind.STAR) { if (annotated.projectionKind == JetProjectionKind.STAR) TargetLists.T_STAR_PROJECTION else TargetLists.T_TYPE_PROJECTION
targetList(STAR_PROJECTION) is JetClassInitializer -> TargetLists.T_INITIALIZER
} else -> TargetLists.EMPTY
else {
targetList(TYPE_PROJECTION)
}
}
is JetClassInitializer -> targetList(INITIALIZER)
else -> targetList()
} }
} }
private class TargetList(val declarationSite: List<KotlinTarget>, val useSite: List<KotlinTarget> = emptyList()) private object TargetLists {
val T_CLASSIFIER = targetList(CLASSIFIER)
private fun targetList(vararg target: KotlinTarget): TargetList { val T_LOCAL_VARIABLE = targetList(LOCAL_VARIABLE) {
return TargetList(listOf(*target), emptyList()) 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<KotlinTarget> = listOf()
private var onlyWithUseSiteTarget: List<KotlinTarget> = 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<KotlinTarget>, vararg target: KotlinTarget): TargetList { private class TargetList(
return TargetList(listOf(*target), extended) val defaultTargets: List<KotlinTarget>,
} val canBeSubstituted: List<KotlinTarget> = emptyList(),
val onlyWithUseSiteTarget: List<KotlinTarget> = emptyList())
} }
} }
@@ -20,12 +20,15 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import kotlin.KotlinPackage;
import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*; 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.Annotations;
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations;
import org.jetbrains.kotlin.descriptors.impl.*; import org.jetbrains.kotlin.descriptors.impl.*;
import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation; 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.*;
import org.jetbrains.kotlin.types.checker.JetTypeChecker; import org.jetbrains.kotlin.types.checker.JetTypeChecker;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import org.jetbrains.kotlin.util.AnnotationSplitter;
import java.util.*; import java.util.*;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.lexer.JetTokens.OVERRIDE_KEYWORD; import static org.jetbrains.kotlin.lexer.JetTokens.OVERRIDE_KEYWORD;
import static org.jetbrains.kotlin.lexer.JetTokens.VARARG_KEYWORD; import static org.jetbrains.kotlin.lexer.JetTokens.VARARG_KEYWORD;
@@ -328,11 +333,28 @@ public class DescriptorResolver {
varargElementType = type; varargElementType = type;
variableType = getVarargParameterType(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( ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
owner, owner,
null, null,
index, index,
annotationResolver.resolveAnnotationsWithoutArguments(scope, valueParameter.getModifierList(), trace), valueParameterAnnotations,
JetPsiUtil.safeName(valueParameter.getName()), JetPsiUtil.safeName(valueParameter.getName()),
variableType, variableType,
valueParameter.hasDefaultValue(), valueParameter.hasDefaultValue(),
@@ -645,13 +667,13 @@ public class DescriptorResolver {
private static void initializeWithDefaultGetterSetter(PropertyDescriptorImpl propertyDescriptor) { private static void initializeWithDefaultGetterSetter(PropertyDescriptorImpl propertyDescriptor) {
PropertyGetterDescriptorImpl getter = propertyDescriptor.getGetter(); PropertyGetterDescriptorImpl getter = propertyDescriptor.getGetter();
if (getter == null && !Visibilities.isPrivate(propertyDescriptor.getVisibility())) { if (getter == null && !Visibilities.isPrivate(propertyDescriptor.getVisibility())) {
getter = DescriptorFactory.createDefaultGetter(propertyDescriptor); getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY);
getter.initialize(propertyDescriptor.getType()); getter.initialize(propertyDescriptor.getType());
} }
PropertySetterDescriptor setter = propertyDescriptor.getSetter(); PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (setter == null && propertyDescriptor.isVar()) { if (setter == null && propertyDescriptor.isVar()) {
setter = DescriptorFactory.createDefaultSetter(propertyDescriptor); setter = DescriptorFactory.createDefaultSetter(propertyDescriptor, Annotations.EMPTY);
} }
propertyDescriptor.initialize(getter, setter); propertyDescriptor.initialize(getter, setter);
} }
@@ -691,9 +713,24 @@ public class DescriptorResolver {
Modality modality = containingDeclaration instanceof ClassDescriptor Modality modality = containingDeclaration instanceof ClassDescriptor
? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody)) ? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody))
: Modality.FINAL; : 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( PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
containingDeclaration, containingDeclaration,
annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace), propertyAnnotations,
modality, modality,
visibility, visibility,
isVar, isVar,
@@ -742,8 +779,10 @@ public class DescriptorResolver {
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration), propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
receiverDescriptor); receiverDescriptor);
PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace); PropertyGetterDescriptorImpl getter = resolvePropertyGetterDescriptor(
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace); scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
scopeWithTypeParameters, property, propertyDescriptor, annotationSplitter, trace);
propertyDescriptor.initialize(getter, setter); propertyDescriptor.initialize(getter, setter);
@@ -923,13 +962,15 @@ public class DescriptorResolver {
@NotNull LexicalScope scope, @NotNull LexicalScope scope,
@NotNull JetProperty property, @NotNull JetProperty property,
@NotNull PropertyDescriptor propertyDescriptor, @NotNull PropertyDescriptor propertyDescriptor,
@NotNull AnnotationSplitter annotationSplitter,
BindingTrace trace BindingTrace trace
) { ) {
JetPropertyAccessor setter = property.getSetter(); JetPropertyAccessor setter = property.getSetter();
PropertySetterDescriptorImpl setterDescriptor = null; PropertySetterDescriptorImpl setterDescriptor = null;
if (setter != null) { if (setter != null) {
Annotations annotations = Annotations annotations = new CompositeAnnotations(KotlinPackage.listOf(
annotationResolver.resolveAnnotationsWithoutArguments(scope, setter.getModifierList(), trace); annotationSplitter.getAnnotationsForTarget(PROPERTY_SETTER),
annotationResolver.resolveAnnotationsWithoutArguments(scope, setter.getModifierList(), trace)));
JetParameter parameter = setter.getParameter(); JetParameter parameter = setter.getParameter();
setterDescriptor = new PropertySetterDescriptorImpl(propertyDescriptor, annotations, setterDescriptor = new PropertySetterDescriptorImpl(propertyDescriptor, annotations,
@@ -973,7 +1014,8 @@ public class DescriptorResolver {
trace.record(BindingContext.PROPERTY_ACCESSOR, setter, setterDescriptor); trace.record(BindingContext.PROPERTY_ACCESSOR, setter, setterDescriptor);
} }
else if (property.isVar()) { 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()) { if (!property.isVar()) {
@@ -990,13 +1032,16 @@ public class DescriptorResolver {
@NotNull LexicalScope scope, @NotNull LexicalScope scope,
@NotNull JetProperty property, @NotNull JetProperty property,
@NotNull PropertyDescriptor propertyDescriptor, @NotNull PropertyDescriptor propertyDescriptor,
@NotNull AnnotationSplitter annotationSplitter,
BindingTrace trace BindingTrace trace
) { ) {
PropertyGetterDescriptorImpl getterDescriptor; PropertyGetterDescriptorImpl getterDescriptor;
JetPropertyAccessor getter = property.getGetter(); JetPropertyAccessor getter = property.getGetter();
if (getter != null) { if (getter != null) {
Annotations annotations = Annotations getterAnnotations = new CompositeAnnotations(KotlinPackage.listOf(
annotationResolver.resolveAnnotationsWithoutArguments(scope, getter.getModifierList(), trace); annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER),
annotationSplitter.getOtherAnnotations(),
annotationResolver.resolveAnnotationsWithoutArguments(scope, getter.getModifierList(), trace)));
JetType outType = propertyDescriptor.getType(); JetType outType = propertyDescriptor.getType();
JetType returnType = outType; JetType returnType = outType;
@@ -1008,7 +1053,7 @@ public class DescriptorResolver {
} }
} }
getterDescriptor = new PropertyGetterDescriptorImpl(propertyDescriptor, annotations, getterDescriptor = new PropertyGetterDescriptorImpl(propertyDescriptor, getterAnnotations,
resolveModalityFromModifiers(getter, propertyDescriptor.getModality()), resolveModalityFromModifiers(getter, propertyDescriptor.getModality()),
resolveVisibilityFromModifiers(getter, propertyDescriptor.getVisibility()), resolveVisibilityFromModifiers(getter, propertyDescriptor.getVisibility()),
getter.hasBody(), false, getter.hasBody(), false,
@@ -1017,7 +1062,8 @@ public class DescriptorResolver {
trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor);
} }
else { else {
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, !property.hasDelegate()); Annotations getterAnnotations = annotationSplitter.getAnnotationsForTarget(PROPERTY_GETTER);
getterDescriptor = DescriptorFactory.createGetter(propertyDescriptor, getterAnnotations, !property.hasDelegate());
getterDescriptor.initialize(propertyDescriptor.getType()); getterDescriptor.initialize(propertyDescriptor.getType());
} }
return getterDescriptor; 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( PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
classDescriptor, classDescriptor,
valueParameter.getAnnotations(), propertyAnnotations,
resolveModalityFromModifiers(parameter, Modality.FINAL), resolveModalityFromModifiers(parameter, Modality.FINAL),
resolveVisibilityFromModifiers(parameter, getDefaultVisibility(parameter, classDescriptor)), resolveVisibilityFromModifiers(parameter, getDefaultVisibility(parameter, classDescriptor)),
isMutable, isMutable,
@@ -1054,9 +1108,13 @@ public class DescriptorResolver {
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(),
getDispatchReceiverParameterIfNeeded(classDescriptor), (ReceiverParameterDescriptor) null); 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 = PropertySetterDescriptor setter =
propertyDescriptor.isVar() ? DescriptorFactory.createDefaultSetter(propertyDescriptor) : null; propertyDescriptor.isVar() ? DescriptorFactory.createDefaultSetter(propertyDescriptor, setterAnnotations) : null;
propertyDescriptor.initialize(getter, setter); propertyDescriptor.initialize(getter, setter);
getter.initialize(propertyDescriptor.getType()); getter.initialize(propertyDescriptor.getType());
@@ -103,9 +103,9 @@ object DynamicCallableDescriptors {
null: JetType? null: JetType?
) )
val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor) val getter = DescriptorFactory.createDefaultGetter(propertyDescriptor, Annotations.EMPTY)
getter.initialize(propertyDescriptor.getType()) getter.initialize(propertyDescriptor.getType())
val setter = DescriptorFactory.createDefaultSetter(propertyDescriptor) val setter = DescriptorFactory.createDefaultSetter(propertyDescriptor, Annotations.EMPTY)
propertyDescriptor.initialize(getter, setter) propertyDescriptor.initialize(getter, setter)
@@ -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<AnnotationUseSiteTarget>) {
private val annotations: Map<AnnotationUseSiteTarget, List<AnnotationWithTarget>>
public val otherAnnotations: Annotations
init {
val map = hashMapOf<AnnotationUseSiteTarget, MutableList<AnnotationWithTarget>>()
val other = arrayListOf<AnnotationWithTarget>()
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
})
}
}
}
@@ -107,7 +107,7 @@ public class LazyJavaClassMemberScope(
) )
// default getter is necessary because there is no real field in annotation // 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) propertyDescriptor.initialize(getter, null)
val returnType = computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method)) val returnType = computeMethodReturnType(method, annotations, c.child(propertyDescriptor, method))
@@ -44,14 +44,21 @@ public class DescriptorFactory {
} }
@NotNull @NotNull
public static PropertySetterDescriptorImpl createDefaultSetter(@NotNull PropertyDescriptor propertyDescriptor) { public static PropertySetterDescriptorImpl createDefaultSetter(
return createSetter(propertyDescriptor, true); @NotNull PropertyDescriptor propertyDescriptor,
@NotNull Annotations annotations
) {
return createSetter(propertyDescriptor, annotations, true);
} }
@NotNull @NotNull
public static PropertySetterDescriptorImpl createSetter(@NotNull PropertyDescriptor propertyDescriptor, boolean isDefault) { public static PropertySetterDescriptorImpl createSetter(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull Annotations annotations,
boolean isDefault
) {
PropertySetterDescriptorImpl setterDescriptor = PropertySetterDescriptorImpl setterDescriptor =
new PropertySetterDescriptorImpl(propertyDescriptor, Annotations.EMPTY, propertyDescriptor.getModality(), new PropertySetterDescriptorImpl(propertyDescriptor, annotations, propertyDescriptor.getModality(),
propertyDescriptor.getVisibility(), !isDefault, isDefault, propertyDescriptor.getVisibility(), !isDefault, isDefault,
CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE); CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE);
setterDescriptor.initializeDefault(); setterDescriptor.initializeDefault();
@@ -59,13 +66,19 @@ public class DescriptorFactory {
} }
@NotNull @NotNull
public static PropertyGetterDescriptorImpl createDefaultGetter(@NotNull PropertyDescriptor propertyDescriptor) { public static PropertyGetterDescriptorImpl createDefaultGetter(
return createGetter(propertyDescriptor, true); @NotNull PropertyDescriptor propertyDescriptor,
@NotNull Annotations annotations
) {
return createGetter(propertyDescriptor, annotations, true);
} }
@NotNull @NotNull
public static PropertyGetterDescriptorImpl createGetter(@NotNull PropertyDescriptor propertyDescriptor, boolean isDefault) { public static PropertyGetterDescriptorImpl createGetter(
return new PropertyGetterDescriptorImpl(propertyDescriptor, Annotations.EMPTY, propertyDescriptor.getModality(), @NotNull PropertyDescriptor propertyDescriptor,
@NotNull Annotations annotations,
boolean isDefault) {
return new PropertyGetterDescriptorImpl(propertyDescriptor, annotations, propertyDescriptor.getModality(),
propertyDescriptor.getVisibility(), !isDefault, isDefault, propertyDescriptor.getVisibility(), !isDefault, isDefault,
CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE); CallableMemberDescriptor.Kind.DECLARATION, null, SourceElement.NO_SOURCE);
} }
@@ -88,7 +88,7 @@ public class MemberDeserializer(private val c: DeserializationContext) {
) )
} }
else { else {
DescriptorFactory.createDefaultGetter(property) DescriptorFactory.createDefaultGetter(property, Annotations.EMPTY)
} }
getter.initialize(property.getReturnType()) getter.initialize(property.getReturnType())
getter getter
@@ -116,7 +116,7 @@ public class MemberDeserializer(private val c: DeserializationContext) {
setter setter
} }
else { else {
DescriptorFactory.createDefaultSetter(property) DescriptorFactory.createDefaultSetter(property, Annotations.EMPTY)
} }
} }
else { else {
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import java.lang.reflect.Field import java.lang.reflect.Field
@@ -50,7 +51,7 @@ interface KPropertyImpl<out R> : KProperty<R>, KCallableImpl<R> {
override val descriptor: PropertyGetterDescriptor by ReflectProperties.lazySoft { override val descriptor: PropertyGetterDescriptor by ReflectProperties.lazySoft {
// TODO: default getter created this way won't have any source information // 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 { override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {
@@ -72,7 +73,7 @@ interface KMutablePropertyImpl<R> : KMutableProperty<R>, KPropertyImpl<R> {
override val descriptor: PropertySetterDescriptor by ReflectProperties.lazySoft { override val descriptor: PropertySetterDescriptor by ReflectProperties.lazySoft {
// TODO: default setter created this way won't have any source information // 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 { override val caller: FunctionCaller<*> by ReflectProperties.lazySoft {