[FIR] @JvmOverloads related checkers

This commit is contained in:
Andrey Zinovyev
2021-08-17 17:16:31 +03:00
committed by TeamCityServer
parent 17ae69416c
commit f9b601edae
17 changed files with 222 additions and 74 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
import org.jetbrains.kotlin.fir.types.ConeKotlinType
@@ -18,12 +19,6 @@ import org.jetbrains.kotlin.psi.KtAnnotationEntry
object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
val DECLARATIONS by object : DiagnosticGroup("Declarations") {
val CONFLICTING_JVM_DECLARATIONS by error<PsiElement>()
val STRICTFP_ON_CLASS by error<KtAnnotationEntry>()
val VOLATILE_ON_VALUE by error<KtAnnotationEntry>()
val VOLATILE_ON_DELEGATE by error<KtAnnotationEntry>()
val SYNCHRONIZED_ON_ABSTRACT by error<KtAnnotationEntry>()
val SYNCHRONIZED_IN_INTERFACE by error<KtAnnotationEntry>()
val SYNCHRONIZED_ON_INLINE by warning<KtAnnotationEntry>()
}
val TYPES by object : DiagnosticGroup("Types") {
@@ -32,4 +27,20 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
parameter<ConeKotlinType>("actualType")
}
}
val ANNOTATIONS by object : DiagnosticGroup("annotations") {
val STRICTFP_ON_CLASS by error<KtAnnotationEntry>()
val VOLATILE_ON_VALUE by error<KtAnnotationEntry>()
val VOLATILE_ON_DELEGATE by error<KtAnnotationEntry>()
val SYNCHRONIZED_ON_ABSTRACT by error<KtAnnotationEntry>()
val SYNCHRONIZED_IN_INTERFACE by error<KtAnnotationEntry>()
val SYNCHRONIZED_ON_INLINE by warning<KtAnnotationEntry>()
val OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS by warning<KtAnnotationEntry>()
val OVERLOADS_ABSTRACT by error<KtAnnotationEntry>()
val OVERLOADS_INTERFACE by error<KtAnnotationEntry>()
val OVERLOADS_LOCAL by error<KtAnnotationEntry>()
val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError<KtAnnotationEntry>(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses)
val OVERLOADS_PRIVATE by warning<KtAnnotationEntry>()
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics.jvm
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -19,14 +20,22 @@ import org.jetbrains.kotlin.psi.KtExpression
object FirJvmErrors {
// Declarations
val CONFLICTING_JVM_DECLARATIONS by error0<PsiElement>()
// Types
val JAVA_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
// annotations
val STRICTFP_ON_CLASS by error0<KtAnnotationEntry>()
val VOLATILE_ON_VALUE by error0<KtAnnotationEntry>()
val VOLATILE_ON_DELEGATE by error0<KtAnnotationEntry>()
val SYNCHRONIZED_ON_ABSTRACT by error0<KtAnnotationEntry>()
val SYNCHRONIZED_IN_INTERFACE by error0<KtAnnotationEntry>()
val SYNCHRONIZED_ON_INLINE by warning0<KtAnnotationEntry>()
// Types
val JAVA_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
val OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS by warning0<KtAnnotationEntry>()
val OVERLOADS_ABSTRACT by error0<KtAnnotationEntry>()
val OVERLOADS_INTERFACE by error0<KtAnnotationEntry>()
val OVERLOADS_LOCAL by error0<KtAnnotationEntry>()
val OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR by deprecationError0<KtAnnotationEntry>(ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses)
val OVERLOADS_PRIVATE by warning0<KtAnnotationEntry>()
}
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.jvm.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirJvmExternalDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirStrictfpApplicabilityChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirSynchronizedAnnotationChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.FirVolatileAnnotationChecker
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration.*
object JvmDeclarationCheckers : DeclarationCheckers() {
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
@@ -30,5 +27,6 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
override val functionCheckers: Set<FirFunctionChecker>
get() = setOf(
FirSynchronizedAnnotationChecker,
FirOverloadsChecker,
)
}
@@ -0,0 +1,55 @@
/*
* 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.fir.analysis.jvm.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.getAnnotationByFqName
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
import org.jetbrains.kotlin.fir.declarations.utils.isActual
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
import org.jetbrains.kotlin.name.FqName
object FirOverloadsChecker : FirFunctionChecker() {
private val JVM_OVERLOADS_FQ_NAME = FqName("kotlin.jvm.JvmOverloads")
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
val annotation = declaration.getAnnotationByFqName(JVM_OVERLOADS_FQ_NAME) ?: return
//todo need to have expect declaration here to check if it has default values
if (declaration.isActual) return
val containingDeclaration = declaration.getContainingClassSymbol(context.session)
when {
containingDeclaration?.classKind == ClassKind.INTERFACE ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_INTERFACE, context)
declaration.isAbstract ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_ABSTRACT, context)
(declaration is FirSimpleFunction && declaration.isLocal) ||
context.containingDeclarations.any { it.isLocalClassOrAnonymousObject() } ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_LOCAL, context)
declaration is FirConstructor && containingDeclaration?.classKind == ClassKind.ANNOTATION_CLASS ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR, context)
!declaration.visibility.isPublicAPI && declaration.visibility != Visibilities.Internal ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_PRIVATE, context)
declaration.valueParameters.none { it.defaultValue != null } ->
reporter.reportOn(annotation.source, FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS, context)
}
}
}
@@ -1,7 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class C {
@kotlin.jvm.JvmOverloads constructor() {
}
@kotlin.jvm.JvmOverloads fun foo(s: String) {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class C {
<!OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS!>@kotlin.jvm.JvmOverloads<!> constructor() {
@@ -1,11 +0,0 @@
interface T {
@kotlin.jvm.JvmOverloads fun foo(s: String = "OK")
@kotlin.jvm.JvmOverloads fun bar(s: String = "OK") {
}
}
abstract class C {
@kotlin.jvm.JvmOverloads abstract fun foo(s: String = "OK")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface T {
<!OVERLOADS_INTERFACE!>@kotlin.jvm.JvmOverloads<!> fun foo(s: String = "OK")
@@ -1,4 +0,0 @@
// !LANGUAGE: -ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
annotation class A1 @JvmOverloads constructor(val x: Int = 1)
annotation class A2 @JvmOverloads constructor()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
annotation class A1 <!OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING!>@JvmOverloads<!> constructor(val x: Int = 1)
@@ -1,4 +0,0 @@
// !LANGUAGE: +ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
annotation class A1 @JvmOverloads constructor(val x: Int = 1)
annotation class A2 @JvmOverloads constructor()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
annotation class A1 <!OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_ERROR!>@JvmOverloads<!> constructor(val x: Int = 1)
@@ -1,23 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class C {
@kotlin.jvm.JvmOverloads private fun foo(s: String = "OK") {
}
@kotlin.jvm.JvmOverloads fun bar(s: String = "OK") {
}
}
fun foo() {
@kotlin.jvm.JvmOverloads fun quux(s: String = "OK") {
}
class D {
@kotlin.jvm.JvmOverloads fun foo(s: String = "OK") {
}
}
val x = object {
@kotlin.jvm.JvmOverloads fun foo(s: String = "OK") {
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class C {
<!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads<!> private fun foo(s: String = "OK") {