RemoveRedundantQualifierNameInspection: support class literal expression
#KT-32046 Fixed
This commit is contained in:
+16
-5
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFirstClassifierWithDeprecationStatus
|
import org.jetbrains.kotlin.resolve.scopes.utils.findFirstClassifierWithDeprecationStatus
|
||||||
|
|
||||||
@@ -28,16 +27,23 @@ class RemoveRedundantQualifierNameInspection : AbstractKotlinInspection(), Clean
|
|||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor =
|
||||||
object : KtVisitorVoid() {
|
object : KtVisitorVoid() {
|
||||||
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
|
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression) {
|
||||||
if (expression.parent is KtDotQualifiedExpression? || expression.isInImportDirective()) return
|
if (expression.parent is KtDotQualifiedExpression || expression.isInImportDirective()) return
|
||||||
val expressionForAnalyze = expression.firstExpressionWithoutReceiver() ?: return
|
val expressionForAnalyze = expression.firstExpressionWithoutReceiver() ?: return
|
||||||
|
|
||||||
val context = expressionForAnalyze.analyze()
|
val parent = expressionForAnalyze.parent
|
||||||
|
@Suppress("USELESS_CAST") val originalExpression = if (parent is KtClassLiteralExpression)
|
||||||
|
parent as KtExpression
|
||||||
|
else
|
||||||
|
expressionForAnalyze
|
||||||
|
|
||||||
|
val context = originalExpression.analyze()
|
||||||
|
|
||||||
val importableFqName = expressionForAnalyze.getQualifiedElementSelector()
|
val importableFqName = expressionForAnalyze.getQualifiedElementSelector()
|
||||||
?.mainReference?.resolveToDescriptors(context)?.firstOrNull()
|
?.mainReference?.resolveToDescriptors(context)?.firstOrNull()
|
||||||
?.importableFqName ?: return
|
?.importableFqName ?: return
|
||||||
|
|
||||||
val applicableExpression = expressionForAnalyze.firstApplicableExpression(validator = {
|
val applicableExpression = expressionForAnalyze.firstApplicableExpression(validator = {
|
||||||
applicableExpression(expressionForAnalyze, context, importableFqName)
|
applicableExpression(originalExpression, context, importableFqName)
|
||||||
}) {
|
}) {
|
||||||
firstChild as? KtDotQualifiedExpression
|
firstChild as? KtDotQualifiedExpression
|
||||||
} ?: return
|
} ?: return
|
||||||
@@ -78,13 +84,18 @@ private fun KtDotQualifiedExpression.applicableExpression(
|
|||||||
val expressionText = originalExpression.text.substring(lastChild.startOffset - originalExpression.startOffset)
|
val expressionText = originalExpression.text.substring(lastChild.startOffset - originalExpression.startOffset)
|
||||||
val newExpression = KtPsiFactory(originalExpression).createExpressionIfPossible(expressionText) ?: return null
|
val newExpression = KtPsiFactory(originalExpression).createExpressionIfPossible(expressionText) ?: return null
|
||||||
val newContext = newExpression.analyzeAsReplacement(originalExpression, oldContext)
|
val newContext = newExpression.analyzeAsReplacement(originalExpression, oldContext)
|
||||||
val newDescriptor = newExpression.getQualifiedElementSelector()?.getResolvedCall(newContext)?.resultingDescriptor ?: return null
|
val newDescriptor = newExpression.selector()
|
||||||
|
?.mainReference?.resolveToDescriptors(newContext)
|
||||||
|
?.firstOrNull() ?: return null
|
||||||
|
|
||||||
return takeIf {
|
return takeIf {
|
||||||
importableFqName == newDescriptor.importableFqName
|
importableFqName == newDescriptor.importableFqName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KtExpression.selector(): KtElement? = if (this is KtClassLiteralExpression) receiverExpression?.getQualifiedElementSelector()
|
||||||
|
else getQualifiedElementSelector()
|
||||||
|
|
||||||
private fun KtExpression.isApplicableReceiver(context: BindingContext): Boolean {
|
private fun KtExpression.isApplicableReceiver(context: BindingContext): Boolean {
|
||||||
if (this is KtInstanceExpressionWithLabel) return false
|
if (this is KtInstanceExpressionWithLabel) return false
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo<caret>.Foo::class
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
Foo::class
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo<caret>.Foo::class.java
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
package foo
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
Foo::class.java
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
val Bwd = 42
|
||||||
|
|
||||||
|
class BBD
|
||||||
|
|
||||||
|
val a = foo.www.ddd<caret>.Check.BBD.Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
val Bwd = 42
|
||||||
|
|
||||||
|
class BBD
|
||||||
|
|
||||||
|
val a = Check.BBD.Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
fun Bwd(): String = ""
|
||||||
|
val a = foo.www.ddd.<caret>Check.BBD.Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
fun Bwd(): String = ""
|
||||||
|
val a = Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
class Bwd
|
||||||
|
val a = foo.www.ddd.<caret>Check.BBD.Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// DISABLE-ERRORS
|
||||||
|
package foo.www.ddd
|
||||||
|
|
||||||
|
class Check {
|
||||||
|
class BBD {
|
||||||
|
class Bwd {
|
||||||
|
fun dad() {
|
||||||
|
class Bwd
|
||||||
|
val a = BBD.Bwd::class.java.annotatedInterfaces.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -7631,6 +7631,31 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/asReceiverProperty.kt");
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/asReceiverProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classLiteral.kt")
|
||||||
|
public void testClassLiteral() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/classLiteral.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classLiteral2.kt")
|
||||||
|
public void testClassLiteral2() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/classLiteral2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classLiteral3.kt")
|
||||||
|
public void testClassLiteral3() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/classLiteral3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classLiteral4.kt")
|
||||||
|
public void testClassLiteral4() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/classLiteral4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classLiteral5.kt")
|
||||||
|
public void testClassLiteral5() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/classLiteral5.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("companionCollision.kt")
|
@TestMetadata("companionCollision.kt")
|
||||||
public void testCompanionCollision() throws Exception {
|
public void testCompanionCollision() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/companionCollision.kt");
|
runTest("idea/testData/inspectionsLocal/removeRedundantQualifierName/companionCollision.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user