Added diagnostic for external serializers
Relates Kotlin/kotlinx.serialization#532
This commit is contained in:
+3
@@ -42,6 +42,9 @@ public interface SerializationErrors {
|
||||
|
||||
DiagnosticFactory2<PsiElement, KotlinType, KotlinType> INCONSISTENT_INHERITABLE_SERIALINFO = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory2<PsiElement, KotlinType, KotlinType> EXTERNAL_CLASS_NOT_SERIALIZABLE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, KotlinType, KotlinType> EXTERNAL_CLASS_IN_ANOTHER_MODULE = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
+17
@@ -41,6 +41,8 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
||||
final override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
|
||||
checkExternalSerializer(descriptor, declaration, context.trace)
|
||||
|
||||
if (!canBeSerializedInternally(descriptor, declaration, context.trace)) return
|
||||
if (declaration !is KtPureClassOrObject) return
|
||||
if (!isIde) {
|
||||
@@ -58,6 +60,21 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
||||
checkInheritedAnnotations(descriptor, declaration, context.trace)
|
||||
}
|
||||
|
||||
private fun checkExternalSerializer(classDescriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace) {
|
||||
val serializableKType = classDescriptor.serializerForClass ?: return
|
||||
val serializableDescriptor = serializableKType.toClassDescriptor ?: return
|
||||
val props = SerializableProperties(serializableDescriptor, trace.bindingContext)
|
||||
|
||||
if (!props.isExternallySerializable) {
|
||||
val entry = classDescriptor.findAnnotationDeclaration(SerializationAnnotations.serializerAnnotationFqName)
|
||||
val inSameModule =
|
||||
trace.bindingContext[BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, serializableDescriptor.fqNameUnsafe] != null
|
||||
val diagnostic = if (inSameModule) SerializationErrors.EXTERNAL_CLASS_NOT_SERIALIZABLE else SerializationErrors.EXTERNAL_CLASS_IN_ANOTHER_MODULE
|
||||
|
||||
trace.report(diagnostic.on(entry ?: declaration, classDescriptor.defaultType, serializableKType))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkInheritedAnnotations(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace) {
|
||||
val annotationsFilter: (Annotations) -> List<Pair<FqName, AnnotationDescriptor>> = { an ->
|
||||
an.map { it.annotationClass!!.fqNameSafe to it }
|
||||
|
||||
+14
@@ -124,5 +124,19 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension {
|
||||
Renderers.RENDER_TYPE,
|
||||
Renderers.RENDER_TYPE
|
||||
)
|
||||
|
||||
MAP.put(
|
||||
SerializationErrors.EXTERNAL_CLASS_NOT_SERIALIZABLE,
|
||||
"Cannot generate external serializer ''{0}'': class ''{1}'' have constructor parameters which are not properties and therefore it is not serializable automatically",
|
||||
Renderers.RENDER_TYPE,
|
||||
Renderers.RENDER_TYPE
|
||||
)
|
||||
|
||||
MAP.put(
|
||||
SerializationErrors.EXTERNAL_CLASS_IN_ANOTHER_MODULE,
|
||||
"Cannot generate external serializer ''{0}'': class ''{1}'' is defined in another module",
|
||||
Renderers.RENDER_TYPE,
|
||||
Renderers.RENDER_TYPE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -198,6 +198,11 @@ internal fun Annotated.findSerializableOrMetaAnnotationDeclaration(): KtAnnotati
|
||||
return lazyDesc?.annotationEntry
|
||||
}
|
||||
|
||||
internal fun Annotated.findAnnotationDeclaration(fqName: FqName): KtAnnotationEntry? {
|
||||
val lazyDesc = annotations.findAnnotation(fqName) as? LazyAnnotationDescriptor
|
||||
return lazyDesc?.annotationEntry
|
||||
}
|
||||
|
||||
// For abstract classes marked with @Serializable,
|
||||
// methods are generated anyway, although they shouldn't have
|
||||
// generated $serializer and use Polymorphic one.
|
||||
|
||||
+5
@@ -34,6 +34,11 @@ public class SerializationPluginDiagnosticTestGenerated extends AbstractSerializ
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ExternalSerializers.kt")
|
||||
public void testExternalSerializers() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ExternalSerializers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("IncorrectTransient.kt")
|
||||
public void testIncorrectTransient() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/IncorrectTransient.kt");
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE, -OPT_IN_USAGE
|
||||
// SKIP_TXT
|
||||
|
||||
// FILE: test.kt
|
||||
import kotlinx.serialization.*
|
||||
|
||||
class Foo(i: Int, val j: Int)
|
||||
|
||||
<!EXTERNAL_CLASS_NOT_SERIALIZABLE!>@Serializer(forClass = Foo::class)<!>
|
||||
object ExternalSerializer
|
||||
Reference in New Issue
Block a user