Add IDE diagnostic on @Serializable classes for non-applied serialization plugin

This commit is contained in:
Leonid Startsev
2019-06-25 14:44:56 +03:00
parent fb94cb141f
commit a3218da1c3
5 changed files with 39 additions and 4 deletions
@@ -18,6 +18,7 @@ import static org.jetbrains.kotlin.diagnostics.Severity.WARNING;
public interface SerializationErrors {
DiagnosticFactory0<PsiElement> INLINE_CLASSES_NOT_SUPPORTED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> PLUGIN_IS_NOT_ENABLED = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> SERIALIZABLE_ANNOTATION_IGNORED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR = DiagnosticFactory0.create(ERROR);
@@ -33,8 +33,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
internal val SERIALIZABLE_PROPERTIES: WritableSlice<ClassDescriptor, SerializableProperties> = Slices.createSimpleSlice()
class SerializationPluginDeclarationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
open class SerializationPluginDeclarationChecker : DeclarationChecker {
final override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is ClassDescriptor) return
if (!canBeSerializedInternally(descriptor, context.trace)) return
@@ -47,6 +47,11 @@ class SerializationPluginDeclarationChecker : DeclarationChecker {
private fun canBeSerializedInternally(descriptor: ClassDescriptor, trace: BindingTrace): Boolean {
if (!descriptor.annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)) return false
if (!serializationPluginEnabledOn(descriptor)) {
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.PLUGIN_IS_NOT_ENABLED)
return false
}
if (descriptor.isInline) {
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED)
return false
@@ -67,6 +72,13 @@ class SerializationPluginDeclarationChecker : DeclarationChecker {
return true
}
open fun serializationPluginEnabledOn(descriptor: ClassDescriptor): Boolean {
// In the CLI/Gradle compiler, this diagnostic is located in the plugin itself.
// Therefore, if we are here, plugin is in the compile classpath and enabled.
// For the IDE case, see SerializationPluginIDEDeclarationChecker
return true
}
private fun buildSerializableProperties(descriptor: ClassDescriptor, trace: BindingTrace): SerializableProperties? {
if (!descriptor.annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)) return null
if (!descriptor.isInternalSerializable) return null
@@ -18,6 +18,11 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension {
SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED,
"Inline classes are not supported by kotlinx.serialization yet"
)
MAP.put(
SerializationErrors.PLUGIN_IS_NOT_ENABLED,
"kotlinx.serialization compiler plugin is not applied to the module, so this annotation would not be processed. " +
"Make sure that you've setup your buildscript correctly and re-import project."
)
MAP.put(
SerializationErrors.SERIALIZABLE_ANNOTATION_IGNORED,
"@Serializable annotation is ignored because it is impossible to serialize automatically interfaces or enums. " +
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlinx.serialization.compiler.diagnostic
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlinx.serialization.idea.getIfEnabledOn
class SerializationPluginIDEDeclarationChecker : SerializationPluginDeclarationChecker() {
override fun serializationPluginEnabledOn(descriptor: ClassDescriptor): Boolean {
// In the IDE, plugin is always in the classpath, but enabled only if corresponding compiler settings
// were imported into project model from Gradle.
return getIfEnabledOn(descriptor) { true } == true
}
}
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationPluginDeclarationChecker
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationPluginIDEDeclarationChecker
class SerializationIDEContainerContributor : StorageComponentContainerContributor {
override fun registerModuleComponents(
@@ -18,6 +18,6 @@ class SerializationIDEContainerContributor : StorageComponentContainerContributo
platform: TargetPlatform,
moduleDescriptor: ModuleDescriptor
) {
container.useInstance(SerializationPluginDeclarationChecker())
container.useInstance(SerializationPluginIDEDeclarationChecker())
}
}