Skip to content

Commit

Permalink
SONARKT-400 Migrate InterfaceCouldBeFunctionalCheck to kotlin-analysi…
Browse files Browse the repository at this point in the history
…s-api

Co-authored-by: Marharyta Nedzelska <[email protected]>
Co-authored-by: Evgeny Mandrikov <[email protected]>
  • Loading branch information
leveretka and Godin committed Dec 5, 2024
1 parent fd49eb9 commit 096bf2e
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,8 @@ fun KtBinaryExpression.isPlus() =
fun PsiElement?.getVariableType(bindingContext: BindingContext) =
this?.let { bindingContext[BindingContext.VARIABLE, it]?.type }

/** Use [org.jetbrains.kotlin.analysis.api.components.KaTypeProvider.type] instead. */
@Deprecated("use kotlin-analysis-api instead")
fun KtTypeReference?.getType(bindingContext: BindingContext): KotlinType? =
this?.let { bindingContext[BindingContext.TYPE, it] }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,18 @@
*/
package org.sonarsource.kotlin.checks

import org.jetbrains.kotlin.js.descriptorUtils.getKotlinTypeFqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.getType
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
import org.sonarsource.kotlin.api.visiting.withKaSession

@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6517")
class InterfaceCouldBeFunctionalCheck : AbstractCheck() {
private val functionalInterClassId = ClassId.fromString("java/lang/FunctionalInterface")

override fun visitClass(klass: KtClass, context: KotlinFileContext) {
checkFunctionalInterface(klass, context)
Expand All @@ -46,9 +45,9 @@ class InterfaceCouldBeFunctionalCheck : AbstractCheck() {
}
}

private fun checkFunctionalInterfaceAnnotation(klass: KtClass, context: KotlinFileContext) {
private fun checkFunctionalInterfaceAnnotation(klass: KtClass, context: KotlinFileContext) = withKaSession {
klass.annotationEntries.forEach {
if (isFunctionalInterfaceAnnotation(it, context)) {
if (it.typeReference?.type?.isClassType(functionalInterClassId) == true) {
context.reportIssue(it, """"@FunctionalInterface" annotation has no effect in Kotlin""")
}
}
Expand All @@ -65,8 +64,3 @@ private fun hasExactlyOneFunctionAndNoProperties(klass: KtClass): Boolean {
it !is KtProperty && (it !is KtNamedFunction || functionCount++ == 0)
} && functionCount > 0
}

private fun isFunctionalInterfaceAnnotation(annotation: KtAnnotationEntry, context: KotlinFileContext): Boolean {
val annotationType = annotation.typeReference.getType(context.bindingContext)
return (annotationType?.getKotlinTypeFqName(false) == "java.lang.FunctionalInterface")
}

0 comments on commit 096bf2e

Please sign in to comment.