Skip to content

Commit

Permalink
(WIP) migrate ViewModelSuspendingFunctionsCheck
Browse files Browse the repository at this point in the history
  • Loading branch information
Godin committed Nov 29, 2024
1 parent e416e91 commit b9ee7f1
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,23 @@
*/
package org.sonarsource.kotlin.checks

import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.analysis.api.analyze
import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol
import org.jetbrains.kotlin.analysis.api.types.symbol
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.FUNCTION
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.suspendModifier
import org.sonarsource.kotlin.api.frontend.KotlinFileContext

@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6313")
class ViewModelSuspendingFunctionsCheck : AbstractCheck() {

override fun visitNamedFunction(function: KtNamedFunction, kotlinFileContext: KotlinFileContext) {
val bindingContext = kotlinFileContext.bindingContext
function.suspendModifier()?.let {
if (!function.isPrivate()
&& function.extendsViewModel(bindingContext)
&& function.extendsViewModel()
) {
kotlinFileContext.reportIssue(it,
"""Classes extending "ViewModel" should not expose suspending functions.""")
Expand All @@ -45,9 +41,15 @@ class ViewModelSuspendingFunctionsCheck : AbstractCheck() {
}
}

private fun KtNamedFunction.extendsViewModel(bindingContext: BindingContext): Boolean {
val classDescriptor = bindingContext[FUNCTION, this]?.containingDeclaration as? ClassDescriptor
return classDescriptor?.getAllSuperClassifiers()?.any {
it.fqNameOrNull()?.asString() == "androidx.lifecycle.ViewModel"
} ?: false
private fun KtNamedFunction.extendsViewModel(): Boolean {
val function = this
analyze(function) {
val containingSymbol = function.symbol.containingSymbol
if (containingSymbol is KaClassSymbol) {
return containingSymbol.superTypes.any {
it.symbol?.classId?.asString() == "androidx/lifecycle/ViewModel"
}
}
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,15 @@
*/
package org.sonarsource.kotlin.checks

internal class ViewModelSuspendingFunctionsCheckTest : CheckTest(ViewModelSuspendingFunctionsCheck())
import org.junit.jupiter.api.Test
import org.sonarsource.kotlin.testapi.KotlinVerifier

internal class ViewModelSuspendingFunctionsCheckTest : CheckTest(ViewModelSuspendingFunctionsCheck()) {
@Test
fun k2() {
KotlinVerifier(check) {
this.fileName = sampleFileSemantics ?: "${checkName}Sample.kt"
this.useK2 = true
}.verify()
}
}

0 comments on commit b9ee7f1

Please sign in to comment.