[Parcelize] Detect redundant TypeParceler when type aliases are used

Make sure redundancies between class and property TypeParceler
annotations are detected when a type alias is used. This requires
checking the expanded type arguments of the annotation, as just
comparing the cone types is not sufficient because the type arguments
are not expanded.

^KT-64979 Fixed
This commit is contained in:
Brian Norman
2024-01-15 10:36:48 -06:00
committed by Space Team
parent 20340f94d4
commit eded51a0f5
3 changed files with 18 additions and 17 deletions
@@ -11,10 +11,7 @@ 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.analysis.checkers.findClosestClassOrObject
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeType
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
@@ -94,13 +91,27 @@ object FirParcelizeAnnotationChecker : FirAnnotationCallChecker() {
val enclosingClass = context.findClosestClassOrObject() ?: return
val annotationType = annotationCall.toAnnotationClassLikeType(context.session) ?: return
if (enclosingClass.hasAnnotation(annotationType, context.session)) {
if (checkForRedundantTypeParceler(enclosingClass, annotationType, context)) {
val reportElement = annotationCall.calleeReference.source ?: annotationCall.source
reporter.reportOn(reportElement, KtErrorsParcelize.REDUNDANT_TYPE_PARCELER, enclosingClass.symbol, context)
}
}
}
private fun checkForRedundantTypeParceler(
enclosingClass: FirClass,
annotationType: ConeClassLikeType,
context: CheckerContext,
): Boolean {
return enclosingClass.annotations
.mapNotNull { it.toAnnotationClassLikeType(context.session) }
.filter { it.classId == annotationType.classId && it.typeArguments.size == annotationType.typeArguments.size }
.any {
it.typeArguments.zip(annotationType.typeArguments)
.all { (first, second) -> first.type?.fullyExpandedType(context.session) == second.type?.fullyExpandedType(context.session) }
}
}
private fun checkWriteWithUsage(annotationCall: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
checkIfTheContainingClassIsParcelize(annotationCall, context, reporter)