publicField -> JvmField
Effectively drop publicField and introduce JvmField (which has the same effect for now) Implement frontend checks for @JvmField Replace publicField -> JvmField in test data
This commit is contained in:
committed by
Michael Bogdanov
parent
bfaf806f47
commit
6cf9bfdb70
@@ -17,8 +17,13 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm.annotations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
public fun DeclarationDescriptor.hasJvmOverloadsAnnotation(): Boolean {
|
||||
return getAnnotations().findAnnotation(FqName("kotlin.jvm.JvmOverloads")) != null
|
||||
}
|
||||
|
||||
public fun DeclarationDescriptor.findJvmFieldAnnotation(): AnnotationDescriptor? {
|
||||
return annotations.findAnnotation(FqName("kotlin.jvm.JvmField"))
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.checkers.JvmFieldApplicabilityChecker.Problem.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
|
||||
class JvmFieldApplicabilityChecker : DeclarationChecker {
|
||||
|
||||
enum class Problem(val errorMessage: String) {
|
||||
NOT_A_PROPERTY("JvmField can only be applied to a property"),
|
||||
NOT_FINAL("JvmField can only be applied to final property"),
|
||||
CUSTOM_ACCESSOR("JvmField cannot be applied to a property with a custom accessor"),
|
||||
NO_BACKING_FIELD("JvmField can only be applied to a property with backing field"),
|
||||
OVERRIDES("JvmField cannot be applied to a property that overrides some other property"),
|
||||
LATEINIT("JvmField cannot be applied to lateinit property"),
|
||||
CONST("JvmField cannot be applied to const property"),
|
||||
INSIDE_COMPANION_OF_INTERFACE("JvmField cannot be applied to a property defined in companion object of interface"),
|
||||
TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE("JvmField cannot be applied to top level property of a file annotated with ${JvmFileClassUtil.JVM_MULTIFILE_CLASS_SHORT}")
|
||||
}
|
||||
|
||||
override fun check(
|
||||
declaration: JetDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
val annotation = descriptor.findJvmFieldAnnotation() ?: return
|
||||
|
||||
val problem = when {
|
||||
descriptor !is PropertyDescriptor -> NOT_A_PROPERTY
|
||||
descriptor.modality.isOverridable -> NOT_FINAL
|
||||
!descriptor.hasBackingField(bindingContext) -> NO_BACKING_FIELD
|
||||
descriptor.hasCustomAccessor() -> CUSTOM_ACCESSOR
|
||||
descriptor.overriddenDescriptors.isNotEmpty() -> OVERRIDES
|
||||
descriptor.isLateInit -> LATEINIT
|
||||
descriptor.isConst -> CONST
|
||||
descriptor.isInsideCompanionObjectOfInterface() -> INSIDE_COMPANION_OF_INTERFACE
|
||||
DescriptorUtils.isTopLevelDeclaration(descriptor) && declaration.isInsideJvmMultifileClassFile() ->
|
||||
TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE
|
||||
else -> return
|
||||
}
|
||||
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
|
||||
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_JVM_FIELD.on(annotationEntry, problem.errorMessage))
|
||||
}
|
||||
|
||||
private fun JetDeclaration.isInsideJvmMultifileClassFile() = JvmFileClassUtil.findAnnotationEntryOnFileNoResolve(
|
||||
getContainingJetFile(),
|
||||
JvmFileClassUtil.JVM_MULTIFILE_CLASS_SHORT
|
||||
) != null
|
||||
|
||||
private fun PropertyDescriptor.hasCustomAccessor()
|
||||
= !(getter?.isDefault ?: true) || !(setter?.isDefault ?: true)
|
||||
|
||||
private fun PropertyDescriptor.hasBackingField(bindingContext: BindingContext)
|
||||
= bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, this) ?: false
|
||||
|
||||
private fun PropertyDescriptor.isInsideCompanionObjectOfInterface(): Boolean {
|
||||
val containingClass = containingDeclaration as? ClassDescriptor ?: return false
|
||||
if (!DescriptorUtils.isCompanionObject(containingClass)) return false
|
||||
|
||||
val outerClassForObject = containingClass.containingDeclaration as? ClassDescriptor ?: return false
|
||||
return DescriptorUtils.isInterface(outerClassForObject)
|
||||
}
|
||||
}
|
||||
-22
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.findPublicFieldAnnotation
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasInlineAnnotation
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasIntrinsicAnnotation
|
||||
import org.jetbrains.kotlin.resolve.annotations.hasPlatformStaticAnnotation
|
||||
@@ -159,27 +158,6 @@ public class OverloadsAnnotationChecker: DeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
public class PublicFieldAnnotationChecker: DeclarationChecker {
|
||||
override fun check(
|
||||
declaration: JetDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
val annotation = descriptor.findPublicFieldAnnotation() ?: return
|
||||
|
||||
fun report() {
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
|
||||
diagnosticHolder.report(ErrorsJvm.INAPPLICABLE_PUBLIC_FIELD.on(annotationEntry))
|
||||
}
|
||||
|
||||
if (descriptor is PropertyDescriptor
|
||||
&& !bindingContext.get<PropertyDescriptor, Boolean>(BindingContext.BACKING_FIELD_REQUIRED, descriptor)!!) {
|
||||
report()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeParameterBoundIsNotArrayChecker : DeclarationChecker {
|
||||
override fun check(
|
||||
declaration: JetDeclaration,
|
||||
|
||||
+2
-2
@@ -74,8 +74,6 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
|
||||
MAP.put(ErrorsJvm.WHEN_ENUM_CAN_BE_NULL_IN_JAVA, "Enum argument can be null in Java, but exhaustive when contains no null branch");
|
||||
|
||||
MAP.put(ErrorsJvm.INAPPLICABLE_PUBLIC_FIELD, "publicField annotation is not applicable to this declaration");
|
||||
|
||||
MAP.put(ErrorsJvm.JAVA_CLASS_ON_COMPANION,
|
||||
"The resulting type of this ''javaClass'' call is {0} and not {1}. " +
|
||||
"Please use the more clear ''::class.java'' syntax to avoid confusion",
|
||||
@@ -88,6 +86,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
|
||||
MAP.put(ErrorsJvm.DUPLICATE_CLASS_NAMES, "Duplicate JVM class name ''{0}'' generated from: {1}", Renderers.TO_STRING, Renderers.TO_STRING);
|
||||
|
||||
MAP.put(ErrorsJvm.UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of a type parameter cannot be an array");
|
||||
|
||||
MAP.put(ErrorsJvm.INAPPLICABLE_JVM_FIELD, "{0}", Renderers.TO_STRING);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-2
@@ -48,6 +48,8 @@ public interface ErrorsJvm {
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_JVM_NAME = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetAnnotationEntry> ILLEGAL_JVM_NAME = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<JetAnnotationEntry, String> INAPPLICABLE_JVM_FIELD = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetDeclaration> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDeclaration> OVERLOADS_ABSTRACT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDeclaration> OVERLOADS_PRIVATE = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
@@ -65,8 +67,6 @@ public interface ErrorsJvm {
|
||||
|
||||
DiagnosticFactory0<JetElement> INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetElement> INAPPLICABLE_PUBLIC_FIELD = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetElement> NO_REFLECTION_IN_CLASS_PATH = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory2<JetElement, JetType, JetType> JAVA_CLASS_ON_COMPANION = DiagnosticFactory2.create(WARNING);
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
ReifiedTypeParameterAnnotationChecker(),
|
||||
NativeFunChecker(),
|
||||
OverloadsAnnotationChecker(),
|
||||
PublicFieldAnnotationChecker(),
|
||||
JvmFieldApplicabilityChecker(),
|
||||
TypeParameterBoundIsNotArrayChecker()
|
||||
),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user