[Parcelize] Reorganize module structure of Parcelize plugin
Also mark parcelize as compatible with K2
This commit is contained in:
committed by
teamcity
parent
2a7dc1cc0c
commit
259862d294
@@ -0,0 +1,30 @@
|
||||
description = "Parcelize compiler plugin (Backend)"
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":plugins:parcelize:parcelize-compiler:parcelize.common"))
|
||||
|
||||
compileOnly(intellijCore())
|
||||
compileOnly(project(":compiler:fir:cones"))
|
||||
compileOnly(project(":compiler:fir:tree"))
|
||||
compileOnly(project(":compiler:fir:resolve"))
|
||||
compileOnly(project(":compiler:fir:checkers"))
|
||||
compileOnly(project(":compiler:fir:checkers:checkers.jvm"))
|
||||
compileOnly(project(":compiler:ir.backend.common"))
|
||||
compileOnly(project(":compiler:ir.tree.impl"))
|
||||
compileOnly(project(":compiler:fir:entrypoint"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
|
||||
runtimeJar()
|
||||
javadocJar()
|
||||
sourcesJar()
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnnotationCallChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.*
|
||||
|
||||
class FirParcelizeCheckersExtension(session: FirSession) : FirAdditionalCheckersExtension(session) {
|
||||
override val expressionCheckers: ExpressionCheckers = object : ExpressionCheckers() {
|
||||
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||
get() = setOf(FirParcelizeAnnotationChecker)
|
||||
}
|
||||
|
||||
override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() {
|
||||
override val classCheckers: Set<FirClassChecker>
|
||||
get() = setOf(FirParcelizeClassChecker)
|
||||
|
||||
override val propertyCheckers: Set<FirPropertyChecker>
|
||||
get() = setOf(FirParcelizePropertyChecker)
|
||||
|
||||
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
|
||||
get() = setOf(FirParcelizeFunctionChecker)
|
||||
|
||||
override val constructorCheckers: Set<FirConstructorChecker>
|
||||
get() = setOf(FirParcelizeConstructorChecker)
|
||||
}
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPluginKey
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.predicate.has
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.isInt
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.DESCRIBE_CONTENTS_NAME
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.DEST_NAME
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.FLAGS_NAME
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.OLD_PARCELIZE_FQN
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELIZE_FQN
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCEL_ID
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.WRITE_TO_PARCEL_NAME
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
class FirParcelizeDeclarationGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||
companion object {
|
||||
private val PREDICATE = has(PARCELIZE_FQN, OLD_PARCELIZE_FQN)
|
||||
private val parcelizeMethodsNames = setOf(DESCRIBE_CONTENTS_NAME, WRITE_TO_PARCEL_NAME)
|
||||
}
|
||||
|
||||
private val matchedClasses by lazy {
|
||||
session.predicateBasedProvider.getSymbolsByPredicate(PREDICATE)
|
||||
.filterIsInstance<FirRegularClassSymbol>()
|
||||
}
|
||||
|
||||
override fun generateFunctions(callableId: CallableId, owner: FirClassSymbol<*>?): List<FirNamedFunctionSymbol> {
|
||||
if (owner == null) return emptyList()
|
||||
require(owner is FirRegularClassSymbol)
|
||||
val functionSymbol = when (callableId.callableName) {
|
||||
DESCRIBE_CONTENTS_NAME -> {
|
||||
val hasDescribeContentImplementation = owner.hasDescribeContentsImplementation() ||
|
||||
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, session).any {
|
||||
it.fullyExpandedType(session).toRegularClassSymbol(session)?.hasDescribeContentsImplementation() ?: false
|
||||
}
|
||||
runIf(!hasDescribeContentImplementation) {
|
||||
generateDescribeContents(owner, callableId)
|
||||
}
|
||||
}
|
||||
WRITE_TO_PARCEL_NAME -> {
|
||||
val declaredFunctions = owner.declarationSymbols.filterIsInstance<FirNamedFunctionSymbol>()
|
||||
runIf(declaredFunctions.none { it.isWriteToParcel() }) { generateWriteToParcel(owner, callableId) }
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return listOfNotNull(functionSymbol)
|
||||
}
|
||||
|
||||
private fun FirRegularClassSymbol.hasDescribeContentsImplementation(): Boolean {
|
||||
return declarationSymbols.filterIsInstance<FirNamedFunctionSymbol>().any { it.isDescribeContentsImplementation() }
|
||||
}
|
||||
|
||||
private fun FirNamedFunctionSymbol.isDescribeContentsImplementation(): Boolean {
|
||||
if (name != DESCRIBE_CONTENTS_NAME) return false
|
||||
return valueParameterSymbols.isEmpty()
|
||||
}
|
||||
|
||||
private fun FirNamedFunctionSymbol.isWriteToParcel(): Boolean {
|
||||
if (name != WRITE_TO_PARCEL_NAME) return false
|
||||
val parameterSymbols = valueParameterSymbols
|
||||
if (parameterSymbols.size != 2) return false
|
||||
val (destSymbol, flagsSymbol) = parameterSymbols
|
||||
if (destSymbol.resolvedReturnTypeRef.coneType.classId != PARCEL_ID) return false
|
||||
if (!flagsSymbol.resolvedReturnTypeRef.type.isInt) return false
|
||||
return true
|
||||
}
|
||||
|
||||
private fun generateDescribeContents(owner: FirRegularClassSymbol, callableId: CallableId): FirNamedFunctionSymbol {
|
||||
return createFunction(owner, callableId) {
|
||||
returnTypeRef = session.builtinTypes.intType
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateWriteToParcel(owner: FirRegularClassSymbol, callableId: CallableId): FirNamedFunctionSymbol {
|
||||
return createFunction(owner, callableId) {
|
||||
returnTypeRef = session.builtinTypes.unitType
|
||||
|
||||
valueParameters += buildValueParameter {
|
||||
moduleData = session.moduleData
|
||||
origin = key.origin
|
||||
name = DEST_NAME
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(PARCEL_ID),
|
||||
emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
symbol = FirValueParameterSymbol(name)
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
|
||||
valueParameters += buildValueParameter {
|
||||
moduleData = session.moduleData
|
||||
origin = key.origin
|
||||
name = FLAGS_NAME
|
||||
returnTypeRef = session.builtinTypes.intType
|
||||
symbol = FirValueParameterSymbol(name)
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun createFunction(
|
||||
owner: FirRegularClassSymbol,
|
||||
callableId: CallableId,
|
||||
init: FirSimpleFunctionBuilder.() -> Unit
|
||||
): FirNamedFunctionSymbol {
|
||||
val function = buildSimpleFunction {
|
||||
moduleData = session.moduleData
|
||||
origin = key.origin
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
if (owner.modality == Modality.FINAL) Modality.FINAL else Modality.OPEN,
|
||||
EffectiveVisibility.Public
|
||||
).apply {
|
||||
isOverride = true
|
||||
}
|
||||
name = callableId.callableName
|
||||
symbol = FirNamedFunctionSymbol(callableId)
|
||||
dispatchReceiverType = owner.defaultType()
|
||||
init()
|
||||
}
|
||||
return function.symbol
|
||||
}
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||
return when {
|
||||
classSymbol.fir.modality == Modality.ABSTRACT -> emptySet()
|
||||
classSymbol in matchedClasses && classSymbol.fir.modality != Modality.SEALED -> parcelizeMethodsNames
|
||||
else -> {
|
||||
val hasAnnotatedSealedSuperType = classSymbol.resolvedSuperTypeRefs.any {
|
||||
val superSymbol = it.type.fullyExpandedType(session).toRegularClassSymbol(session) ?: return@any false
|
||||
superSymbol.fir.modality == Modality.SEALED && superSymbol in matchedClasses
|
||||
}
|
||||
if (hasAnnotatedSealedSuperType) {
|
||||
parcelizeMethodsNames
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val key: FirPluginKey
|
||||
get() = FirParcelizePluginKey
|
||||
|
||||
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
||||
register(PREDICATE)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||
|
||||
class FirParcelizeExtensionRegistrar : FirExtensionRegistrar() {
|
||||
override fun ExtensionRegistrarContext.configurePlugin() {
|
||||
+::FirParcelizeDeclarationGenerator
|
||||
+::FirParcelizeCheckersExtension
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPluginKey
|
||||
|
||||
object FirParcelizePluginKey : FirPluginKey() {
|
||||
override fun toString(): String {
|
||||
return "FirParcelize"
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnnotationCallChecker
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.DEPRECATED_RUNTIME_PACKAGE
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.IGNORED_ON_PARCEL_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELIZE_CLASS_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.RAW_VALUE_ANNOTATION_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.TYPE_PARCELER_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.WRITE_WITH_CLASS_IDS
|
||||
|
||||
object FirParcelizeAnnotationChecker : FirAnnotationCallChecker() {
|
||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val annotationType = expression.annotationTypeRef.coneType.fullyExpandedType(context.session) as? ConeClassLikeType ?: return
|
||||
val resolvedAnnotationSymbol = annotationType.lookupTag.toFirRegularClassSymbol(context.session) ?: return
|
||||
when (val annotationClassId = resolvedAnnotationSymbol.classId) {
|
||||
in TYPE_PARCELER_CLASS_IDS -> {
|
||||
checkTypeParcelerUsage(expression, context, reporter)
|
||||
checkDeprecatedAnnotations(expression, annotationClassId, context, reporter, isForbidden = true)
|
||||
}
|
||||
in WRITE_WITH_CLASS_IDS -> {
|
||||
checkWriteWithUsage(expression, context, reporter)
|
||||
checkDeprecatedAnnotations(expression, annotationClassId, context, reporter, isForbidden = true)
|
||||
}
|
||||
in IGNORED_ON_PARCEL_CLASS_IDS -> {
|
||||
checkDeprecatedAnnotations(expression, annotationClassId, context, reporter, isForbidden = false)
|
||||
}
|
||||
in PARCELIZE_CLASS_CLASS_IDS, in RAW_VALUE_ANNOTATION_CLASS_IDS -> {
|
||||
checkDeprecatedAnnotations(expression, annotationClassId, context, reporter, isForbidden = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDeprecatedAnnotations(
|
||||
annotationCall: FirAnnotationCall,
|
||||
annotationClassId: ClassId,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isForbidden: Boolean
|
||||
) {
|
||||
if (annotationClassId.packageFqName == DEPRECATED_RUNTIME_PACKAGE) {
|
||||
val factory = if (isForbidden) KtErrorsParcelize.FORBIDDEN_DEPRECATED_ANNOTATION else KtErrorsParcelize.DEPRECATED_ANNOTATION
|
||||
reporter.reportOn(annotationCall.source, factory, context)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun checkTypeParcelerUsage(annotationCall: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// TODO: this check checks type arguments of annotation which are not supported in FIR
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun checkWriteWithUsage(annotationCall: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// TODO: this check checks type arguments of annotation which are not supported in FIR
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.constructors
|
||||
import org.jetbrains.kotlin.fir.declarations.delegateFieldsMap
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.classId
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.isSubtypeOf
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.CREATOR_NAME
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.OLD_PARCELER_ID
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELABLE_ID
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELER_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELIZE_CLASS_CLASS_IDS
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
object FirParcelizeClassChecker : FirClassChecker() {
|
||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
checkParcelableClass(declaration, context, reporter)
|
||||
checkParcelerClass(declaration, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkParcelableClass(klass: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val symbol = klass.symbol
|
||||
if (!symbol.isParcelize(context.session)) return
|
||||
val source = klass.source ?: return
|
||||
if (klass !is FirRegularClass) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_SHOULD_BE_CLASS, context)
|
||||
return
|
||||
}
|
||||
|
||||
val classKind = klass.classKind
|
||||
if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.INTERFACE && !klass.isSealed) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_SHOULD_BE_CLASS, context)
|
||||
return
|
||||
}
|
||||
|
||||
klass.companionObjectSymbol?.let { companionSymbol ->
|
||||
if (companionSymbol.classId.shortClassName == CREATOR_NAME) {
|
||||
reporter.reportOn(companionSymbol.source, KtErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (classKind == ClassKind.CLASS && klass.isAbstract) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_SHOULD_BE_INSTANTIABLE, context)
|
||||
}
|
||||
|
||||
if (klass.isInner) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_CANT_BE_INNER_CLASS, context)
|
||||
}
|
||||
|
||||
if (klass.isLocal) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_CANT_BE_LOCAL_CLASS, context)
|
||||
}
|
||||
|
||||
val supertypes = lookupSuperTypes(klass, lookupInterfaces = true, deep = true, context.session, substituteTypes = false)
|
||||
if (supertypes.none { it.classId == PARCELABLE_ID }) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.NO_PARCELABLE_SUPERTYPE, context)
|
||||
}
|
||||
|
||||
klass.delegateFieldsMap?.forEach { (index, _) ->
|
||||
val superTypeRef = klass.superTypeRefs[index]
|
||||
val superType = superTypeRef.coneType
|
||||
val parcelableType = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(PARCELABLE_ID),
|
||||
emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
if (superType.isSubtypeOf(parcelableType, context.session)) {
|
||||
reporter.reportOn(superTypeRef.source, KtErrorsParcelize.PARCELABLE_DELEGATE_IS_NOT_ALLOWED, context)
|
||||
}
|
||||
}
|
||||
|
||||
val constructorSymbols = klass.constructors(context.session)
|
||||
val primaryConstructorSymbol = constructorSymbols.find { it.isPrimary }
|
||||
val secondaryConstructorSymbols = constructorSymbols.filterNot { it.isPrimary }
|
||||
if (primaryConstructorSymbol == null && secondaryConstructorSymbols.isNotEmpty()) {
|
||||
reporter.reportOn(source, KtErrorsParcelize.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkParcelerClass(klass: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (klass !is FirRegularClass || klass.isCompanion) return
|
||||
for (superTypeRef in klass.superTypeRefs) {
|
||||
withSuppressedDiagnostics(superTypeRef, context) {
|
||||
if (superTypeRef.coneType.classId == OLD_PARCELER_ID) {
|
||||
val strategy = if (klass.name == SpecialNames.NO_NAME_PROVIDED) {
|
||||
SourceElementPositioningStrategies.OBJECT_KEYWORD
|
||||
} else {
|
||||
SourceElementPositioningStrategies.NAME_IDENTIFIER
|
||||
}
|
||||
reporter.reportOn(klass.source, KtErrorsParcelize.DEPRECATED_PARCELER, it, positioningStrategy = strategy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun FirClassSymbol<*>?.isParcelize(session: FirSession): Boolean {
|
||||
contract {
|
||||
returns(true) implies (this@isParcelize != null)
|
||||
}
|
||||
|
||||
if (this == null) return false
|
||||
if (this.annotations.any { it.classId in PARCELIZE_CLASS_CLASS_IDS }) return true
|
||||
return resolvedSuperTypeRefs.any {
|
||||
val symbol = it.type.fullyExpandedType(session).toRegularClassSymbol(session) ?: return@any false
|
||||
symbol.annotations.any { it.classId in PARCELIZE_CLASS_CLASS_IDS }
|
||||
}
|
||||
}
|
||||
|
||||
fun FirRegularClass.hasCustomParceler(session: FirSession): Boolean {
|
||||
val companion = companionObjectSymbol ?: return false
|
||||
return lookupSuperTypes(companion, lookupInterfaces = true, deep = true, useSiteSession = session).any {
|
||||
it.classId in PARCELER_CLASS_IDS
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.hasValOrVar
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirConstructorChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.classId
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames
|
||||
|
||||
object FirParcelizeConstructorChecker : FirConstructorChecker() {
|
||||
override fun check(declaration: FirConstructor, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.isPrimary) return
|
||||
val source = declaration.source ?: return
|
||||
if (source.kind == KtFakeSourceElementKind.ImplicitConstructor) return
|
||||
val containingClass = context.containingDeclarations.last() as? FirRegularClass ?: return
|
||||
val containingClassSymbol = containingClass.symbol
|
||||
if (!containingClassSymbol.isParcelize(context.session) || containingClass.hasCustomParceler(context.session)) return
|
||||
|
||||
if (declaration.valueParameters.isEmpty()) {
|
||||
reporter.reportOn(containingClass.source, KtErrorsParcelize.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY, context)
|
||||
} else {
|
||||
for (valueParameter in declaration.valueParameters) {
|
||||
if (valueParameter.source?.hasValOrVar() != true) {
|
||||
reporter.reportOn(
|
||||
valueParameter.source,
|
||||
KtErrorsParcelize.PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR,
|
||||
context
|
||||
)
|
||||
}
|
||||
if (valueParameter.defaultValue == null) {
|
||||
val illegalAnnotation = valueParameter.annotations.firstOrNull {
|
||||
it.classId in ParcelizeNames.IGNORED_ON_PARCEL_CLASS_IDS
|
||||
}
|
||||
if (illegalAnnotation != null) {
|
||||
reporter.reportOn(
|
||||
illegalAnnotation.source,
|
||||
KtErrorsParcelize.INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSimpleFunctionChecker
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isInt
|
||||
import org.jetbrains.kotlin.fir.types.isUnit
|
||||
|
||||
object FirParcelizeFunctionChecker : FirSimpleFunctionChecker() {
|
||||
override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val containingClassSymbol = declaration.dispatchReceiverType?.toRegularClassSymbol(context.session)
|
||||
if (!containingClassSymbol.isParcelize(context.session)) return
|
||||
if (declaration.origin != FirDeclarationOrigin.Source) return
|
||||
if (declaration.isWriteToParcel() && declaration.isOverride) {
|
||||
reporter.reportOn(declaration.source, KtErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirSimpleFunction.isWriteToParcel(): Boolean {
|
||||
return typeParameters.isEmpty() &&
|
||||
valueParameters.size == 2 &&
|
||||
valueParameters[1].returnTypeRef.coneType.isInt &&
|
||||
returnTypeRef.coneType.isUnit
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.kotlin.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.hasJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.classId
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.CREATOR_NAME
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.IGNORED_ON_PARCEL_CLASS_IDS
|
||||
import org.jetbrains.kotlin.parcelize.ParcelizeNames.PARCELER_ID
|
||||
|
||||
object FirParcelizePropertyChecker : FirPropertyChecker() {
|
||||
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val containingClassSymbol = declaration.dispatchReceiverType?.toRegularClassSymbol(context.session) ?: return
|
||||
|
||||
if (containingClassSymbol.isParcelize(context.session)) {
|
||||
val fromPrimaryConstructor = declaration.fromPrimaryConstructor ?: false
|
||||
if (
|
||||
!fromPrimaryConstructor &&
|
||||
(declaration.hasBackingField || declaration.delegate != null) &&
|
||||
!declaration.hasIgnoredOnParcel() &&
|
||||
!containingClassSymbol.hasCustomParceler(context.session)
|
||||
) {
|
||||
reporter.reportOn(declaration.source, KtErrorsParcelize.PROPERTY_WONT_BE_SERIALIZED, context)
|
||||
}
|
||||
if (fromPrimaryConstructor) {
|
||||
checkParcelableClassProperty(declaration, containingClassSymbol, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration.name == CREATOR_NAME && containingClassSymbol.isCompanion && declaration.hasJvmFieldAnnotation) {
|
||||
val outerClass = context.containingDeclarations.asReversed().getOrNull(1) as? FirRegularClass
|
||||
if (outerClass != null && outerClass.symbol.isParcelize(context.session)) {
|
||||
reporter.reportOn(declaration.source, KtErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun checkParcelableClassProperty(
|
||||
property: FirProperty,
|
||||
containingClassSymbol: FirRegularClassSymbol,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val type = property.returnTypeRef.coneType
|
||||
if (type is ConeErrorType || containingClassSymbol.hasCustomParceler(context.session)) return
|
||||
/*
|
||||
* TODO: abstract code from ParcelSerializer or IrParcelSerializerFactory to avoid duplication
|
||||
* of allowed types checking
|
||||
*/
|
||||
}
|
||||
|
||||
private fun FirProperty.hasIgnoredOnParcel(): Boolean {
|
||||
return annotations.hasIgnoredOnParcel() || (getter?.annotations?.hasIgnoredOnParcel() ?: false)
|
||||
}
|
||||
|
||||
|
||||
private fun List<FirAnnotation>.hasIgnoredOnParcel(): Boolean {
|
||||
return this.any {
|
||||
if (it.annotationTypeRef.coneType.classId !in IGNORED_ON_PARCEL_CLASS_IDS) return@any false
|
||||
val target = it.useSiteTarget
|
||||
target == null || target == AnnotationUseSiteTarget.PROPERTY || target == AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClassSymbol.hasCustomParceler(session: FirSession): Boolean {
|
||||
val companionObjectSymbol = this.companionObjectSymbol ?: return false
|
||||
return lookupSuperTypes(companionObjectSymbol, lookupInterfaces = true, deep = true, session).any {
|
||||
it.classId == PARCELER_ID
|
||||
}
|
||||
}
|
||||
}
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.parcelize.fir.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_CLASS_OR_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.DEPRECATED_ANNOTATION
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.DEPRECATED_PARCELER
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.DUPLICATING_TYPE_PARCELERS
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.FORBIDDEN_DEPRECATED_ANNOTATION
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.INAPPLICABLE_IGNORED_ON_PARCEL
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.NO_PARCELABLE_SUPERTYPE
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_CANT_BE_INNER_CLASS
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_CANT_BE_LOCAL_CLASS
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_DELEGATE_IS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_SHOULD_BE_CLASS
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_SHOULD_BE_INSTANTIABLE
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_SHOULD_NOT_BE_ENUM_CLASS
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELABLE_TYPE_NOT_SUPPORTED
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELER_SHOULD_BE_OBJECT
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PARCELER_TYPE_INCOMPATIBLE
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.PROPERTY_WONT_BE_SERIALIZED
|
||||
import org.jetbrains.kotlin.parcelize.fir.diagnostics.KtErrorsParcelize.REDUNDANT_TYPE_PARCELER
|
||||
|
||||
object KtDefaultErrorMessagesParcelize {
|
||||
fun getRendererForDiagnostic(diagnostic: KtDiagnostic): KtDiagnosticRenderer {
|
||||
val factory = diagnostic.factory
|
||||
return MAP[factory] ?: factory.ktRenderer
|
||||
}
|
||||
|
||||
val MAP = KtDiagnosticFactoryToRendererMap("Parcelize").also { map ->
|
||||
map.put(
|
||||
PARCELABLE_SHOULD_BE_CLASS,
|
||||
"'Parcelable' should be a class"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_DELEGATE_IS_NOT_ALLOWED,
|
||||
"Delegating 'Parcelable' is not allowed"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_SHOULD_NOT_BE_ENUM_CLASS,
|
||||
"'Parcelable' should not be a 'enum class'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_SHOULD_BE_INSTANTIABLE,
|
||||
"'Parcelable' should not be an 'abstract' class"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_CANT_BE_INNER_CLASS,
|
||||
"'Parcelable' can't be an inner class"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_CANT_BE_LOCAL_CLASS,
|
||||
"'Parcelable' can't be a local class"
|
||||
)
|
||||
|
||||
map.put(
|
||||
NO_PARCELABLE_SUPERTYPE,
|
||||
"No 'Parcelable' supertype"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR,
|
||||
"'Parcelable' should have a primary constructor"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY,
|
||||
"The primary constructor is empty, no data will be serialized to 'Parcel'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR,
|
||||
"'Parcelable' constructor parameter should be 'val' or 'var'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PROPERTY_WONT_BE_SERIALIZED,
|
||||
"Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning"
|
||||
)
|
||||
|
||||
map.put(
|
||||
OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED,
|
||||
"Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead"
|
||||
)
|
||||
|
||||
map.put(
|
||||
CREATOR_DEFINITION_IS_NOT_ALLOWED,
|
||||
"'CREATOR' definition is not allowed. Use 'Parceler' companion object instead"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELABLE_TYPE_NOT_SUPPORTED,
|
||||
"Type is not directly supported by 'Parcelize'. " +
|
||||
"Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELER_SHOULD_BE_OBJECT,
|
||||
"Parceler should be an object"
|
||||
)
|
||||
|
||||
map.put(
|
||||
PARCELER_TYPE_INCOMPATIBLE,
|
||||
"Parceler type {0} is incompatible with {1}",
|
||||
RENDER_TYPE, RENDER_TYPE
|
||||
)
|
||||
|
||||
map.put(
|
||||
DUPLICATING_TYPE_PARCELERS,
|
||||
"Duplicating ''TypeParceler'' annotations"
|
||||
)
|
||||
|
||||
map.put(
|
||||
REDUNDANT_TYPE_PARCELER,
|
||||
"This ''TypeParceler'' is already provided for {0}",
|
||||
RENDER_CLASS_OR_OBJECT
|
||||
)
|
||||
|
||||
map.put(
|
||||
CLASS_SHOULD_BE_PARCELIZE,
|
||||
"{0} should be annotated with ''@Parcelize''",
|
||||
RENDER_CLASS_OR_OBJECT
|
||||
)
|
||||
|
||||
map.put(
|
||||
INAPPLICABLE_IGNORED_ON_PARCEL,
|
||||
"'@IgnoredOnParcel' is only applicable to class properties"
|
||||
)
|
||||
|
||||
map.put(
|
||||
INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY,
|
||||
"'@IgnoredOnParcel' is inapplicable to properties without default value declared in the primary constructor"
|
||||
)
|
||||
|
||||
map.put(
|
||||
FORBIDDEN_DEPRECATED_ANNOTATION,
|
||||
"Parceler-related annotations from package 'kotlinx.android.parcel' are forbidden. Change package to 'kotlinx.parcelize'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
DEPRECATED_ANNOTATION,
|
||||
"Parcelize annotations from package 'kotlinx.android.parcel' are deprecated. Change package to 'kotlinx.parcelize'"
|
||||
)
|
||||
|
||||
map.put(
|
||||
DEPRECATED_PARCELER,
|
||||
"'kotlinx.android.parcel.Parceler' is deprecated. Use 'kotlinx.parcelize.Parceler' instead"
|
||||
)
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.parcelize.fir.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.ABSTRACT_MODIFIER
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.DELEGATED_SUPERTYPE_BY_KEYWORD
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.INNER_MODIFIER
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.NAME_IDENTIFIER
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.OVERRIDE_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
object KtErrorsParcelize {
|
||||
val PARCELABLE_SHOULD_BE_CLASS by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PARCELABLE_DELEGATE_IS_NOT_ALLOWED by error0<PsiElement>(DELEGATED_SUPERTYPE_BY_KEYWORD)
|
||||
val PARCELABLE_SHOULD_NOT_BE_ENUM_CLASS by error0<PsiElement>()
|
||||
val PARCELABLE_SHOULD_BE_INSTANTIABLE by error0<PsiElement>(ABSTRACT_MODIFIER)
|
||||
val PARCELABLE_CANT_BE_INNER_CLASS by error0<PsiElement>(INNER_MODIFIER)
|
||||
val PARCELABLE_CANT_BE_LOCAL_CLASS by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val NO_PARCELABLE_SUPERTYPE by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY by warning0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PROPERTY_WONT_BE_SERIALIZED by warning0<PsiElement>(NAME_IDENTIFIER)
|
||||
val OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED by error0<PsiElement>(OVERRIDE_MODIFIER)
|
||||
val CREATOR_DEFINITION_IS_NOT_ALLOWED by error0<PsiElement>(NAME_IDENTIFIER)
|
||||
val PARCELABLE_TYPE_NOT_SUPPORTED by error0<PsiElement>()
|
||||
val PARCELER_SHOULD_BE_OBJECT by error0<PsiElement>()
|
||||
val PARCELER_TYPE_INCOMPATIBLE by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
|
||||
val DUPLICATING_TYPE_PARCELERS by error0<PsiElement>()
|
||||
val REDUNDANT_TYPE_PARCELER by warning1<PsiElement, KtClassOrObject>()
|
||||
val CLASS_SHOULD_BE_PARCELIZE by error1<PsiElement, KtClassOrObject>()
|
||||
val FORBIDDEN_DEPRECATED_ANNOTATION by error0<PsiElement>()
|
||||
val DEPRECATED_ANNOTATION by warning0<PsiElement>()
|
||||
val DEPRECATED_PARCELER by error0<PsiElement>()
|
||||
val INAPPLICABLE_IGNORED_ON_PARCEL by warning0<PsiElement>()
|
||||
val INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY by warning0<PsiElement>()
|
||||
}
|
||||
Reference in New Issue
Block a user