mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] "Redundant 'inner' modifier": fix a receiver on the call site
#KTIJ-3020 Fixed closes https://github.com/JetBrains/intellij-community/pull/1697 GitOrigin-RevId: f3019a729e947c6f40a538c6a94d81b28a93b91f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a0109ab276
commit
fe68621f65
+44
-8
@@ -2,11 +2,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.codeInspection.IntentionWrapper
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.psi.util.parentsOfType
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.intentions.receiverType
|
||||
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.util.getThisReceiverOwner
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
@@ -41,10 +42,7 @@ class RedundantInnerClassModifierInspection : AbstractKotlinInspection() {
|
||||
innerModifier,
|
||||
KotlinBundle.message("inspection.redundant.inner.class.modifier.descriptor"),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
IntentionWrapper(
|
||||
RemoveModifierFix(targetClass, KtTokens.INNER_KEYWORD, isRedundant = true),
|
||||
targetClass.containingFile
|
||||
)
|
||||
RemoveInnerModifierFix()
|
||||
)
|
||||
})
|
||||
|
||||
@@ -115,4 +113,42 @@ class RedundantInnerClassModifierInspection : AbstractKotlinInspection() {
|
||||
private fun PsiElement.receiverTypeReference(): KtTypeReference? {
|
||||
return safeAs<KtNamedFunction>()?.receiverTypeReference ?: safeAs<KtProperty>()?.receiverTypeReference
|
||||
}
|
||||
|
||||
private class RemoveInnerModifierFix : LocalQuickFix {
|
||||
override fun getName() = KotlinBundle.message("remove.redundant.0.modifier", KtTokens.INNER_KEYWORD.value)
|
||||
|
||||
override fun getFamilyName() = name
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val targetClass = descriptor.psiElement.getStrictParentOfType<KtClass>() ?: return
|
||||
val fixedElements = fixReceiverOnCallSite(targetClass)
|
||||
targetClass.removeModifier(KtTokens.INNER_KEYWORD)
|
||||
fixedElements.filterIsInstance<KtQualifiedExpression>().forEach { ShortenReferences.DEFAULT.process(it) }
|
||||
}
|
||||
|
||||
private fun fixReceiverOnCallSite(targetClass: KtClass): List<PsiElement> {
|
||||
val containingClass = targetClass.getStrictParentOfType<KtClass>() ?: return emptyList()
|
||||
val bindingContext = containingClass.analyze(BodyResolveMode.PARTIAL)
|
||||
val fqName =
|
||||
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, containingClass]?.fqNameOrNull()?.asString() ?: return emptyList()
|
||||
val psiFactory = KtPsiFactory(targetClass)
|
||||
val newReceiver = psiFactory.createExpression(fqName)
|
||||
return ReferencesSearch.search(targetClass, targetClass.useScope).mapNotNull {
|
||||
val callExpression = it.element.parent as? KtCallExpression ?: return@mapNotNull null
|
||||
val qualifiedExpression = callExpression.getQualifiedExpressionForSelector()
|
||||
val parentClass = callExpression.getStrictParentOfType<KtClass>()
|
||||
when {
|
||||
// Explicit receiver
|
||||
qualifiedExpression != null ->
|
||||
if (parentClass == containingClass) {
|
||||
qualifiedExpression.replace(callExpression)
|
||||
} else {
|
||||
qualifiedExpression.receiverExpression.replace(newReceiver)
|
||||
}
|
||||
// Implicit receiver
|
||||
else -> callExpression.replace(psiFactory.createExpressionByPattern("$0.$1", newReceiver, callExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -8184,6 +8184,36 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/inLocalClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall.kt")
|
||||
public void testInnerClassConstructorCall() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall2.kt")
|
||||
public void testInnerClassConstructorCall2() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall3.kt")
|
||||
public void testInnerClassConstructorCall3() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall4.kt")
|
||||
public void testInnerClassConstructorCall4() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall4.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall5.kt")
|
||||
public void testInnerClassConstructorCall5() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall5.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassConstructorCall6.kt")
|
||||
public void testInnerClassConstructorCall6() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/innerClassConstructorCall6.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("noOuterClassMemberReference.kt")
|
||||
public void testNoOuterClassMemberReference() throws Exception {
|
||||
runTest("testData/inspectionsLocal/redundantInnerClassModifier/noOuterClassMemberReference.kt");
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
<caret>inner class Inner
|
||||
|
||||
fun foo() {
|
||||
Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Inner
|
||||
|
||||
fun foo() {
|
||||
Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
<caret>inner class Inner
|
||||
|
||||
fun foo() {
|
||||
this.Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Inner
|
||||
|
||||
fun foo() {
|
||||
Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
<caret>inner class Inner
|
||||
|
||||
fun foo(t: Test) {
|
||||
t.Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Inner
|
||||
|
||||
fun foo(t: Test) {
|
||||
Inner()
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
<caret>inner class Inner
|
||||
}
|
||||
|
||||
fun foo(t: Test) {
|
||||
t.Inner()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Inner
|
||||
}
|
||||
|
||||
fun foo(t: Test) {
|
||||
Test.Inner()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
<caret>inner class Foo {
|
||||
inner class Bar
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.foo(t: Test) {
|
||||
Foo().Bar()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Foo {
|
||||
inner class Bar
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.foo(t: Test) {
|
||||
Test.Foo().Bar()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Foo {
|
||||
<caret>inner class Bar
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.foo(t: Test) {
|
||||
Test.Foo().Bar()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
class Test {
|
||||
class Foo {
|
||||
class Bar
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.foo(t: Test) {
|
||||
Test.Foo.Bar()
|
||||
}
|
||||
Reference in New Issue
Block a user