Idea: add quick fix for replacing usages of deprecated "INSTANCE$" field

This commit is contained in:
Pavel V. Talanov
2015-10-07 17:34:44 +03:00
committed by Michael Bogdanov
parent d630c25f7d
commit f4ef9647b1
10 changed files with 136 additions and 0 deletions
+8
View File
@@ -1240,6 +1240,14 @@
cleanupTool="true"
level="WARNING"/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.DeprecatedObjectInstanceFieldReferenceInspection"
displayName="Usage of deprecated 'INSTANCE$' field"
groupName="Kotlin"
language="JAVA"
enabledByDefault="true"
cleanupTool="true"
level="WARNING"/>
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInspection.*
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.codeStyle.JavaCodeStyleManager
import org.jetbrains.kotlin.asJava.KotlinLightClass
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.JetObjectDeclaration
public class DeprecatedObjectInstanceFieldReferenceInspection : LocalInspectionTool(), CleanupLocalInspectionTool {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
return object : JavaElementVisitor() {
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
val resolvedTo = expression.reference?.resolve()
if (!(resolvedTo is PsiField && resolvedTo.name == JvmAbi.DEPRECATED_INSTANCE_FIELD)) return
val containingClass = resolvedTo.containingClass
if (containingClass !is KotlinLightClass || containingClass.getOrigin() !is JetObjectDeclaration) return
holder.registerProblem(
expression, "Use of deprecated '${JvmAbi.DEPRECATED_INSTANCE_FIELD}' field",
ProblemHighlightType.LIKE_DEPRECATED,
DeprecatedObjectInstanceFieldReferenceFix()
)
}
}
}
}
public class DeprecatedObjectInstanceFieldReferenceFix : LocalQuickFix {
override fun getName(): String = "Replace with reference to '${JvmAbi.INSTANCE_FIELD}' field"
override fun getFamilyName(): String = name
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val reference = descriptor.psiElement.reference ?: return
val deprecatedField = reference.resolve() as? PsiField ?: return
val lightClassForObject = deprecatedField.containingClass as? KotlinLightClass ?: return
val correctField = lightClassForObject.findFieldByName(JvmAbi.INSTANCE_FIELD, false) ?: return
val newReference = reference.bindToElement(correctField)
val codeStyleManager = JavaCodeStyleManager.getInstance(project)
codeStyleManager.shortenClassReferences(newReference)
val javaFile = newReference.containingFile as? PsiJavaFile ?: return
codeStyleManager.removeRedundantImports(javaFile)
}
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.DeprecatedObjectInstanceFieldReferenceInspection
@@ -0,0 +1,8 @@
// "Replace with reference to 'INSTANCE' field" "true"
import a.A;
class B {
void bar() {
A.INSTANCE.getName();
}
}
@@ -0,0 +1,8 @@
// "Replace with reference to 'INSTANCE' field" "true"
import a.A;
class B {
void bar() {
A.IN<caret>STANCE$.getName();
}
}
@@ -0,0 +1,4 @@
package a
object A {
}
@@ -0,0 +1,8 @@
// "Replace with reference to 'INSTANCE' field" "true"
import a.A;
class B {
void bar() {
A.INSTANCE.getName();
}
}
@@ -0,0 +1,8 @@
// "Replace with reference to 'INSTANCE' field" "true"
import static a.A.INSTANCE$;
class B {
void bar() {
IN<caret>STANCE$.getName();
}
}
@@ -0,0 +1,5 @@
package a
object A {
val name: String = ""
}
@@ -1063,6 +1063,27 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
}
@TestMetadata("idea/testData/quickfix/migration/deprecatedObjectInstanceField")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DeprecatedObjectInstanceField extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInDeprecatedObjectInstanceField() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/deprecatedObjectInstanceField"), Pattern.compile("^(\\w+)\\.before\\.Main\\.\\w+$"), true);
}
@TestMetadata("basic.before.Main.java")
public void testBasic() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deprecatedObjectInstanceField/basic.before.Main.java");
doTestWithExtraFile(fileName);
}
@TestMetadata("staticImport.before.Main.java")
public void testStaticImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deprecatedObjectInstanceField/staticImport.before.Main.java");
doTestWithExtraFile(fileName);
}
}
@TestMetadata("idea/testData/quickfix/migration/deprecatedPackageFacade")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)