Deprecated reportFromPlugin way to report diagnostics from plugin
Originally reportFromPlugin method was introduced to address the problem with loading of DefaultErrorMessages.Extension vis ServiceLoader. For some cases this extension was not loaded by ServiceLoader because classes was loaded via different class loader, common scenario here is compiler plugins. Ideally we should load such extension point via getService approach, but unfortunately to do that we need project and DefaultErrorMessages.render is static method for now. Also with reportFromPlugin approach is a problem -- all diagnostics reported via this method has the same id: PLUGIN_[WARNING|ERROR|INFO] and it isn't possible to suppress only one particular diagnostic. To bypass this problem the new method initializeFactoryNamesAndDefaultErrorMessages was introduced. It basically store DiagnosticRenderer inside DiagnosticFactory. It is not ideal, because one DiagnosticFactory could have different renderers for different scenarios -- for compiler and for IDE, but I think that it is better than reportByPlugin approach.
This commit is contained in:
@@ -17,6 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.diagnostics;
|
package org.jetbrains.kotlin.diagnostics;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -26,6 +28,8 @@ public abstract class DiagnosticFactory<D extends Diagnostic> {
|
|||||||
private String name = null;
|
private String name = null;
|
||||||
private final Severity severity;
|
private final Severity severity;
|
||||||
|
|
||||||
|
private DiagnosticRenderer<D> defaultRenderer;
|
||||||
|
|
||||||
protected DiagnosticFactory(@NotNull Severity severity) {
|
protected DiagnosticFactory(@NotNull Severity severity) {
|
||||||
this.severity = severity;
|
this.severity = severity;
|
||||||
}
|
}
|
||||||
@@ -49,6 +53,15 @@ public abstract class DiagnosticFactory<D extends Diagnostic> {
|
|||||||
return severity;
|
return severity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public DiagnosticRenderer<D> getDefaultRenderer() {
|
||||||
|
return defaultRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDefaultRenderer(@Nullable DiagnosticRenderer<D> defaultRenderer) {
|
||||||
|
this.defaultRenderer = defaultRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public D cast(@NotNull Diagnostic diagnostic) {
|
public D cast(@NotNull Diagnostic diagnostic) {
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import org.jetbrains.kotlin.config.LanguageVersion;
|
|||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
import org.jetbrains.kotlin.config.LanguageVersionSettings;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.DeclarationWithDiagnosticComponents;
|
import org.jetbrains.kotlin.diagnostics.rendering.DeclarationWithDiagnosticComponents;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
|
||||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
@@ -1157,6 +1160,14 @@ public interface Errors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void initializeFactoryNames(@NotNull Class<?> aClass) {
|
public static void initializeFactoryNames(@NotNull Class<?> aClass) {
|
||||||
|
initializeFactoryNamesAndDefaultErrorMessages(aClass, DiagnosticFactoryToRendererMap::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initializeFactoryNamesAndDefaultErrorMessages(
|
||||||
|
@NotNull Class<?> aClass,
|
||||||
|
@NotNull DefaultErrorMessages.Extension defaultErrorMessages
|
||||||
|
) {
|
||||||
|
DiagnosticFactoryToRendererMap diagnosticToRendererMap = defaultErrorMessages.getMap();
|
||||||
for (Field field : aClass.getFields()) {
|
for (Field field : aClass.getFields()) {
|
||||||
if (Modifier.isStatic(field.getModifiers())) {
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
try {
|
try {
|
||||||
@@ -1164,6 +1175,9 @@ public interface Errors {
|
|||||||
if (value instanceof DiagnosticFactory) {
|
if (value instanceof DiagnosticFactory) {
|
||||||
DiagnosticFactory<?> factory = (DiagnosticFactory<?>)value;
|
DiagnosticFactory<?> factory = (DiagnosticFactory<?>)value;
|
||||||
factory.setName(field.getName());
|
factory.setName(field.getName());
|
||||||
|
|
||||||
|
//noinspection rawtypes, unchecked
|
||||||
|
factory.setDefaultRenderer((DiagnosticRenderer) diagnosticToRendererMap.get(factory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException e) {
|
catch (IllegalAccessException e) {
|
||||||
@@ -1171,6 +1185,7 @@ public interface Errors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Initializer INSTANCE = new Initializer();
|
private static final Initializer INSTANCE = new Initializer();
|
||||||
|
|||||||
@@ -179,10 +179,17 @@ inline fun <reified T : KtDeclaration> reportOnDeclarationAs(
|
|||||||
} ?: throw AssertionError("No declaration for $descriptor")
|
} ?: throw AssertionError("No declaration for $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method should not be used in the project, but it is leaved for some time for compatibility with old compiler plugins
|
||||||
|
@Deprecated(
|
||||||
|
"Please register DefaultErrorMessages.Extension in moment of DiagnosticFactory initialization by calling " +
|
||||||
|
"initializeFactoryNamesAndDefaultErrorMessages method instead of initializeFactoryNames",
|
||||||
|
ReplaceWith("report(diagnostic)"),
|
||||||
|
level = DeprecationLevel.ERROR
|
||||||
|
)
|
||||||
fun <D : Diagnostic> DiagnosticSink.reportFromPlugin(diagnostic: D, ext: DefaultErrorMessages.Extension) {
|
fun <D : Diagnostic> DiagnosticSink.reportFromPlugin(diagnostic: D, ext: DefaultErrorMessages.Extension) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val renderer = ext.map[diagnostic.factory] as? DiagnosticRenderer<D>
|
val renderer = ext.map[diagnostic.factory] as? DiagnosticRenderer<D>
|
||||||
?: error("Renderer not found for diagnostic ${diagnostic.factory.name}")
|
?: error("Renderer not found for diagnostic ${diagnostic.factory.name}")
|
||||||
|
|
||||||
val renderedDiagnostic = RenderedDiagnostic(diagnostic, renderer)
|
val renderedDiagnostic = RenderedDiagnostic(diagnostic, renderer)
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -56,7 +56,11 @@ public class DefaultErrorMessages {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static DiagnosticRenderer getRendererForDiagnostic(@NotNull Diagnostic diagnostic) {
|
public static DiagnosticRenderer getRendererForDiagnostic(@NotNull Diagnostic diagnostic) {
|
||||||
return AddToStdlibKt.firstNotNullResult(RENDERER_MAPS, map -> map.get(diagnostic.getFactory()));
|
DiagnosticRenderer<?> renderer = AddToStdlibKt.firstNotNullResult(RENDERER_MAPS, map -> map.get(diagnostic.getFactory()));
|
||||||
|
if (renderer != null)
|
||||||
|
return renderer;
|
||||||
|
else
|
||||||
|
return diagnostic.getFactory().getDefaultRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|||||||
+10
-14
@@ -21,13 +21,11 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import kotlinx.android.parcel.IgnoredOnParcel
|
import kotlinx.android.parcel.IgnoredOnParcel
|
||||||
import kotlinx.android.parcel.TypeParceler
|
import kotlinx.android.parcel.TypeParceler
|
||||||
import kotlinx.android.parcel.WriteWith
|
import kotlinx.android.parcel.WriteWith
|
||||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid
|
|
||||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid
|
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid
|
||||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
@@ -70,12 +68,11 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
|
|
||||||
private fun checkIgnoredOnParcelUsage(annotationEntry: KtAnnotationEntry, context: CallCheckerContext, element: KtModifierListOwner) {
|
private fun checkIgnoredOnParcelUsage(annotationEntry: KtAnnotationEntry, context: CallCheckerContext, element: KtModifierListOwner) {
|
||||||
if (element is KtParameter && PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) is KtPrimaryConstructor) {
|
if (element is KtParameter && PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) is KtPrimaryConstructor) {
|
||||||
context.trace.reportFromPlugin(
|
context.trace.report(
|
||||||
ErrorsAndroid.INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY.on(annotationEntry),
|
ErrorsAndroid.INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY.on(annotationEntry)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
} else if (element !is KtProperty || PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) !is KtClass) {
|
} else if (element !is KtProperty || PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) !is KtClass) {
|
||||||
context.trace.reportFromPlugin(ErrorsAndroid.INAPPLICABLE_IGNORED_ON_PARCEL.on(annotationEntry), DefaultErrorMessagesAndroid)
|
context.trace.report(ErrorsAndroid.INAPPLICABLE_IGNORED_ON_PARCEL.on(annotationEntry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +92,7 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
|
|
||||||
if (duplicatingAnnotationCount > 1) {
|
if (duplicatingAnnotationCount > 1) {
|
||||||
val reportElement = annotationEntry.typeArguments.firstOrNull() ?: annotationEntry
|
val reportElement = annotationEntry.typeArguments.firstOrNull() ?: annotationEntry
|
||||||
context.trace.reportFromPlugin(ErrorsAndroid.DUPLICATING_TYPE_PARCELERS.on(reportElement), DefaultErrorMessagesAndroid)
|
context.trace.report(ErrorsAndroid.DUPLICATING_TYPE_PARCELERS.on(reportElement))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +112,9 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
// We can ignore value arguments here cause @TypeParceler is a zero-parameter annotation
|
// We can ignore value arguments here cause @TypeParceler is a zero-parameter annotation
|
||||||
if (containingClassDescriptor.annotations.any { it.type == thisAnnotationDescriptor.type }) {
|
if (containingClassDescriptor.annotations.any { it.type == thisAnnotationDescriptor.type }) {
|
||||||
val reportElement = (annotationEntry.typeReference?.typeElement as? KtUserType)?.referenceExpression ?: annotationEntry
|
val reportElement = (annotationEntry.typeReference?.typeElement as? KtUserType)?.referenceExpression ?: annotationEntry
|
||||||
context.trace.reportFromPlugin(
|
context.trace.report(
|
||||||
ErrorsAndroid.REDUNDANT_TYPE_PARCELER.on(reportElement, containingClass), DefaultErrorMessagesAndroid)
|
ErrorsAndroid.REDUNDANT_TYPE_PARCELER.on(reportElement, containingClass)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +139,7 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
fun reportElement() = annotationEntry.typeArguments.singleOrNull() ?: annotationEntry
|
fun reportElement() = annotationEntry.typeArguments.singleOrNull() ?: annotationEntry
|
||||||
|
|
||||||
if (parcelerClass.kind != ClassKind.OBJECT) {
|
if (parcelerClass.kind != ClassKind.OBJECT) {
|
||||||
context.trace.reportFromPlugin(ErrorsAndroid.PARCELER_SHOULD_BE_OBJECT.on(reportElement()), DefaultErrorMessagesAndroid)
|
context.trace.report(ErrorsAndroid.PARCELER_SHOULD_BE_OBJECT.on(reportElement()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +148,7 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
val expectedType = parcelerSuperType.arguments.singleOrNull()?.type ?: return
|
val expectedType = parcelerSuperType.arguments.singleOrNull()?.type ?: return
|
||||||
|
|
||||||
if (!actualType.isSubtypeOf(expectedType)) {
|
if (!actualType.isSubtypeOf(expectedType)) {
|
||||||
context.trace.reportFromPlugin(ErrorsAndroid.PARCELER_TYPE_INCOMPATIBLE.on(reportElement(), expectedType, actualType),
|
context.trace.report(ErrorsAndroid.PARCELER_TYPE_INCOMPATIBLE.on(reportElement(), expectedType, actualType))
|
||||||
DefaultErrorMessagesAndroid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +161,7 @@ class ParcelableAnnotationChecker : CallChecker {
|
|||||||
val containingClassDescriptor = context.trace[BindingContext.CLASS, containingClass]
|
val containingClassDescriptor = context.trace[BindingContext.CLASS, containingClass]
|
||||||
if (containingClassDescriptor != null && !containingClassDescriptor.isParcelize) {
|
if (containingClassDescriptor != null && !containingClassDescriptor.isParcelize) {
|
||||||
val reportElement = (annotationEntry.typeReference?.typeElement as? KtUserType)?.referenceExpression ?: annotationEntry
|
val reportElement = (annotationEntry.typeReference?.typeElement as? KtUserType)?.referenceExpression ?: annotationEntry
|
||||||
context.trace.reportFromPlugin(ErrorsAndroid.CLASS_SHOULD_BE_PARCELIZE.on(reportElement, containingClass),
|
context.trace.report(ErrorsAndroid.CLASS_SHOULD_BE_PARCELIZE.on(reportElement, containingClass))
|
||||||
DefaultErrorMessagesAndroid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-34
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.android.parcel
|
|||||||
import kotlinx.android.parcel.IgnoredOnParcel
|
import kotlinx.android.parcel.IgnoredOnParcel
|
||||||
import org.jetbrains.kotlin.android.parcel.serializers.ParcelSerializer
|
import org.jetbrains.kotlin.android.parcel.serializers.ParcelSerializer
|
||||||
import org.jetbrains.kotlin.android.parcel.serializers.isParcelable
|
import org.jetbrains.kotlin.android.parcel.serializers.isParcelable
|
||||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid
|
|
||||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid
|
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
import org.jetbrains.kotlin.codegen.FrameMap
|
import org.jetbrains.kotlin.codegen.FrameMap
|
||||||
@@ -20,7 +19,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -76,9 +74,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
if (method.isWriteToParcel() && declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
|
if (method.isWriteToParcel() && declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
|
||||||
val reportElement =
|
val reportElement =
|
||||||
declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: declaration.nameIdentifier ?: declaration
|
declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED.on(reportElement),
|
ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +98,7 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
&& !hasIgnoredOnParcel()
|
&& !hasIgnoredOnParcel()
|
||||||
) {
|
) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.PROPERTY_WONT_BE_SERIALIZED.on(reportElement), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.PROPERTY_WONT_BE_SERIALIZED.on(reportElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
// @JvmName is not applicable to property so we can check just the descriptor name
|
// @JvmName is not applicable to property so we can check just the descriptor name
|
||||||
@@ -109,9 +106,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
val outerClass = containingClass.containingDeclaration as? ClassDescriptor
|
val outerClass = containingClass.containingDeclaration as? ClassDescriptor
|
||||||
if (outerClass != null && outerClass.isParcelize) {
|
if (outerClass != null && outerClass.isParcelize) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED.on(reportElement),
|
ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,22 +123,21 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
if (!descriptor.isParcelize) return
|
if (!descriptor.isParcelize) return
|
||||||
|
|
||||||
if (declaration !is KtClassOrObject) {
|
if (declaration !is KtClassOrObject) {
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(declaration), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(declaration))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is KtClass && (declaration.isAnnotation() || declaration.isInterface())) {
|
if (declaration is KtClass && (declaration.isAnnotation() || declaration.isInterface())) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(reportElement), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(reportElement))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (companion in declaration.companionObjects) {
|
for (companion in declaration.companionObjects) {
|
||||||
if (companion.name == "CREATOR") {
|
if (companion.name == "CREATOR") {
|
||||||
val reportElement = companion.nameIdentifier ?: companion
|
val reportElement = companion.nameIdentifier ?: companion
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED.on(reportElement),
|
ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,26 +145,25 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
val sealedOrAbstract =
|
val sealedOrAbstract =
|
||||||
declaration.modifierList?.let { it.getModifier(KtTokens.ABSTRACT_KEYWORD) ?: it.getModifier(KtTokens.SEALED_KEYWORD) }
|
declaration.modifierList?.let { it.getModifier(KtTokens.ABSTRACT_KEYWORD) ?: it.getModifier(KtTokens.SEALED_KEYWORD) }
|
||||||
if (sealedOrAbstract != null) {
|
if (sealedOrAbstract != null) {
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_SHOULD_BE_INSTANTIABLE.on(sealedOrAbstract),
|
ErrorsAndroid.PARCELABLE_SHOULD_BE_INSTANTIABLE.on(sealedOrAbstract)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is KtClass && declaration.isInner()) {
|
if (declaration is KtClass && declaration.isInner()) {
|
||||||
val reportElement = declaration.modifierList?.getModifier(KtTokens.INNER_KEYWORD) ?: declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.modifierList?.getModifier(KtTokens.INNER_KEYWORD) ?: declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.PARCELABLE_CANT_BE_INNER_CLASS.on(reportElement), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.PARCELABLE_CANT_BE_INNER_CLASS.on(reportElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.isLocal) {
|
if (declaration.isLocal) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.PARCELABLE_CANT_BE_LOCAL_CLASS.on(reportElement), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.PARCELABLE_CANT_BE_LOCAL_CLASS.on(reportElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
val superTypes = TypeUtils.getAllSupertypes(descriptor.defaultType)
|
val superTypes = TypeUtils.getAllSupertypes(descriptor.defaultType)
|
||||||
if (superTypes.none { it.constructor.declarationDescriptor?.fqNameSafe == ANDROID_PARCELABLE_CLASS_FQNAME }) {
|
if (superTypes.none { it.constructor.declarationDescriptor?.fqNameSafe == ANDROID_PARCELABLE_CLASS_FQNAME }) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(ErrorsAndroid.NO_PARCELABLE_SUPERTYPE.on(reportElement), DefaultErrorMessagesAndroid)
|
diagnosticHolder.report(ErrorsAndroid.NO_PARCELABLE_SUPERTYPE.on(reportElement))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (supertypeEntry in declaration.superTypeListEntries) {
|
for (supertypeEntry in declaration.superTypeListEntries) {
|
||||||
@@ -178,9 +172,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
val type = bindingContext[BindingContext.TYPE, supertypeEntry.typeReference] ?: continue
|
val type = bindingContext[BindingContext.TYPE, supertypeEntry.typeReference] ?: continue
|
||||||
if (type.isParcelable()) {
|
if (type.isParcelable()) {
|
||||||
val reportElement = supertypeEntry.byKeywordNode?.psi ?: delegateExpression
|
val reportElement = supertypeEntry.byKeywordNode?.psi ?: delegateExpression
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_DELEGATE_IS_NOT_ALLOWED.on(reportElement),
|
ErrorsAndroid.PARCELABLE_DELEGATE_IS_NOT_ALLOWED.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,15 +181,13 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
val primaryConstructor = declaration.primaryConstructor
|
val primaryConstructor = declaration.primaryConstructor
|
||||||
if (primaryConstructor == null && declaration.secondaryConstructors.isNotEmpty()) {
|
if (primaryConstructor == null && declaration.secondaryConstructors.isNotEmpty()) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR.on(reportElement),
|
ErrorsAndroid.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
} else if (primaryConstructor != null && primaryConstructor.valueParameters.isEmpty()) {
|
} else if (primaryConstructor != null && primaryConstructor.valueParameters.isEmpty()) {
|
||||||
val reportElement = declaration.nameIdentifier ?: declaration
|
val reportElement = declaration.nameIdentifier ?: declaration
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY.on(reportElement),
|
ErrorsAndroid.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,8 +211,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
) {
|
) {
|
||||||
if (!parameter.hasValOrVar()) {
|
if (!parameter.hasValOrVar()) {
|
||||||
val reportElement = parameter.nameIdentifier ?: parameter
|
val reportElement = parameter.nameIdentifier ?: parameter
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR.on(reportElement), DefaultErrorMessagesAndroid
|
ErrorsAndroid.PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR.on(reportElement)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,9 +235,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
|
|||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
// get() throws IllegalArgumentException on unknown types
|
// get() throws IllegalArgumentException on unknown types
|
||||||
val reportElement = parameter.typeReference ?: parameter.nameIdentifier ?: parameter
|
val reportElement = parameter.typeReference ?: parameter.nameIdentifier ?: parameter
|
||||||
diagnosticHolder.reportFromPlugin(
|
diagnosticHolder.report(
|
||||||
ErrorsAndroid.PARCELABLE_TYPE_NOT_SUPPORTED.on(reportElement),
|
ErrorsAndroid.PARCELABLE_TYPE_NOT_SUPPORTED.on(reportElement)
|
||||||
DefaultErrorMessagesAndroid
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
|||||||
import org.jetbrains.kotlin.android.synthetic.res.isErrorType
|
import org.jetbrains.kotlin.android.synthetic.res.isErrorType
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
|
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
@@ -51,7 +50,7 @@ class AndroidExtensionPropertiesCallChecker : CallChecker {
|
|||||||
|
|
||||||
private fun DiagnosticSink.checkDeprecated(expression: KtExpression, packageDescriptor: AndroidSyntheticPackageFragmentDescriptor) {
|
private fun DiagnosticSink.checkDeprecated(expression: KtExpression, packageDescriptor: AndroidSyntheticPackageFragmentDescriptor) {
|
||||||
if (packageDescriptor.packageData.isDeprecated) {
|
if (packageDescriptor.packageData.isDeprecated) {
|
||||||
reportFromPlugin(SYNTHETIC_DEPRECATED_PACKAGE.on(expression), DefaultErrorMessagesAndroid)
|
report(SYNTHETIC_DEPRECATED_PACKAGE.on(expression))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +59,7 @@ class AndroidExtensionPropertiesCallChecker : CallChecker {
|
|||||||
val type = property.errorType ?: return
|
val type = property.errorType ?: return
|
||||||
|
|
||||||
val warning = if (type.contains('.')) SYNTHETIC_UNRESOLVED_WIDGET_TYPE else SYNTHETIC_INVALID_WIDGET_TYPE
|
val warning = if (type.contains('.')) SYNTHETIC_UNRESOLVED_WIDGET_TYPE else SYNTHETIC_INVALID_WIDGET_TYPE
|
||||||
reportFromPlugin(warning.on(expression, type), DefaultErrorMessagesAndroid)
|
report(warning.on(expression, type))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticSink.checkPartiallyDefinedResource(
|
private fun DiagnosticSink.checkPartiallyDefinedResource(
|
||||||
@@ -73,7 +72,7 @@ class AndroidExtensionPropertiesCallChecker : CallChecker {
|
|||||||
|
|
||||||
val expectedType = context.resolutionContext.expectedType
|
val expectedType = context.resolutionContext.expectedType
|
||||||
if (!TypeUtils.noExpectedType(expectedType) && !expectedType.isMarkedNullable && !expectedType.isFlexible()) {
|
if (!TypeUtils.noExpectedType(expectedType) && !expectedType.isMarkedNullable && !expectedType.isFlexible()) {
|
||||||
reportFromPlugin(UNSAFE_CALL_ON_PARTIALLY_DEFINED_RESOURCE.on(calleeExpression), DefaultErrorMessagesAndroid)
|
report(UNSAFE_CALL_ON_PARTIALLY_DEFINED_RESOURCE.on(calleeExpression))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +80,7 @@ class AndroidExtensionPropertiesCallChecker : CallChecker {
|
|||||||
val usage = outermostQualifiedExpression.parent
|
val usage = outermostQualifiedExpression.parent
|
||||||
|
|
||||||
if (usage is KtDotQualifiedExpression && usage.receiverExpression == outermostQualifiedExpression) {
|
if (usage is KtDotQualifiedExpression && usage.receiverExpression == outermostQualifiedExpression) {
|
||||||
reportFromPlugin(UNSAFE_CALL_ON_PARTIALLY_DEFINED_RESOURCE.on(calleeExpression), DefaultErrorMessagesAndroid)
|
report(UNSAFE_CALL_ON_PARTIALLY_DEFINED_RESOURCE.on(calleeExpression))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
|
|||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry;
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
@@ -62,7 +60,7 @@ public interface ErrorsAndroid {
|
|||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
{
|
{
|
||||||
Errors.Initializer.initializeFactoryNames(ErrorsAndroid.class);
|
Errors.Initializer.initializeFactoryNamesAndDefaultErrorMessages(ErrorsAndroid.class, DefaultErrorMessagesAndroid.INSTANCE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -35,8 +35,8 @@ public interface SerializationErrors {
|
|||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
{
|
{
|
||||||
Errors.Initializer.initializeFactoryNames(SerializationErrors.class);
|
Errors.Initializer
|
||||||
|
.initializeFactoryNamesAndDefaultErrorMessages(SerializationErrors.class, SerializationPluginErrorsRendering.INSTANCE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-31
@@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||||
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
|
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
@@ -45,10 +44,7 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
private fun canBeSerializedInternally(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace): Boolean {
|
private fun canBeSerializedInternally(descriptor: ClassDescriptor, declaration: KtDeclaration, trace: BindingTrace): Boolean {
|
||||||
if (descriptor.isSerializableEnumWithMissingSerializer()) {
|
if (descriptor.isSerializableEnumWithMissingSerializer()) {
|
||||||
val declarationToReport = declaration.modifierList ?: declaration
|
val declarationToReport = declaration.modifierList ?: declaration
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.EXPLICIT_SERIALIZABLE_IS_REQUIRED.on(declarationToReport))
|
||||||
SerializationErrors.EXPLICIT_SERIALIZABLE_IS_REQUIRED.on(declarationToReport),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,10 +107,7 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
props.serializableProperties.forEach {
|
props.serializableProperties.forEach {
|
||||||
if (!namesSet.add(it.name)) {
|
if (!namesSet.add(it.name)) {
|
||||||
descriptor.safeReport { a ->
|
descriptor.safeReport { a ->
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.DUPLICATE_SERIAL_NAME.on(a, it.name))
|
||||||
SerializationErrors.DUPLICATE_SERIAL_NAME.on(a, it.name),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,17 +129,11 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
if (!hasBackingField && isMarkedTransient) {
|
if (!hasBackingField && isMarkedTransient) {
|
||||||
val transientPsi =
|
val transientPsi =
|
||||||
(descriptor.annotations.findAnnotation(SerializationAnnotations.serialTransientFqName) as? LazyAnnotationDescriptor)?.annotationEntry
|
(descriptor.annotations.findAnnotation(SerializationAnnotations.serialTransientFqName) as? LazyAnnotationDescriptor)?.annotationEntry
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.TRANSIENT_IS_REDUNDANT.on(transientPsi ?: declaration))
|
||||||
SerializationErrors.TRANSIENT_IS_REDUNDANT.on(transientPsi ?: declaration),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMarkedTransient && !isInitialized && hasBackingField) {
|
if (isMarkedTransient && !isInitialized && hasBackingField) {
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.TRANSIENT_MISSING_INITIALIZER.on(declaration))
|
||||||
SerializationErrors.TRANSIENT_MISSING_INITIALIZER.on(declaration),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,20 +190,14 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
if (type.genericIndex != null) return // type arguments always have serializer stored in class' field
|
if (type.genericIndex != null) return // type arguments always have serializer stored in class' field
|
||||||
val element = ktType?.typeElement
|
val element = ktType?.typeElement
|
||||||
if (type.isUnsupportedInlineType()) {
|
if (type.isUnsupportedInlineType()) {
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED.on(element ?: fallbackElement))
|
||||||
SerializationErrors.INLINE_CLASSES_NOT_SUPPORTED.on(element ?: fallbackElement),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
val serializer = findTypeSerializerOrContextUnchecked(module, type)
|
val serializer = findTypeSerializerOrContextUnchecked(module, type)
|
||||||
if (serializer != null) {
|
if (serializer != null) {
|
||||||
checkSerializerNullability(type, serializer.defaultType, element, trace, fallbackElement)
|
checkSerializerNullability(type, serializer.defaultType, element, trace, fallbackElement)
|
||||||
checkTypeArguments(module, type, element, trace, fallbackElement)
|
checkTypeArguments(module, type, element, trace, fallbackElement)
|
||||||
} else {
|
} else {
|
||||||
trace.reportFromPlugin(
|
trace.report(SerializationErrors.SERIALIZER_NOT_FOUND.on(element ?: fallbackElement, type))
|
||||||
SerializationErrors.SERIALIZER_NOT_FOUND.on(element ?: fallbackElement, type),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,9 +212,8 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
val castedToKSerial = serializerType.supertypes().find { isKSerializer(it) } ?: return
|
val castedToKSerial = serializerType.supertypes().find { isKSerializer(it) } ?: return
|
||||||
|
|
||||||
if (!classType.isMarkedNullable && castedToKSerial.arguments.first().type.isMarkedNullable)
|
if (!classType.isMarkedNullable && castedToKSerial.arguments.first().type.isMarkedNullable)
|
||||||
trace.reportFromPlugin(
|
trace.report(
|
||||||
SerializationErrors.SERIALIZER_NULLABILITY_INCOMPATIBLE.on(element ?: fallbackElement, serializerType, classType),
|
SerializationErrors.SERIALIZER_NULLABILITY_INCOMPATIBLE.on(element ?: fallbackElement, serializerType, classType),
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,10 +223,7 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
|
|||||||
|
|
||||||
private fun BindingTrace.reportOnSerializableAnnotation(descriptor: ClassDescriptor, error: DiagnosticFactory0<in KtAnnotationEntry>) {
|
private fun BindingTrace.reportOnSerializableAnnotation(descriptor: ClassDescriptor, error: DiagnosticFactory0<in KtAnnotationEntry>) {
|
||||||
descriptor.safeReport { e ->
|
descriptor.safeReport { e ->
|
||||||
reportFromPlugin(
|
report(error.on(e))
|
||||||
error.on(e),
|
|
||||||
SerializationPluginErrorsRendering
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,5 +6,5 @@ import kotlinx.serialization.*
|
|||||||
@Serializable
|
@Serializable
|
||||||
open class Parent(open val arg: Int)
|
open class Parent(open val arg: Int)
|
||||||
|
|
||||||
<!PLUGIN_ERROR("Serializable class has duplicate serial name of property 'arg', either in the class itself or its supertypes")!>@Serializable<!>
|
<!DUPLICATE_SERIAL_NAME("arg")!>@Serializable<!>
|
||||||
class Derived(override val arg: Int): Parent(arg)
|
class Derived(override val arg: Int): Parent(arg)
|
||||||
|
|||||||
+1
-1
@@ -5,5 +5,5 @@ import kotlinx.serialization.*
|
|||||||
|
|
||||||
open class NonSerializableParent(val arg: Int)
|
open class NonSerializableParent(val arg: Int)
|
||||||
|
|
||||||
<!PLUGIN_ERROR("Impossible to make this class serializable because its parent is not serializable and does not have exactly one constructor without parameters")!>@Serializable<!>
|
<!NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR!>@Serializable<!>
|
||||||
class Derived(val someData: String): NonSerializableParent(42)
|
class Derived(val someData: String): NonSerializableParent(42)
|
||||||
|
|||||||
Vendored
+3
-3
@@ -6,12 +6,12 @@ import kotlinx.serialization.*
|
|||||||
class NonSerializable
|
class NonSerializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class Basic(val foo: <!PLUGIN_ERROR("Serializer has not been found for type 'NonSerializable'. To use context serializer as fallback, explicitly annotate type or property with @ContextualSerialization")!>NonSerializable<!>)
|
class Basic(val foo: <!SERIALIZER_NOT_FOUND("NonSerializable")!>NonSerializable<!>)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class Inside(val foo: List<<!PLUGIN_ERROR("Serializer has not been found for type 'NonSerializable'. To use context serializer as fallback, explicitly annotate type or property with @ContextualSerialization")!>NonSerializable<!>>)
|
class Inside(val foo: List<<!SERIALIZER_NOT_FOUND("NonSerializable")!>NonSerializable<!>>)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class WithImplicitType {
|
class WithImplicitType {
|
||||||
<!PLUGIN_ERROR("Serializer has not been found for type 'NonSerializable'. To use context serializer as fallback, explicitly annotate type or property with @ContextualSerialization")!>val foo = NonSerializable()<!>
|
<!SERIALIZER_NOT_FOUND("NonSerializable")!>val foo = NonSerializable()<!>
|
||||||
}
|
}
|
||||||
+1
-1
@@ -13,4 +13,4 @@ class NopeNullableSerializer: KSerializer<Nope?> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class Foo(val foo: <!PLUGIN_ERROR("Type 'Nope' is non-nullable and therefore can not be serialized with serializer for nullable type 'NopeNullableSerializer'")!>Nope<!>)
|
class Foo(val foo: <!SERIALIZER_NULLABILITY_INCOMPATIBLE("NopeNullableSerializer", "Nope")!>Nope<!>)
|
||||||
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
<!PLUGIN_ERROR("This class is not serializable automatically because it has primary constructor parameters of which are not properties")!>@Serializable<!>
|
<!PRIMARY_CONSTRUCTOR_PARAMETER_IS_NOT_A_PROPERTY!>@Serializable<!>
|
||||||
class Test(val someData: String, cantBeDeserialized: Int)
|
class Test(val someData: String, cantBeDeserialized: Int)
|
||||||
|
|||||||
plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.kt
Vendored
+2
-2
@@ -5,9 +5,9 @@ import kotlinx.serialization.*
|
|||||||
|
|
||||||
enum class SimpleEnum { A, B }
|
enum class SimpleEnum { A, B }
|
||||||
|
|
||||||
<!PLUGIN_WARNING("Explicit @Serializable annotation on enum class is required when @SerialName or @SerialInfo annotations are used on its members.")!>enum<!> class MarkedNameEnum { @SerialName("a") A, B}
|
<!EXPLICIT_SERIALIZABLE_IS_REQUIRED!>enum<!> class MarkedNameEnum { @SerialName("a") A, B}
|
||||||
|
|
||||||
<!PLUGIN_WARNING("Explicit @Serializable annotation on enum class is required when @SerialName or @SerialInfo annotations are used on its members.")!>enum<!> class MarkedInfoEnum { @SerialId(10) A, B}
|
<!EXPLICIT_SERIALIZABLE_IS_REQUIRED!>enum<!> class MarkedInfoEnum { @SerialId(10) A, B}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class ExplicitlyMarkedEnum { @SerialId(10) A, B}
|
enum class ExplicitlyMarkedEnum { @SerialId(10) A, B}
|
||||||
|
|||||||
+1
-1
@@ -3,5 +3,5 @@
|
|||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
<!PLUGIN_ERROR("@Serializable annotation is ignored because it is impossible to serialize automatically interfaces or enums. Provide serializer manually via e.g. companion object")!>@Serializable<!>
|
<!SERIALIZABLE_ANNOTATION_IGNORED!>@Serializable<!>
|
||||||
interface INonSerializable
|
interface INonSerializable
|
||||||
|
|||||||
Vendored
+2
-2
@@ -4,8 +4,8 @@
|
|||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class WithTransients(<!PLUGIN_ERROR("This property is marked as @Transient and therefore must have an initializing expression")!>@Transient val missing: Int<!>) {
|
data class WithTransients(<!TRANSIENT_MISSING_INITIALIZER!>@Transient val missing: Int<!>) {
|
||||||
<!PLUGIN_WARNING("Property does not have backing field which makes it non-serializable and therefore @Transient is redundant")!>@Transient<!> val redundant: Int get() = 42
|
<!TRANSIENT_IS_REDUNDANT!>@Transient<!> val redundant: Int get() = 42
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var allowTransientLateinitWithoutInitializer: String
|
lateinit var allowTransientLateinitWithoutInitializer: String
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.noarg.diagnostic
|
package org.jetbrains.kotlin.noarg.diagnostic
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.reportFromPlugin
|
|
||||||
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
|
import org.jetbrains.kotlin.extensions.AnnotationBasedExtension
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
@@ -40,7 +39,7 @@ abstract class AbstractNoArgDeclarationChecker : DeclarationChecker, AnnotationB
|
|||||||
val superClass = descriptor.getSuperClassOrAny()
|
val superClass = descriptor.getSuperClassOrAny()
|
||||||
if (superClass.constructors.none { it.isNoArgConstructor() } && !superClass.hasSpecialAnnotation(declaration)) {
|
if (superClass.constructors.none { it.isNoArgConstructor() } && !superClass.hasSpecialAnnotation(declaration)) {
|
||||||
val reportTarget = declaration.nameIdentifier ?: declaration.getClassOrInterfaceKeyword() ?: declaration
|
val reportTarget = declaration.nameIdentifier ?: declaration.getClassOrInterfaceKeyword() ?: declaration
|
||||||
context.trace.reportFromPlugin(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(reportTarget), DefaultErrorMessagesNoArg)
|
context.trace.report(ErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS.on(reportTarget))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public interface ErrorsNoArg {
|
|||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
{
|
{
|
||||||
Errors.Initializer.initializeFactoryNames(ErrorsNoArg.class);
|
Errors.Initializer.initializeFactoryNamesAndDefaultErrorMessages(ErrorsNoArg.class, DefaultErrorMessagesNoArg.INSTANCE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user