delegate use-site targeted annotations: parser, front-end, codegen with some tests #KT-10502 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-01-14 16:28:29 +03:00
parent 474076a550
commit b78d481bb1
29 changed files with 366 additions and 51 deletions
@@ -130,16 +130,18 @@ public class PropertyCodegen {
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) { private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
boolean hasBackingField = hasBackingField(declaration, descriptor); boolean hasBackingField = hasBackingField(declaration, descriptor);
boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate();
AnnotationSplitter annotationSplitter = AnnotationSplitter annotationSplitter =
AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS, AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS,
descriptor.getAnnotations(), descriptor.getAnnotations(),
AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField)); AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField, hasDelegate));
Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD); Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD);
Annotations delegateAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD);
Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY); Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY);
generateBackingField(declaration, descriptor, fieldAnnotations); generateBackingField(declaration, descriptor, fieldAnnotations, delegateAnnotations);
generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations); generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations);
} }
@@ -228,17 +230,18 @@ public class PropertyCodegen {
private boolean generateBackingField( private boolean generateBackingField(
@NotNull KtNamedDeclaration p, @NotNull KtNamedDeclaration p,
@NotNull PropertyDescriptor descriptor, @NotNull PropertyDescriptor descriptor,
@NotNull Annotations annotations @NotNull Annotations backingFieldAnnotations,
@NotNull Annotations delegateAnnotations
) { ) {
if (isJvmInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.DEFAULT_IMPLS) { if (isJvmInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.DEFAULT_IMPLS) {
return false; return false;
} }
if (p instanceof KtProperty && ((KtProperty) p).hasDelegate()) { if (p instanceof KtProperty && ((KtProperty) p).hasDelegate()) {
generatePropertyDelegateAccess((KtProperty) p, descriptor, annotations); generatePropertyDelegateAccess((KtProperty) p, descriptor, delegateAnnotations);
} }
else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) { else if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
generateBackingFieldAccess(p, descriptor, annotations); generateBackingFieldAccess(p, descriptor, backingFieldAnnotations);
} }
else { else {
return false; return false;
@@ -327,7 +330,8 @@ public class PropertyCodegen {
typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue); typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue);
Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations); Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations);
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(fieldAnnotated, type, AnnotationUseSiteTarget.FIELD); AnnotationCodegen.forField(fv, typeMapper).genAnnotations(
fieldAnnotated, type, isDelegate ? AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD : AnnotationUseSiteTarget.FIELD);
} }
private void generatePropertyDelegateAccess(KtProperty p, PropertyDescriptor propertyDescriptor, Annotations annotations) { private void generatePropertyDelegateAccess(KtProperty p, PropertyDescriptor propertyDescriptor, Annotations annotations) {
@@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.resolve.AnnotationChecker
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
@@ -54,22 +56,24 @@ class AnnotationSplitter(
} }
@JvmStatic fun getTargetSet(parameter: Boolean, context: BindingContext, wrapper: PropertyWrapper): Set<AnnotationUseSiteTarget> { @JvmStatic fun getTargetSet(parameter: Boolean, context: BindingContext, wrapper: PropertyWrapper): Set<AnnotationUseSiteTarget> {
val property = wrapper.property val descriptor = wrapper.descriptor
assert(property != null) assert(descriptor != null)
val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, property] ?: false val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false
return getTargetSet(parameter, property!!.isVar, hasBackingField) val hasDelegate = wrapper.declaration is KtProperty && wrapper.declaration.hasDelegate()
return getTargetSet(parameter, descriptor!!.isVar, hasBackingField, hasDelegate)
} }
@JvmStatic fun getTargetSet(parameter: Boolean, isVar: Boolean, hasBackingField: Boolean): Set<AnnotationUseSiteTarget> { @JvmStatic fun getTargetSet(
return hashSetOf(PROPERTY, PROPERTY_GETTER).apply { parameter: Boolean, isVar: Boolean, hasBackingField: Boolean, hasDelegate: Boolean
if (parameter) add(CONSTRUCTOR_PARAMETER) ): Set<AnnotationUseSiteTarget> = hashSetOf(PROPERTY, PROPERTY_GETTER).apply {
if (hasBackingField) add(FIELD) if (parameter) add(CONSTRUCTOR_PARAMETER)
if (isVar) add(PROPERTY_SETTER) if (hasBackingField) add(FIELD)
} if (isVar) add(PROPERTY_SETTER)
if (hasDelegate) add(PROPERTY_DELEGATE_FIELD)
} }
} }
class PropertyWrapper(var property: PropertyDescriptor? = null) class PropertyWrapper @JvmOverloads constructor(val declaration: KtDeclaration, var descriptor: PropertyDescriptor? = null)
private val splitAnnotations = storageManager.createLazyValue { private val splitAnnotations = storageManager.createLazyValue {
val map = hashMapOf<AnnotationUseSiteTarget, MutableList<AnnotationWithTarget>>() val map = hashMapOf<AnnotationUseSiteTarget, MutableList<AnnotationWithTarget>>()
@@ -167,7 +167,9 @@ public interface Errors {
DiagnosticFactory0<KtExpression> NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtExpression> NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1<PsiElement, String> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_RECEIVER_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INAPPLICABLE_RECEIVER_TARGET = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INAPPLICABLE_PARAM_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INAPPLICABLE_PARAM_TARGET = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<PsiElement, String> REDUNDANT_ANNOTATION_TARGET = DiagnosticFactory1.create(WARNING); DiagnosticFactory1<PsiElement, String> REDUNDANT_ANNOTATION_TARGET = DiagnosticFactory1.create(WARNING);
@@ -157,8 +157,10 @@ public class DefaultErrorMessages {
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable"); MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere"); MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere");
MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}'' annotations could be applied only to property declarations", TO_STRING); MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING);
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "Property must be mutable"); MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "''@{0}:'' annotations could be applied only to mutable properties", TO_STRING);
MAP.put(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, "''@delegate:'' annotations could be applied only to delegated properties");
MAP.put(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD, "''@field:'' annotations could be applied only to properties with backing fields");
MAP.put(INAPPLICABLE_RECEIVER_TARGET, "''@receiver:'' annotations could be applied only to extension function or extension property declarations"); MAP.put(INAPPLICABLE_RECEIVER_TARGET, "''@receiver:'' annotations could be applied only to extension function or extension property declarations");
MAP.put(INAPPLICABLE_PARAM_TARGET, "''@param:'' annotations could be applied only to primary constructor parameters"); MAP.put(INAPPLICABLE_PARAM_TARGET, "''@param:'' annotations could be applied only to primary constructor parameters");
MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING); MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING);
@@ -142,6 +142,7 @@ public interface KtTokens {
KtKeywordToken RECEIVER_KEYWORD = KtKeywordToken.softKeyword("receiver"); KtKeywordToken RECEIVER_KEYWORD = KtKeywordToken.softKeyword("receiver");
KtKeywordToken PARAM_KEYWORD = KtKeywordToken.softKeyword("param"); KtKeywordToken PARAM_KEYWORD = KtKeywordToken.softKeyword("param");
KtKeywordToken SETPARAM_KEYWORD = KtKeywordToken.softKeyword("setparam"); KtKeywordToken SETPARAM_KEYWORD = KtKeywordToken.softKeyword("setparam");
KtKeywordToken DELEGATE_KEYWORD = KtKeywordToken.softKeyword("delegate");
KtKeywordToken IMPORT_KEYWORD = KtKeywordToken.softKeyword("import"); KtKeywordToken IMPORT_KEYWORD = KtKeywordToken.softKeyword("import");
KtKeywordToken WHERE_KEYWORD = KtKeywordToken.softKeyword("where"); KtKeywordToken WHERE_KEYWORD = KtKeywordToken.softKeyword("where");
KtKeywordToken BY_KEYWORD = KtKeywordToken.softKeyword("by"); KtKeywordToken BY_KEYWORD = KtKeywordToken.softKeyword("by");
@@ -203,6 +204,7 @@ public interface KtTokens {
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD, CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, REIFIED_KEYWORD,
DYNAMIC_KEYWORD, COMPANION_KEYWORD, CONSTRUCTOR_KEYWORD, INIT_KEYWORD, SEALED_KEYWORD, DYNAMIC_KEYWORD, COMPANION_KEYWORD, CONSTRUCTOR_KEYWORD, INIT_KEYWORD, SEALED_KEYWORD,
FIELD_KEYWORD, PROPERTY_KEYWORD, RECEIVER_KEYWORD, PARAM_KEYWORD, SETPARAM_KEYWORD, FIELD_KEYWORD, PROPERTY_KEYWORD, RECEIVER_KEYWORD, PARAM_KEYWORD, SETPARAM_KEYWORD,
DELEGATE_KEYWORD,
LATEINIT_KEYWORD, LATEINIT_KEYWORD,
DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD, DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD,
ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD, CONST_KEYWORD, OPERATOR_KEYWORD, INFIX_KEYWORD ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD, CONST_KEYWORD, OPERATOR_KEYWORD, INFIX_KEYWORD
@@ -64,7 +64,8 @@ public class KotlinParsing extends AbstractKotlinParsing {
TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS); TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
private static final TokenSet SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD); private static final TokenSet SOFT_KEYWORDS_AT_MEMBER_START = TokenSet.create(CONSTRUCTOR_KEYWORD, INIT_KEYWORD);
private static final TokenSet ANNOTATION_TARGETS = TokenSet.create( private static final TokenSet ANNOTATION_TARGETS = TokenSet.create(
FILE_KEYWORD, FIELD_KEYWORD, GET_KEYWORD, SET_KEYWORD, PROPERTY_KEYWORD, RECEIVER_KEYWORD, PARAM_KEYWORD, SETPARAM_KEYWORD); FILE_KEYWORD, FIELD_KEYWORD, GET_KEYWORD, SET_KEYWORD, PROPERTY_KEYWORD,
RECEIVER_KEYWORD, PARAM_KEYWORD, SETPARAM_KEYWORD, DELEGATE_KEYWORD);
static KotlinParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) { static KotlinParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
KotlinParsing jetParsing = new KotlinParsing(builder); KotlinParsing jetParsing = new KotlinParsing(builder);
@@ -54,6 +54,7 @@ class KtAnnotationUseSiteTarget : KtElementImplStub<KotlinAnnotationUseSiteTarge
KtTokens.RECEIVER_KEYWORD -> AnnotationUseSiteTarget.RECEIVER KtTokens.RECEIVER_KEYWORD -> AnnotationUseSiteTarget.RECEIVER
KtTokens.PARAM_KEYWORD -> AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER KtTokens.PARAM_KEYWORD -> AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
KtTokens.SETPARAM_KEYWORD -> AnnotationUseSiteTarget.SETTER_PARAMETER KtTokens.SETPARAM_KEYWORD -> AnnotationUseSiteTarget.SETTER_PARAMETER
KtTokens.DELEGATE_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
else -> throw IllegalStateException("Unknown annotation target " + node.getText()) else -> throw IllegalStateException("Unknown annotation target " + node.getText())
} }
} }
@@ -179,9 +179,9 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
if (annotated.isLocal) if (annotated.isLocal)
TargetLists.T_LOCAL_VARIABLE TargetLists.T_LOCAL_VARIABLE
else if (annotated.parent is KtClassOrObject || annotated.parent is KtClassBody) else if (annotated.parent is KtClassOrObject || annotated.parent is KtClassBody)
TargetLists.T_MEMBER_PROPERTY(descriptor.hasBackingField(trace)) TargetLists.T_MEMBER_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
else else
TargetLists.T_TOP_LEVEL_PROPERTY(descriptor.hasBackingField(trace)) TargetLists.T_TOP_LEVEL_PROPERTY(descriptor.hasBackingField(trace), annotated.hasDelegate())
} }
is KtParameter -> { is KtParameter -> {
if (annotated.hasValOrVar()) if (annotated.hasValOrVar())
@@ -224,19 +224,31 @@ class AnnotationChecker(private val additionalCheckers: Iterable<AdditionalAnnot
val T_DESTRUCTURING_DECLARATION = targetList(DESTRUCTURING_DECLARATION) val T_DESTRUCTURING_DECLARATION = targetList(DESTRUCTURING_DECLARATION)
fun T_MEMBER_PROPERTY(backingField: Boolean) = fun TargetListBuilder.propertyTargets(backingField: Boolean, delegate: Boolean) {
targetList(if (backingField) MEMBER_PROPERTY_WITH_FIELD else MEMBER_PROPERTY_WITHOUT_FIELD,
MEMBER_PROPERTY, PROPERTY) {
if (backingField) extraTargets(FIELD) if (backingField) extraTargets(FIELD)
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER) if (delegate) {
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER, FIELD)
}
else {
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER)
}
} }
fun T_TOP_LEVEL_PROPERTY(backingField: Boolean) = fun T_MEMBER_PROPERTY(backingField: Boolean, delegate: Boolean) =
targetList(if (backingField) TOP_LEVEL_PROPERTY_WITH_FIELD else TOP_LEVEL_PROPERTY_WITHOUT_FIELD, targetList(if (backingField) MEMBER_PROPERTY_WITH_BACKING_FIELD
else if (delegate) MEMBER_PROPERTY_WITH_DELEGATE
else MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE,
MEMBER_PROPERTY, PROPERTY) {
propertyTargets(backingField, delegate)
}
fun T_TOP_LEVEL_PROPERTY(backingField: Boolean, delegate: Boolean) =
targetList(if (backingField) TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD
else if (delegate) TOP_LEVEL_PROPERTY_WITH_DELEGATE
else TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE,
TOP_LEVEL_PROPERTY, PROPERTY) { TOP_LEVEL_PROPERTY, PROPERTY) {
if (backingField) extraTargets(FIELD) propertyTargets(backingField, delegate)
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER) }
}
val T_PROPERTY_GETTER = targetList(PROPERTY_GETTER) val T_PROPERTY_GETTER = targetList(PROPERTY_GETTER)
val T_PROPERTY_SETTER = targetList(PROPERTY_SETTER) val T_PROPERTY_SETTER = targetList(PROPERTY_SETTER)
@@ -28,6 +28,7 @@ object AnnotationUseSiteTargetChecker {
if (annotated is KtFunction) { if (annotated is KtFunction) {
for (parameter in annotated.valueParameters) { for (parameter in annotated.valueParameters) {
if (parameter.hasValOrVar()) continue
val parameterDescriptor = trace.bindingContext[BindingContext.VALUE_PARAMETER, parameter] ?: continue val parameterDescriptor = trace.bindingContext[BindingContext.VALUE_PARAMETER, parameter] ?: continue
trace.checkDeclaration(parameter, parameterDescriptor) trace.checkDeclaration(parameter, parameterDescriptor)
} }
@@ -45,6 +46,7 @@ object AnnotationUseSiteTargetChecker {
when (target) { when (target) {
AnnotationUseSiteTarget.RECEIVER -> {} AnnotationUseSiteTarget.RECEIVER -> {}
AnnotationUseSiteTarget.FIELD, AnnotationUseSiteTarget.FIELD,
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD,
AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.PROPERTY_GETTER, AnnotationUseSiteTarget.PROPERTY_GETTER,
AnnotationUseSiteTarget.PROPERTY_SETTER, AnnotationUseSiteTarget.PROPERTY_SETTER,
@@ -62,9 +64,10 @@ object AnnotationUseSiteTargetChecker {
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue
when (target) { when (target) {
AnnotationUseSiteTarget.FIELD, AnnotationUseSiteTarget.FIELD -> checkIfHasBackingField(annotated, descriptor, annotation)
AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.PROPERTY_GETTER -> {} AnnotationUseSiteTarget.PROPERTY_GETTER -> {}
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> checkIfDelegatedProperty(annotated, annotation)
AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation) AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation)
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> { AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> {
if (annotated !is KtParameter) { if (annotated !is KtParameter) {
@@ -87,6 +90,22 @@ object AnnotationUseSiteTargetChecker {
} }
} }
private fun BindingTrace.checkIfDelegatedProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry) {
if (annotated is KtProperty && !annotated.hasDelegate() || annotated is KtParameter && annotated.hasValOrVar()) {
report(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE.on(annotation))
}
}
private fun BindingTrace.checkIfHasBackingField(annotated: KtAnnotated, descriptor: DeclarationDescriptor, annotation: KtAnnotationEntry) {
if (annotated is KtProperty && annotated.hasDelegate() &&
descriptor is PropertyDescriptor && get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) != true) {
report(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD.on(annotation))
}
}
private fun KtAnnotationEntry.useSiteDescription() =
useSiteTarget?.getAnnotationUseSiteTarget()?.renderName ?: "unknown target" // should not happen
private fun BindingTrace.checkIfMutableProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry) { private fun BindingTrace.checkIfMutableProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry) {
if (!checkIfProperty(annotated, annotation)) return if (!checkIfProperty(annotated, annotation)) return
@@ -96,7 +115,9 @@ object AnnotationUseSiteTargetChecker {
annotated.isMutable annotated.isMutable
else false else false
if (!isMutable) report(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE.on(annotation)) if (!isMutable) {
report(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE.on(annotation, annotation.useSiteDescription()))
}
} }
private fun BindingTrace.checkIfProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry): Boolean { private fun BindingTrace.checkIfProperty(annotated: KtAnnotated, annotation: KtAnnotationEntry): Boolean {
@@ -106,8 +127,7 @@ object AnnotationUseSiteTargetChecker {
annotated.hasValOrVar() annotated.hasValOrVar()
else false else false
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget()?.renderName ?: "unknown target" // should not happen if (!isProperty) report(INAPPLICABLE_TARGET_ON_PROPERTY.on(annotation, annotation.useSiteDescription()))
if (!isProperty) report(INAPPLICABLE_TARGET_ON_PROPERTY.on(annotation, target))
return isProperty return isProperty
} }
} }
@@ -676,7 +676,7 @@ public class DescriptorResolver {
? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody)) ? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody))
: Modality.FINAL; : Modality.FINAL;
final AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(); final AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(property);
Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace); Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace);
AnnotationSplitter annotationSplitter = AnnotationSplitter annotationSplitter =
@@ -688,7 +688,7 @@ public class DescriptorResolver {
}); });
Annotations propertyAnnotations = new CompositeAnnotations(CollectionsKt.listOf( Annotations propertyAnnotations = new CompositeAnnotations(CollectionsKt.listOf(
annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD), annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD, PROPERTY_DELEGATE_FIELD),
annotationSplitter.getOtherAnnotations())); annotationSplitter.getOtherAnnotations()));
PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create( PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
@@ -703,7 +703,7 @@ public class DescriptorResolver {
modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD), modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD),
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD) modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD)
); );
wrapper.setProperty(propertyDescriptor); wrapper.setDescriptor(propertyDescriptor);
List<TypeParameterDescriptorImpl> typeParameterDescriptors; List<TypeParameterDescriptorImpl> typeParameterDescriptors;
LexicalScope scopeWithTypeParameters; LexicalScope scopeWithTypeParameters;
@@ -938,7 +938,7 @@ public class DescriptorResolver {
} }
} }
final AnnotationSplitter.PropertyWrapper propertyWrapper = new AnnotationSplitter.PropertyWrapper(); final AnnotationSplitter.PropertyWrapper propertyWrapper = new AnnotationSplitter.PropertyWrapper(parameter);
Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, parameter.getModifierList(), trace); Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, parameter.getModifierList(), trace);
AnnotationSplitter annotationSplitter = AnnotationSplitter annotationSplitter =
new AnnotationSplitter(storageManager, allAnnotations, new Function0<Set<AnnotationUseSiteTarget>>() { new AnnotationSplitter(storageManager, allAnnotations, new Function0<Set<AnnotationUseSiteTarget>>() {
@@ -964,7 +964,7 @@ public class DescriptorResolver {
/* lateInit = */ false, /* lateInit = */ false,
/* isConst = */ false /* isConst = */ false
); );
propertyWrapper.setProperty(propertyDescriptor); propertyWrapper.setDescriptor(propertyDescriptor);
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(),
getDispatchReceiverParameterIfNeeded(classDescriptor), (ReceiverParameterDescriptor) null); getDispatchReceiverParameterIfNeeded(classDescriptor), (ReceiverParameterDescriptor) null);
@@ -1,8 +1,14 @@
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import kotlin.reflect.KProperty
class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
}
class C { class C {
@Volatile var vol = 1 @Volatile var vol = 1
@Transient val tra = 1 @Transient val tra = 1
@delegate:Transient val del: String by CustomDelegate()
@Strictfp fun str() {} @Strictfp fun str() {}
@Synchronized fun sync() {} @Synchronized fun sync() {}
@@ -13,6 +19,7 @@ fun box(): String {
if (c.getDeclaredField("vol").getModifiers() and Modifier.VOLATILE == 0) return "Fail: volatile" if (c.getDeclaredField("vol").getModifiers() and Modifier.VOLATILE == 0) return "Fail: volatile"
if (c.getDeclaredField("tra").getModifiers() and Modifier.TRANSIENT == 0) return "Fail: transient" if (c.getDeclaredField("tra").getModifiers() and Modifier.TRANSIENT == 0) return "Fail: transient"
if (c.getDeclaredField("del\$delegate").getModifiers() and Modifier.TRANSIENT == 0) return "Fail: delegate transient"
if (c.getDeclaredMethod("str").getModifiers() and Modifier.STRICT == 0) return "Fail: strict" if (c.getDeclaredMethod("str").getModifiers() and Modifier.STRICT == 0) return "Fail: strict"
if (c.getDeclaredMethod("sync").getModifiers() and Modifier.SYNCHRONIZED == 0) return "Fail: synchronized" if (c.getDeclaredMethod("sync").getModifiers() and Modifier.SYNCHRONIZED == 0) return "Fail: synchronized"
@@ -1,13 +1,23 @@
import kotlin.reflect.KProperty
annotation class AnnProp annotation class AnnProp
annotation class AnnField annotation class AnnField
annotation class AnnProp2 annotation class AnnProp2
annotation class AnnGetter annotation class AnnGetter
annotation class AnnSetter annotation class AnnSetter
annotation class AnnParam annotation class AnnParam
annotation class AnnDelegate
class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
}
public class A(@AnnParam @field:AnnField @property:AnnProp2 val x: Int, @param:AnnParam @get:AnnGetter @set:AnnSetter var y: Int) { public class A(@AnnParam @field:AnnField @property:AnnProp2 val x: Int, @param:AnnParam @get:AnnGetter @set:AnnSetter var y: Int) {
@AnnProp @field:AnnField @property:AnnProp2 @get:AnnGetter @set:AnnSetter @setparam:AnnParam @AnnProp @field:AnnField @property:AnnProp2 @get:AnnGetter @set:AnnSetter @setparam:AnnParam
var p: Int = 0 var p: Int = 0
@AnnProp @property:AnnProp2 @delegate:AnnDelegate @property:AnnDelegate
val s: String by CustomDelegate()
} }
@@ -1,18 +1,27 @@
@kotlin.jvm.internal.KotlinClass @kotlin.jvm.internal.KotlinClass
public final class A { public final class A {
private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
private @AnnField field p: int private @AnnField field p: int
private final @AnnDelegate @org.jetbrains.annotations.NotNull field s$delegate: CustomDelegate
private final @AnnField field x: int private final @AnnField field x: int
private field y: int private field y: int
static method <clinit>(): void
public method <init>(@AnnParam p0: int, @AnnParam p1: int): void public method <init>(@AnnParam p0: int, @AnnParam p1: int): void
public final @AnnGetter method getP(): int public final @AnnGetter method getP(): int
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
public final method getX(): int public final method getX(): int
public final @AnnGetter method getY(): int public final @AnnGetter method getY(): int
private synthetic deprecated final static @AnnProp @AnnProp2 method p$annotations(): void private synthetic deprecated final static @AnnProp @AnnProp2 method p$annotations(): void
private synthetic deprecated final static @AnnProp @AnnProp2 @AnnDelegate method s$annotations(): void
public final @AnnSetter method setP(@AnnParam p0: int): void public final @AnnSetter method setP(@AnnParam p0: int): void
public final @AnnSetter method setY(p0: int): void public final @AnnSetter method setY(p0: int): void
private synthetic deprecated final static @AnnProp2 method x$annotations(): void private synthetic deprecated final static @AnnProp2 method x$annotations(): void
} }
@java.lang.annotation.Retention
@kotlin.jvm.internal.KotlinClass
public abstract class AnnDelegate
@java.lang.annotation.Retention @java.lang.annotation.Retention
@kotlin.jvm.internal.KotlinClass @kotlin.jvm.internal.KotlinClass
public abstract class AnnField public abstract class AnnField
@@ -35,4 +44,10 @@ public abstract class AnnProp2
@java.lang.annotation.Retention @java.lang.annotation.Retention
@kotlin.jvm.internal.KotlinClass @kotlin.jvm.internal.KotlinClass
public abstract class AnnSetter public abstract class AnnSetter
@kotlin.jvm.internal.KotlinClass
public final class CustomDelegate {
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String
}
@@ -0,0 +1,33 @@
import kotlin.reflect.KProperty
@Target(AnnotationTarget.FIELD) annotation class Field
@Target(AnnotationTarget.PROPERTY) annotation class Prop
class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
}
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Field<!>
class SomeClass {
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Field<!>
constructor()
<!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE!>@delegate:Field<!> <!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Prop<!>
protected val simpleProperty: String = "text"
@delegate:Field <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Prop<!>
protected val delegatedProperty: String by CustomDelegate()
<!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Field<!> <!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Prop<!>
val propertyWithCustomGetter: Int
get() = 5
}
class WithPrimaryConstructor(<!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE!>@delegate:Field<!> <!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE, WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Prop<!> val a: String,
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:Field<!> <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:Prop<!> val b: String)
fun foo(<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Field<!> <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@delegate:Prop<!> x: Int) = x
@@ -0,0 +1,44 @@
package
public fun foo(/*0*/ @delegate:Field() @delegate:Prop() x: kotlin.Int): kotlin.Int
public final class CustomDelegate {
public constructor CustomDelegate()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FIELD}) public final annotation class Field : kotlin.Annotation {
public constructor Field()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY}) public final annotation class Prop : kotlin.Annotation {
public constructor Prop()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@delegate:Field() public final class SomeClass {
@delegate:Field() public constructor SomeClass()
@delegate:Field() @delegate:Prop() protected final val delegatedProperty: kotlin.String
@delegate:Field() @delegate:Prop() public final val propertyWithCustomGetter: kotlin.Int
@delegate:Field() @delegate:Prop() protected final val simpleProperty: kotlin.String = "text"
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class WithPrimaryConstructor {
public constructor WithPrimaryConstructor(/*0*/ a: kotlin.String, /*1*/ @param:Field() @param:Prop() b: kotlin.String)
@delegate:Field() @delegate:Prop() public final val a: kotlin.String
public final val b: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -18,7 +18,7 @@ class SomeClass {
@field:[Ann] @field:[Ann]
protected val simplePropertyWithAnnotationList: String = "text" protected val simplePropertyWithAnnotationList: String = "text"
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@field:Ann<!> <!INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD!>@field:Ann<!>
protected val delegatedProperty: String by CustomDelegate() protected val delegatedProperty: String by CustomDelegate()
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@field:Ann<!> <!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@field:Ann<!>
@@ -1,8 +1,14 @@
import kotlin.reflect.KProperty
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
@Repeatable @Repeatable
annotation class RepeatableAnn annotation class RepeatableAnn
annotation class Ann annotation class Ann
class CustomDelegate {
operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name
}
public class A(@param:Ann <!REPEATED_ANNOTATION!>@Ann<!> val x: Int, @param: RepeatableAnn @Ann val y: Int) { public class A(@param:Ann <!REPEATED_ANNOTATION!>@Ann<!> val x: Int, @param: RepeatableAnn @Ann val y: Int) {
@field:Ann @property:Ann @RepeatableAnn @property:RepeatableAnn @field:Ann @property:Ann @RepeatableAnn @property:RepeatableAnn
@@ -17,4 +23,20 @@ public class A(@param:Ann <!REPEATED_ANNOTATION!>@Ann<!> val x: Int, @param: Rep
@property:RepeatableAnn @RepeatableAnn @property:RepeatableAnn @RepeatableAnn
val d: Int = 0 val d: Int = 0
@property:RepeatableAnn @RepeatableAnn @delegate:RepeatableAnn
val e: String by CustomDelegate()
@property:Ann @delegate:Ann
val f: String by CustomDelegate()
// Ideally we should not have repeated anotation here and below
// (because @Ann should go to the property and the second annotation to its related field)
@Ann <!REPEATED_ANNOTATION!>@delegate:Ann<!>
val g: String by CustomDelegate()
@Ann <!REPEATED_ANNOTATION!>@field:Ann<!>
val h: String = ""
@property:Ann @field:Ann
val i: String = ""
} }
@@ -6,6 +6,11 @@ public final class A {
@Ann() @property:Ann() @field:Ann() public final val b: kotlin.Int = 0 @Ann() @property:Ann() @field:Ann() public final val b: kotlin.Int = 0
@field:RepeatableAnn() @field:RepeatableAnn() public final val c: kotlin.Int = 0 @field:RepeatableAnn() @field:RepeatableAnn() public final val c: kotlin.Int = 0
@property:RepeatableAnn() @RepeatableAnn() public final val d: kotlin.Int = 0 @property:RepeatableAnn() @RepeatableAnn() public final val d: kotlin.Int = 0
@property:RepeatableAnn() @RepeatableAnn() @delegate:RepeatableAnn() public final val e: kotlin.String
@property:Ann() @delegate:Ann() public final val f: kotlin.String
@Ann() @delegate:Ann() public final val g: kotlin.String
@Ann() @field:Ann() public final val h: kotlin.String = ""
@property:Ann() @field:Ann() public final val i: kotlin.String = ""
public final val x: kotlin.Int public final val x: kotlin.Int
public final val y: kotlin.Int public final val y: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -20,6 +25,14 @@ public final annotation class Ann : kotlin.Annotation {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
public final class CustomDelegate {
public constructor CustomDelegate()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Repeatable() public final annotation class RepeatableAnn : kotlin.Annotation { @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Repeatable() public final annotation class RepeatableAnn : kotlin.Annotation {
public constructor RepeatableAnn() public constructor RepeatableAnn()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -0,0 +1,5 @@
class C {
val plainField: Int = 1
@delegate:Transient
val lazy by lazy { 1 }
}
@@ -0,0 +1,10 @@
package
public final class C {
public constructor C()
@delegate:kotlin.jvm.Transient() public final val lazy: kotlin.Int
public final val plainField: kotlin.Int = 1
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,7 @@
class C {
@delegate:Transient
val plainField: Int = 1
@delegate:Transient
val lazy by lazy { 1 }
}
@@ -0,0 +1,77 @@
JetFile: delegate.kt
PACKAGE_DIRECTIVE
<empty list>
IMPORT_LIST
<empty list>
CLASS
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('C')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
ANNOTATION_TARGET
PsiElement(delegate)('delegate')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Transient')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('plainField')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n\n ')
PROPERTY
MODIFIER_LIST
ANNOTATION_ENTRY
PsiElement(AT)('@')
ANNOTATION_TARGET
PsiElement(delegate)('delegate')
PsiElement(COLON)(':')
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Transient')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('lazy')
PsiWhiteSpace(' ')
PROPERTY_DELEGATE
PsiElement(by)('by')
PsiWhiteSpace(' ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('lazy')
PsiWhiteSpace(' ')
LAMBDA_ARGUMENT
LAMBDA_EXPRESSION
FUNCTION_LITERAL
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
BLOCK
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -1436,6 +1436,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget"), Pattern.compile("^(.+)\\.kt$"), true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget"), Pattern.compile("^(.+)\\.kt$"), true);
} }
@TestMetadata("DelegateAnnotations.kt")
public void testDelegateAnnotations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.kt");
doTest(fileName);
}
@TestMetadata("FieldAnnotations.kt") @TestMetadata("FieldAnnotations.kt")
public void testFieldAnnotations() throws Exception { public void testFieldAnnotations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt");
@@ -169,6 +169,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
doTest(fileName); doTest(fileName);
} }
@TestMetadata("TransientOnDelegate.kt")
public void testTransientOnDelegate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.kt");
doTest(fileName);
}
@TestMetadata("Volatile.kt") @TestMetadata("Volatile.kt")
public void testVolatile() throws Exception { public void testVolatile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt");
@@ -1003,6 +1003,12 @@ public class ParsingTestGenerated extends AbstractParsingTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/targeted/onField"), Pattern.compile("^(.*)\\.kts?$"), true); KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/annotation/targeted/onField"), Pattern.compile("^(.*)\\.kts?$"), true);
} }
@TestMetadata("delegate.kt")
public void testDelegate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/annotation/targeted/onField/delegate.kt");
doParsingTest(fileName);
}
@TestMetadata("fqName.kt") @TestMetadata("fqName.kt")
public void testFqName() throws Exception { public void testFqName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/annotation/targeted/onField/fqName.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/annotation/targeted/onField/fqName.kt");
@@ -26,7 +26,8 @@ enum class AnnotationUseSiteTarget(renderName: String? = null) {
PROPERTY_SETTER("set"), PROPERTY_SETTER("set"),
RECEIVER(), RECEIVER(),
CONSTRUCTOR_PARAMETER("param"), CONSTRUCTOR_PARAMETER("param"),
SETTER_PARAMETER("setparam"); SETTER_PARAMETER("setparam"),
PROPERTY_DELEGATE_FIELD("delegate");
val renderName: String = renderName ?: name.toLowerCase() val renderName: String = renderName ?: name.toLowerCase()
@@ -57,12 +57,14 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true)
MEMBER_FUNCTION("member function", false), MEMBER_FUNCTION("member function", false),
TOP_LEVEL_FUNCTION("top level function", false), TOP_LEVEL_FUNCTION("top level function", false),
MEMBER_PROPERTY("member property", false), // includes PROPERTY_PARAMETER, with and without field MEMBER_PROPERTY("member property", false), // includes PROPERTY_PARAMETER, with and without field/delegate
MEMBER_PROPERTY_WITH_FIELD("member property with backing field", false), MEMBER_PROPERTY_WITH_BACKING_FIELD("member property with backing field", false),
MEMBER_PROPERTY_WITHOUT_FIELD("member property without backing field", false), MEMBER_PROPERTY_WITH_DELEGATE("member property with delegate", false),
TOP_LEVEL_PROPERTY("top level property", false), // with and without field MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE("member property without backing field or delegate", false),
TOP_LEVEL_PROPERTY_WITH_FIELD("top level property with backing field", false), TOP_LEVEL_PROPERTY("top level property", false), // with and without field/delegate
TOP_LEVEL_PROPERTY_WITHOUT_FIELD("top level property without backing field", false), TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD("top level property with backing field", false),
TOP_LEVEL_PROPERTY_WITH_DELEGATE("top level property with delegate", false),
TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE("top level property without backing field or delegate", false),
INITIALIZER("initializer", false), INITIALIZER("initializer", false),
DESTRUCTURING_DECLARATION("destructuring declaration", false), DESTRUCTURING_DECLARATION("destructuring declaration", false),
@@ -125,7 +127,8 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true)
AnnotationUseSiteTarget.PROPERTY_GETTER to PROPERTY_GETTER, AnnotationUseSiteTarget.PROPERTY_GETTER to PROPERTY_GETTER,
AnnotationUseSiteTarget.PROPERTY_SETTER to PROPERTY_SETTER, AnnotationUseSiteTarget.PROPERTY_SETTER to PROPERTY_SETTER,
AnnotationUseSiteTarget.RECEIVER to VALUE_PARAMETER, AnnotationUseSiteTarget.RECEIVER to VALUE_PARAMETER,
AnnotationUseSiteTarget.SETTER_PARAMETER to VALUE_PARAMETER) AnnotationUseSiteTarget.SETTER_PARAMETER to VALUE_PARAMETER,
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD to FIELD)
} }
} }
+1
View File
@@ -8,4 +8,5 @@
// EXIST: { itemText: "setparam:" } // EXIST: { itemText: "setparam:" }
// EXIST: { itemText: "property:" } // EXIST: { itemText: "property:" }
// EXIST: { itemText: "receiver:" } // EXIST: { itemText: "receiver:" }
// EXIST: { itemText: "delegate:" }
// NOTHING_ELSE // NOTHING_ELSE
@@ -11,4 +11,5 @@ class Completion(@get:Ann val p1: String, @<caret>)
/*TODO: in fact is not applicable */ /*TODO: in fact is not applicable */
// EXIST: receiver // EXIST: receiver
// EXIST: delegate
// NOTHING_ELSE // NOTHING_ELSE