Volatile forbidden for delegated properties (and checked for other use-site targets)
This commit is contained in:
+9
-3
@@ -143,9 +143,15 @@ class VolatileAnnotationChecker : DeclarationChecker {
|
|||||||
bindingContext: BindingContext
|
bindingContext: BindingContext
|
||||||
) {
|
) {
|
||||||
val volatileAnnotation = DescriptorUtils.getVolatileAnnotation(descriptor)
|
val volatileAnnotation = DescriptorUtils.getVolatileAnnotation(descriptor)
|
||||||
if (volatileAnnotation != null && descriptor is PropertyDescriptor && !descriptor.isVar) {
|
if (volatileAnnotation != null) {
|
||||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
|
if (descriptor is PropertyDescriptor && !descriptor.isVar) {
|
||||||
diagnosticHolder.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
|
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
|
||||||
|
diagnosticHolder.report(ErrorsJvm.VOLATILE_ON_VALUE.on(annotationEntry))
|
||||||
|
}
|
||||||
|
if (declaration is KtProperty && declaration.hasDelegate()) {
|
||||||
|
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(volatileAnnotation) ?: return
|
||||||
|
diagnosticHolder.report(ErrorsJvm.VOLATILE_ON_DELEGATE.on(annotationEntry))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -64,6 +64,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
|||||||
MAP.put(ErrorsJvm.INAPPLICABLE_JVM_NAME, "''@JvmName'' annotation is not applicable to this declaration");
|
MAP.put(ErrorsJvm.INAPPLICABLE_JVM_NAME, "''@JvmName'' annotation is not applicable to this declaration");
|
||||||
MAP.put(ErrorsJvm.ILLEGAL_JVM_NAME, "Illegal JVM name");
|
MAP.put(ErrorsJvm.ILLEGAL_JVM_NAME, "Illegal JVM name");
|
||||||
MAP.put(ErrorsJvm.VOLATILE_ON_VALUE, "''@Volatile'' annotation cannot be used on immutable properties");
|
MAP.put(ErrorsJvm.VOLATILE_ON_VALUE, "''@Volatile'' annotation cannot be used on immutable properties");
|
||||||
|
MAP.put(ErrorsJvm.VOLATILE_ON_DELEGATE, "''@Volatile'' annotation cannot be used on delegated properties");
|
||||||
MAP.put(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT, "''@Synchronized'' annotation cannot be used on abstract functions");
|
MAP.put(ErrorsJvm.SYNCHRONIZED_ON_ABSTRACT, "''@Synchronized'' annotation cannot be used on abstract functions");
|
||||||
MAP.put(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, "External declaration can not be abstract");
|
MAP.put(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT, "External declaration can not be abstract");
|
||||||
MAP.put(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, "External declaration can not have a body");
|
MAP.put(ErrorsJvm.EXTERNAL_DECLARATION_CANNOT_HAVE_BODY, "External declaration can not have a body");
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public interface ErrorsJvm {
|
|||||||
DiagnosticFactory1<KtAnnotationEntry, String> INAPPLICABLE_JVM_FIELD = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<KtAnnotationEntry, String> INAPPLICABLE_JVM_FIELD = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_VALUE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_VALUE = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_DELEGATE = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory0<KtDeclaration> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
DiagnosticFactory0<KtDeclaration> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import kotlin.jvm.Volatile
|
import kotlin.jvm.Volatile
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
class My {
|
class My {
|
||||||
<!VOLATILE_ON_VALUE!>@Volatile<!> val x = 0
|
<!VOLATILE_ON_VALUE!>@Volatile<!> val x = 0
|
||||||
// ok
|
// ok
|
||||||
@Volatile var y = 1
|
@Volatile var y = 1
|
||||||
|
|
||||||
|
<!VOLATILE_ON_DELEGATE!>@delegate:Volatile<!> var z: String by Delegates.observable("?") { prop, old, new -> old.hashCode() }
|
||||||
|
|
||||||
|
<!VOLATILE_ON_VALUE!>@field:Volatile<!> val w = 2
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,10 @@ package
|
|||||||
|
|
||||||
public final class My {
|
public final class My {
|
||||||
public constructor My()
|
public constructor My()
|
||||||
|
@field:kotlin.jvm.Volatile() public final val w: kotlin.Int = 2
|
||||||
@kotlin.jvm.Volatile() public final val x: kotlin.Int = 0
|
@kotlin.jvm.Volatile() public final val x: kotlin.Int = 0
|
||||||
@kotlin.jvm.Volatile() public final var y: kotlin.Int
|
@kotlin.jvm.Volatile() public final var y: kotlin.Int
|
||||||
|
@delegate:kotlin.jvm.Volatile() public final var z: kotlin.String
|
||||||
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
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ public class DescriptorUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static String getJvmName(@NotNull Annotated annotated) {
|
public static String getJvmName(@NotNull Annotated annotated) {
|
||||||
AnnotationDescriptor jvmNameAnnotation = getJvmNameAnnotation(annotated.getAnnotations());
|
AnnotationDescriptor jvmNameAnnotation = getAnnotationByFqName(annotated.getAnnotations(), JVM_NAME);
|
||||||
if (jvmNameAnnotation == null) return null;
|
if (jvmNameAnnotation == null) return null;
|
||||||
|
|
||||||
Map<ValueParameterDescriptor, ConstantValue<?>> arguments = jvmNameAnnotation.getAllValueArguments();
|
Map<ValueParameterDescriptor, ConstantValue<?>> arguments = jvmNameAnnotation.getAllValueArguments();
|
||||||
@@ -520,24 +520,24 @@ public class DescriptorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AnnotationDescriptor getJvmNameAnnotation(@NotNull Annotations annotations) {
|
public static AnnotationDescriptor getAnnotationByFqName(@NotNull Annotations annotations, @NotNull FqName name) {
|
||||||
AnnotationWithTarget jvmName = Annotations.Companion.findAnyAnnotation(annotations, JVM_NAME);
|
AnnotationWithTarget annotationWithTarget = Annotations.Companion.findAnyAnnotation(annotations, name);
|
||||||
return jvmName == null ? null : jvmName.getAnnotation();
|
return annotationWithTarget == null ? null : annotationWithTarget.getAnnotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AnnotationDescriptor getJvmNameAnnotation(@NotNull Annotated annotated) {
|
public static AnnotationDescriptor getJvmNameAnnotation(@NotNull Annotated annotated) {
|
||||||
return getJvmNameAnnotation(annotated.getAnnotations());
|
return getAnnotationByFqName(annotated.getAnnotations(), JVM_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AnnotationDescriptor getVolatileAnnotation(@NotNull Annotated annotated) {
|
public static AnnotationDescriptor getVolatileAnnotation(@NotNull Annotated annotated) {
|
||||||
return annotated.getAnnotations().findAnnotation(VOLATILE);
|
return getAnnotationByFqName(annotated.getAnnotations(), VOLATILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AnnotationDescriptor getSynchronizedAnnotation(@NotNull Annotated annotated) {
|
public static AnnotationDescriptor getSynchronizedAnnotation(@NotNull Annotated annotated) {
|
||||||
return annotated.getAnnotations().findAnnotation(SYNCHRONIZED);
|
return getAnnotationByFqName(annotated.getAnnotations(), SYNCHRONIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user