From b78d481bb155b44da768f9920e6b4aa569a61fed Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 14 Jan 2016 16:28:29 +0300 Subject: [PATCH] delegate use-site targeted annotations: parser, front-end, codegen with some tests #KT-10502 Fixed --- .../kotlin/codegen/PropertyCodegen.java | 16 ++-- .../annotations/AnnotationSplitter.kt | 26 ++++--- .../jetbrains/kotlin/diagnostics/Errors.java | 4 +- .../rendering/DefaultErrorMessages.java | 6 +- .../org/jetbrains/kotlin/lexer/KtTokens.java | 2 + .../kotlin/parsing/KotlinParsing.java | 3 +- .../kotlin/psi/KtAnnotationUseSiteTarget.kt | 1 + .../kotlin/resolve/AnnotationChecker.kt | 34 +++++--- .../resolve/AnnotationUseSiteTargetChecker.kt | 28 ++++++- .../kotlin/resolve/DescriptorResolver.java | 10 +-- .../fullJdk/jvmAnnotationFlags.kt | 7 ++ .../annotations/onProperties.kt | 10 +++ .../annotations/onProperties.txt | 17 +++- .../withUseSiteTarget/DelegateAnnotations.kt | 33 ++++++++ .../withUseSiteTarget/DelegateAnnotations.txt | 44 +++++++++++ .../withUseSiteTarget/FieldAnnotations.kt | 2 +- .../withUseSiteTarget/repeatable.kt | 22 ++++++ .../withUseSiteTarget/repeatable.txt | 13 ++++ .../annotations/TransientOnDelegate.kt | 5 ++ .../annotations/TransientOnDelegate.txt | 10 +++ .../annotation/targeted/onField/delegate.kt | 7 ++ .../annotation/targeted/onField/delegate.txt | 77 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++ .../DiagnosticsTestWithStdLibGenerated.java | 6 ++ .../kotlin/parsing/ParsingTestGenerated.java | 6 ++ .../annotations/AnnotationUseSiteTarget.kt | 3 +- .../descriptors/annotations/KotlinTarget.kt | 17 ++-- .../testData/keywords/FileKeyword.kt | 1 + ...iteTargetForPrimaryConstructorParameter.kt | 1 + 29 files changed, 366 insertions(+), 51 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.txt create mode 100644 compiler/testData/psi/annotation/targeted/onField/delegate.kt create mode 100644 compiler/testData/psi/annotation/targeted/onField/delegate.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 9ab4b35a969..9aeab9dc4eb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -130,16 +130,18 @@ public class PropertyCodegen { private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) { boolean hasBackingField = hasBackingField(declaration, descriptor); + boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate(); AnnotationSplitter annotationSplitter = AnnotationSplitter.create(LockBasedStorageManager.NO_LOCKS, descriptor.getAnnotations(), - AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField)); + AnnotationSplitter.getTargetSet(isParameter, descriptor.isVar(), hasBackingField, hasDelegate)); Annotations fieldAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.FIELD); + Annotations delegateAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD); Annotations propertyAnnotations = annotationSplitter.getAnnotationsForTarget(AnnotationUseSiteTarget.PROPERTY); - generateBackingField(declaration, descriptor, fieldAnnotations); + generateBackingField(declaration, descriptor, fieldAnnotations, delegateAnnotations); generateSyntheticMethodIfNeeded(descriptor, propertyAnnotations); } @@ -228,17 +230,18 @@ public class PropertyCodegen { private boolean generateBackingField( @NotNull KtNamedDeclaration p, @NotNull PropertyDescriptor descriptor, - @NotNull Annotations annotations + @NotNull Annotations backingFieldAnnotations, + @NotNull Annotations delegateAnnotations ) { if (isJvmInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.DEFAULT_IMPLS) { return false; } 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))) { - generateBackingFieldAccess(p, descriptor, annotations); + generateBackingFieldAccess(p, descriptor, backingFieldAnnotations); } else { return false; @@ -327,7 +330,8 @@ public class PropertyCodegen { typeMapper.mapFieldSignature(jetType, propertyDescriptor), defaultValue); 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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationSplitter.kt b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationSplitter.kt index a541d86f2d1..10c0db85b8e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationSplitter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationSplitter.kt @@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.resolve.AnnotationChecker import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.* 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.storage.StorageManager import org.jetbrains.kotlin.storage.getValue @@ -54,22 +56,24 @@ class AnnotationSplitter( } @JvmStatic fun getTargetSet(parameter: Boolean, context: BindingContext, wrapper: PropertyWrapper): Set { - val property = wrapper.property - assert(property != null) - val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, property] ?: false - return getTargetSet(parameter, property!!.isVar, hasBackingField) + val descriptor = wrapper.descriptor + assert(descriptor != null) + val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false + 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 { - return hashSetOf(PROPERTY, PROPERTY_GETTER).apply { - if (parameter) add(CONSTRUCTOR_PARAMETER) - if (hasBackingField) add(FIELD) - if (isVar) add(PROPERTY_SETTER) - } + @JvmStatic fun getTargetSet( + parameter: Boolean, isVar: Boolean, hasBackingField: Boolean, hasDelegate: Boolean + ): Set = hashSetOf(PROPERTY, PROPERTY_GETTER).apply { + if (parameter) add(CONSTRUCTOR_PARAMETER) + 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 { val map = hashMapOf>() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 32f13f94634..fe66bef4cf4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -167,7 +167,9 @@ public interface Errors { DiagnosticFactory0 NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 INAPPLICABLE_TARGET_ON_PROPERTY = DiagnosticFactory1.create(ERROR); - DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory1.create(ERROR); + DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_HAS_NO_DELEGATE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_RECEIVER_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_PARAM_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 REDUNDANT_ANNOTATION_TARGET = DiagnosticFactory1.create(WARNING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index d2e85ec66a4..7ce12e1fb30 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -157,8 +157,10 @@ public class DefaultErrorMessages { 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(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_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING); + 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_PARAM_TARGET, "''@param:'' annotations could be applied only to primary constructor parameters"); MAP.put(REDUNDANT_ANNOTATION_TARGET, "Redundant annotation target ''{0}''", STRING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/lexer/KtTokens.java b/compiler/frontend/src/org/jetbrains/kotlin/lexer/KtTokens.java index b4a3c930577..fbd40901ab2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/lexer/KtTokens.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/lexer/KtTokens.java @@ -142,6 +142,7 @@ public interface KtTokens { KtKeywordToken RECEIVER_KEYWORD = KtKeywordToken.softKeyword("receiver"); KtKeywordToken PARAM_KEYWORD = KtKeywordToken.softKeyword("param"); KtKeywordToken SETPARAM_KEYWORD = KtKeywordToken.softKeyword("setparam"); + KtKeywordToken DELEGATE_KEYWORD = KtKeywordToken.softKeyword("delegate"); KtKeywordToken IMPORT_KEYWORD = KtKeywordToken.softKeyword("import"); KtKeywordToken WHERE_KEYWORD = KtKeywordToken.softKeyword("where"); 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, DYNAMIC_KEYWORD, COMPANION_KEYWORD, CONSTRUCTOR_KEYWORD, INIT_KEYWORD, SEALED_KEYWORD, FIELD_KEYWORD, PROPERTY_KEYWORD, RECEIVER_KEYWORD, PARAM_KEYWORD, SETPARAM_KEYWORD, + DELEGATE_KEYWORD, LATEINIT_KEYWORD, DATA_KEYWORD, INLINE_KEYWORD, NOINLINE_KEYWORD, TAILREC_KEYWORD, EXTERNAL_KEYWORD, ANNOTATION_KEYWORD, CROSSINLINE_KEYWORD, CONST_KEYWORD, OPERATOR_KEYWORD, INFIX_KEYWORD diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java index 901c23c54ed..b31de91bec6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java @@ -64,7 +64,8 @@ public class KotlinParsing extends AbstractKotlinParsing { 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 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) { KotlinParsing jetParsing = new KotlinParsing(builder); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtAnnotationUseSiteTarget.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtAnnotationUseSiteTarget.kt index c48c832eaa9..454d3019642 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtAnnotationUseSiteTarget.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtAnnotationUseSiteTarget.kt @@ -54,6 +54,7 @@ class KtAnnotationUseSiteTarget : KtElementImplStub AnnotationUseSiteTarget.RECEIVER KtTokens.PARAM_KEYWORD -> AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER KtTokens.SETPARAM_KEYWORD -> AnnotationUseSiteTarget.SETTER_PARAMETER + KtTokens.DELEGATE_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD else -> throw IllegalStateException("Unknown annotation target " + node.getText()) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt index 97cd7fe0e5c..86c57e3a722 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationChecker.kt @@ -179,9 +179,9 @@ class AnnotationChecker(private val additionalCheckers: Iterable { if (annotated.hasValOrVar()) @@ -224,19 +224,31 @@ class AnnotationChecker(private val additionalCheckers: Iterable {} AnnotationUseSiteTarget.FIELD, + AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD, AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY_GETTER, AnnotationUseSiteTarget.PROPERTY_SETTER, @@ -62,9 +64,10 @@ object AnnotationUseSiteTargetChecker { val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue when (target) { - AnnotationUseSiteTarget.FIELD, + AnnotationUseSiteTarget.FIELD -> checkIfHasBackingField(annotated, descriptor, annotation) AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY_GETTER -> {} + AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> checkIfDelegatedProperty(annotated, annotation) AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation) AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> { 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) { if (!checkIfProperty(annotated, annotation)) return @@ -96,7 +115,9 @@ object AnnotationUseSiteTargetChecker { annotated.isMutable 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 { @@ -106,8 +127,7 @@ object AnnotationUseSiteTargetChecker { annotated.hasValOrVar() else false - val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget()?.renderName ?: "unknown target" // should not happen - if (!isProperty) report(INAPPLICABLE_TARGET_ON_PROPERTY.on(annotation, target)) + if (!isProperty) report(INAPPLICABLE_TARGET_ON_PROPERTY.on(annotation, annotation.useSiteDescription())) return isProperty } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 5cd8c017e6d..4e60c9a7ee4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -676,7 +676,7 @@ public class DescriptorResolver { ? resolveModalityFromModifiers(property, getDefaultModality(containingDeclaration, visibility, hasBody)) : Modality.FINAL; - final AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(); + final AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(property); Annotations allAnnotations = annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace); AnnotationSplitter annotationSplitter = @@ -688,7 +688,7 @@ public class DescriptorResolver { }); Annotations propertyAnnotations = new CompositeAnnotations(CollectionsKt.listOf( - annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD), + annotationSplitter.getAnnotationsForTargets(PROPERTY, FIELD, PROPERTY_DELEGATE_FIELD), annotationSplitter.getOtherAnnotations())); PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create( @@ -703,7 +703,7 @@ public class DescriptorResolver { modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD), modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD) ); - wrapper.setProperty(propertyDescriptor); + wrapper.setDescriptor(propertyDescriptor); List typeParameterDescriptors; 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); AnnotationSplitter annotationSplitter = new AnnotationSplitter(storageManager, allAnnotations, new Function0>() { @@ -964,7 +964,7 @@ public class DescriptorResolver { /* lateInit = */ false, /* isConst = */ false ); - propertyWrapper.setProperty(propertyDescriptor); + propertyWrapper.setDescriptor(propertyDescriptor); propertyDescriptor.setType(type, Collections.emptyList(), getDispatchReceiverParameterIfNeeded(classDescriptor), (ReceiverParameterDescriptor) null); diff --git a/compiler/testData/codegen/boxWithStdlib/fullJdk/jvmAnnotationFlags.kt b/compiler/testData/codegen/boxWithStdlib/fullJdk/jvmAnnotationFlags.kt index 5fa233b7793..5d2dd7d826a 100644 --- a/compiler/testData/codegen/boxWithStdlib/fullJdk/jvmAnnotationFlags.kt +++ b/compiler/testData/codegen/boxWithStdlib/fullJdk/jvmAnnotationFlags.kt @@ -1,8 +1,14 @@ import java.lang.reflect.Modifier +import kotlin.reflect.KProperty + +class CustomDelegate { + operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name +} class C { @Volatile var vol = 1 @Transient val tra = 1 + @delegate:Transient val del: String by CustomDelegate() @Strictfp fun str() {} @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("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("sync").getModifiers() and Modifier.SYNCHRONIZED == 0) return "Fail: synchronized" diff --git a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt index 8e76475e603..cf4f0560177 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt +++ b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.kt @@ -1,13 +1,23 @@ +import kotlin.reflect.KProperty + annotation class AnnProp annotation class AnnField annotation class AnnProp2 annotation class AnnGetter annotation class AnnSetter 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) { @AnnProp @field:AnnField @property:AnnProp2 @get:AnnGetter @set:AnnSetter @setparam:AnnParam var p: Int = 0 + @AnnProp @property:AnnProp2 @delegate:AnnDelegate @property:AnnDelegate + val s: String by CustomDelegate() + } \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt index 8695846aaea..0ac9239740d 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/onProperties.txt @@ -1,18 +1,27 @@ @kotlin.jvm.internal.KotlinClass public final class A { + private synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] private @AnnField field p: int + private final @AnnDelegate @org.jetbrains.annotations.NotNull field s$delegate: CustomDelegate private final @AnnField field x: int private field y: int + static method (): void public method (@AnnParam p0: int, @AnnParam p1: int): void public final @AnnGetter method getP(): int + public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String public final method getX(): 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 @AnnDelegate method s$annotations(): void public final @AnnSetter method setP(@AnnParam p0: int): void public final @AnnSetter method setY(p0: int): 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 @kotlin.jvm.internal.KotlinClass public abstract class AnnField @@ -35,4 +44,10 @@ public abstract class AnnProp2 @java.lang.annotation.Retention @kotlin.jvm.internal.KotlinClass -public abstract class AnnSetter \ No newline at end of file +public abstract class AnnSetter + +@kotlin.jvm.internal.KotlinClass +public final class CustomDelegate { + public method (): 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 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.kt new file mode 100644 index 00000000000..ec802af51d9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.kt @@ -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 +} + +@delegate:Field +class SomeClass { + + @delegate:Field + constructor() + + @delegate:Field @delegate:Prop + protected val simpleProperty: String = "text" + + @delegate:Field @delegate:Prop + protected val delegatedProperty: String by CustomDelegate() + + @delegate:Field @delegate:Prop + val propertyWithCustomGetter: Int + get() = 5 + +} + +class WithPrimaryConstructor(@delegate:Field @delegate:Prop val a: String, + @param:Field @param:Prop val b: String) + +fun foo(@delegate:Field @delegate:Prop x: Int) = x + diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.txt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.txt new file mode 100644 index 00000000000..62a2ead5cc6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/DelegateAnnotations.txt @@ -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 +} diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt index b3dd4eea75a..5bccfc5e716 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt @@ -18,7 +18,7 @@ class SomeClass { @field:[Ann] protected val simplePropertyWithAnnotationList: String = "text" - @field:Ann + @field:Ann protected val delegatedProperty: String by CustomDelegate() @field:Ann diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt index f66fb0e012e..309e4341e1c 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.kt @@ -1,8 +1,14 @@ +import kotlin.reflect.KProperty + @Retention(AnnotationRetention.SOURCE) @Repeatable annotation class RepeatableAnn annotation class Ann +class CustomDelegate { + operator fun getValue(thisRef: Any?, prop: KProperty<*>): String = prop.name +} + public class A(@param:Ann @Ann val x: Int, @param: RepeatableAnn @Ann val y: Int) { @field:Ann @property:Ann @RepeatableAnn @property:RepeatableAnn @@ -17,4 +23,20 @@ public class A(@param:Ann @Ann val x: Int, @param: Rep @property:RepeatableAnn @RepeatableAnn 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 @delegate:Ann + val g: String by CustomDelegate() + + @Ann @field:Ann + val h: String = "" + + @property:Ann @field:Ann + val i: String = "" } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.txt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.txt index 71830de16b2..2ca908781d6 100644 --- a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.txt +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/repeatable.txt @@ -6,6 +6,11 @@ public final class A { @Ann() @property:Ann() @field:Ann() public final val b: 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() @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 y: kotlin.Int 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 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 { public constructor RepeatableAnn() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.kt new file mode 100644 index 00000000000..30742ed854c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.kt @@ -0,0 +1,5 @@ +class C { + val plainField: Int = 1 + @delegate:Transient + val lazy by lazy { 1 } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.txt new file mode 100644 index 00000000000..49811b7fbdc --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/TransientOnDelegate.txt @@ -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 +} diff --git a/compiler/testData/psi/annotation/targeted/onField/delegate.kt b/compiler/testData/psi/annotation/targeted/onField/delegate.kt new file mode 100644 index 00000000000..0b56aaecaa4 --- /dev/null +++ b/compiler/testData/psi/annotation/targeted/onField/delegate.kt @@ -0,0 +1,7 @@ +class C { + @delegate:Transient + val plainField: Int = 1 + + @delegate:Transient + val lazy by lazy { 1 } +} \ No newline at end of file diff --git a/compiler/testData/psi/annotation/targeted/onField/delegate.txt b/compiler/testData/psi/annotation/targeted/onField/delegate.txt new file mode 100644 index 00000000000..6631dfe181c --- /dev/null +++ b/compiler/testData/psi/annotation/targeted/onField/delegate.txt @@ -0,0 +1,77 @@ +JetFile: delegate.kt + PACKAGE_DIRECTIVE + + IMPORT_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)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 5b1b658b7ee..20425acbf6a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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); } + @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") public void testFieldAnnotations() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FieldAnnotations.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 86f82725ae1..054c99da2c1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -169,6 +169,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW 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") public void testVolatile() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/annotations/Volatile.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java index a8b72c9a432..5a9382ad615 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java @@ -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); } + @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") public void testFqName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/annotation/targeted/onField/fqName.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt index fd0fcb42230..686010e2934 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt @@ -26,7 +26,8 @@ enum class AnnotationUseSiteTarget(renderName: String? = null) { PROPERTY_SETTER("set"), RECEIVER(), CONSTRUCTOR_PARAMETER("param"), - SETTER_PARAMETER("setparam"); + SETTER_PARAMETER("setparam"), + PROPERTY_DELEGATE_FIELD("delegate"); val renderName: String = renderName ?: name.toLowerCase() diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt index 33736f18a18..4510254a99e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/KotlinTarget.kt @@ -57,12 +57,14 @@ enum class KotlinTarget(val description: String, val isDefault: Boolean = true) MEMBER_FUNCTION("member function", false), TOP_LEVEL_FUNCTION("top level function", false), - MEMBER_PROPERTY("member property", false), // includes PROPERTY_PARAMETER, with and without field - MEMBER_PROPERTY_WITH_FIELD("member property with backing field", false), - MEMBER_PROPERTY_WITHOUT_FIELD("member property without backing field", false), - TOP_LEVEL_PROPERTY("top level property", false), // with and without field - TOP_LEVEL_PROPERTY_WITH_FIELD("top level property with backing field", false), - TOP_LEVEL_PROPERTY_WITHOUT_FIELD("top level property without backing field", false), + MEMBER_PROPERTY("member property", false), // includes PROPERTY_PARAMETER, with and without field/delegate + MEMBER_PROPERTY_WITH_BACKING_FIELD("member property with backing field", false), + MEMBER_PROPERTY_WITH_DELEGATE("member property with delegate", false), + MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE("member property without backing field or delegate", false), + TOP_LEVEL_PROPERTY("top level property", false), // with and without field/delegate + 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), 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_SETTER to PROPERTY_SETTER, AnnotationUseSiteTarget.RECEIVER to VALUE_PARAMETER, - AnnotationUseSiteTarget.SETTER_PARAMETER to VALUE_PARAMETER) + AnnotationUseSiteTarget.SETTER_PARAMETER to VALUE_PARAMETER, + AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD to FIELD) } } \ No newline at end of file diff --git a/idea/idea-completion/testData/keywords/FileKeyword.kt b/idea/idea-completion/testData/keywords/FileKeyword.kt index cb7656336f4..b1246c0a6ac 100644 --- a/idea/idea-completion/testData/keywords/FileKeyword.kt +++ b/idea/idea-completion/testData/keywords/FileKeyword.kt @@ -8,4 +8,5 @@ // EXIST: { itemText: "setparam:" } // EXIST: { itemText: "property:" } // EXIST: { itemText: "receiver:" } +// EXIST: { itemText: "delegate:" } // NOTHING_ELSE diff --git a/idea/idea-completion/testData/keywords/UseSiteTargetForPrimaryConstructorParameter.kt b/idea/idea-completion/testData/keywords/UseSiteTargetForPrimaryConstructorParameter.kt index 1672ce6d244..45b4a538fcd 100644 --- a/idea/idea-completion/testData/keywords/UseSiteTargetForPrimaryConstructorParameter.kt +++ b/idea/idea-completion/testData/keywords/UseSiteTargetForPrimaryConstructorParameter.kt @@ -11,4 +11,5 @@ class Completion(@get:Ann val p1: String, @) /*TODO: in fact is not applicable */ // EXIST: receiver +// EXIST: delegate // NOTHING_ELSE