[devkit] Simplifiable service retrieving: fix false positives

The inspection must not suggest replacing service retrieving calls with a `getInstance` call if a `getInstance` method has a nullable return type.

GitOrigin-RevId: cd8a36698f0c1efb4c6af27962554ae36ba7266a
This commit is contained in:
Andrey Cherkasov
2023-11-29 13:31:50 +00:00
committed by intellij-monorepo-bot
parent 80601d7d6a
commit 7bef3fb7b8
5 changed files with 68 additions and 6 deletions
@@ -8,6 +8,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElementVisitor
import com.intellij.uast.UastHintedVisitorAdapter
import org.jetbrains.annotations.Nullable
import org.jetbrains.idea.devkit.DevKitBundle
import org.jetbrains.uast.*
import org.jetbrains.uast.generate.UastCodeGenerationPlugin
@@ -73,9 +74,7 @@ internal class SimplifiableServiceRetrievingInspection : ServiceRetrievingInspec
}
private fun isGetInstanceProjectLevel(method: UMethod): Boolean {
if (!(method.isStaticOrJvmStatic && method.visibility == UastVisibility.PUBLIC && method.uastParameters.size == 1)) {
return false
}
if (!isApplicableForGetInstance(method) || method.uastParameters.size != 1) return false
val param = method.uastParameters[0]
if (param.type.canonicalText != Project::class.java.canonicalName) return false
val qualifiedRef = getReturnExpression(method)?.returnExpression as? UQualifiedReferenceExpression ?: return false
@@ -84,9 +83,7 @@ internal class SimplifiableServiceRetrievingInspection : ServiceRetrievingInspec
}
private fun isGetInstanceApplicationLevel(method: UMethod): Boolean {
if (!(method.isStaticOrJvmStatic && method.visibility == UastVisibility.PUBLIC && method.uastParameters.isEmpty())) {
return false
}
if (!isApplicableForGetInstance(method) || method.uastParameters.isNotEmpty()) return false
return when (val returnExpression = getReturnExpression(method)?.returnExpression) {
is UQualifiedReferenceExpression -> {
(componentManagerGetServiceMethods.uCallMatches(returnExpression.selector as? UCallExpression)
@@ -97,6 +94,12 @@ internal class SimplifiableServiceRetrievingInspection : ServiceRetrievingInspec
}
}
private fun isApplicableForGetInstance(method: UMethod): Boolean {
return method.isStaticOrJvmStatic &&
method.visibility == UastVisibility.PUBLIC &&
!method.javaPsi.hasAnnotation(Nullable::class.java.canonicalName)
}
private val UMethod.isStaticOrJvmStatic: Boolean
get() = this.isStatic || this.findAnnotation(JvmStatic::class.java.canonicalName) != null
@@ -0,0 +1,25 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
import org.jetbrains.annotations.Nullable;
@Service
final class MyAppService {
public static @Nullable MyAppService getInstance() {
return ApplicationManager.getApplication().getService(MyAppService.class);
}
void foo() {
MyAppService service = ApplicationManager.getApplication().getService(MyAppService.class);
}
}
@Service(Service.Level.PROJECT)
final class MyProjectService {
public static @Nullable MyProjectService getInstance() {
return ApplicationManager.getApplication().getService(MyProjectService.class);
}
void foo() {
MyProjectService service = ApplicationManager.getApplication().getService(MyProjectService.class);
}
}
@@ -23,4 +23,8 @@ internal class SimplifiableServiceRetrievingInspectionTest : SimplifiableService
fun testTooGenericGetInstanceReturnType() {
doTest()
}
fun testNullableGetInstanceMethod() {
doTest()
}
}
@@ -0,0 +1,26 @@
@file:Suppress("NO_REFLECTION_IN_CLASS_PATH")
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
@Service
class MyAppService {
companion object {
@JvmStatic
fun getInstance(): MyAppService? = ApplicationManager.getApplication().getService(MyAppService::class.java)
}
}
@Service(Service.Level.PROJECT)
class MyProjectService {
companion object {
@JvmStatic
fun getInstance(project: Project): MyProjectService? = project.getService(MyProjectService::class.java)
}
}
fun test(project: Project) {
ApplicationManager.getApplication().getService(MyAppService::class.java)
project.getService(MyProjectService::class.java)
}
@@ -56,6 +56,10 @@ internal class KtSimplifiableServiceRetrievingInspectionTest : SimplifiableServi
doTest()
}
fun testNullableGetInstanceMethod() {
doTest()
}
fun testReturnTypeHasTypeParam() {
doTest(DevKitBundle.message("inspection.simplifiable.service.retrieving.replace.with", "MyAppService", "getInstance"))
}