Added second quickfix on conflicting extension to mark it hidden and deprecated

This commit is contained in:
Valentin Kipyatkov
2015-08-31 23:43:02 +03:00
parent b2ea369129
commit 086d29a44a
36 changed files with 91 additions and 31 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.inspections
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.codeInspection.*
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotatedAsHidden
import org.jetbrains.kotlin.resolve.scopes.FileScope
@@ -67,12 +69,25 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection()
// don't report on hidden declarations
if (propertyDescriptor.isAnnotatedAsHidden()) return
val fixes = if (isSameAsSynthetic(property, conflictingExtension)) {
val fix1 = IntentionWrapper(DeleteRedundantExtensionAction(property), file)
// don't add the second fix when on the fly to allow code cleanup
val fix2 = if (isOnTheFly)
object : IntentionWrapper(MarkHiddenAndDeprecatedAction(property), file), LowPriorityAction {}
else
null
listOf(fix1, fix2).filterNotNull().toTypedArray()
}
else {
emptyArray()
}
val problemDescriptor = holder.manager.createProblemDescriptor(
nameElement,
"This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler",
createQuickFix(property, conflictingExtension),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
true
true,
fixes,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
)
holder.registerProblem(problemDescriptor)
}
@@ -88,18 +103,18 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection()
.firstIsInstanceOrNull()
}
private fun createQuickFix(declaration: JetProperty, syntheticProperty: SyntheticJavaPropertyDescriptor): LocalQuickFix? {
val getter = declaration.getter ?: return null
private fun isSameAsSynthetic(declaration: JetProperty, syntheticProperty: SyntheticJavaPropertyDescriptor): Boolean {
val getter = declaration.getter ?: return false
val setter = declaration.setter
if (!checkGetterBodyIsGetMethodCall(getter, syntheticProperty.getMethod)) return null
if (!checkGetterBodyIsGetMethodCall(getter, syntheticProperty.getMethod)) return false
if (setter != null) {
val setMethod = syntheticProperty.setMethod ?: return null // synthetic property is val but our property is var
if (!checkSetterBodyIsSetMethodCall(setter, setMethod)) return null
val setMethod = syntheticProperty.setMethod ?: return false // synthetic property is val but our property is var
if (!checkSetterBodyIsSetMethodCall(setter, setMethod)) return false
}
return IntentionWrapper(DeleteRedundantExtensionAction(declaration), declaration.containingFile)
return true
}
private fun checkGetterBodyIsGetMethodCall(getter: JetPropertyAccessor, getMethod: FunctionDescriptor): Boolean {
@@ -196,4 +211,31 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection()
}
}
}
private class MarkHiddenAndDeprecatedAction(property: JetProperty) : JetIntentionAction<JetProperty>(property) {
override fun getFamilyName() = "Mark with @HiddenDeclaration and @deprecated"
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
val factory = JetPsiFactory(project)
val name = element.nameAsName!!.render()
element.addAnnotationWithLineBreak(factory.createAnnotationEntry("@deprecated(\"Is replaced with automatic synthetic extension\", ReplaceWith(\"$name\"))"))
element.addAnnotationWithLineBreak(factory.createAnnotationEntry("@HiddenDeclaration"))
}
//TODO: move into PSI?
private fun JetNamedDeclaration.addAnnotationWithLineBreak(annotationEntry: JetAnnotationEntry): JetAnnotationEntry {
val newLine = JetPsiFactory(this).createNewLine()
if (modifierList != null) {
val result = addAnnotationEntry(annotationEntry)
modifierList!!.addAfter(newLine, result)
return result
}
else {
val result = addAnnotationEntry(annotationEntry)
addAfter(newLine, modifierList)
return result
}
}
}
}
@@ -0,0 +1,5 @@
// "Mark with @HiddenDeclaration and @deprecated" "true"
import java.io.File
val File.<caret>name: String
get() = getName()
@@ -0,0 +1,7 @@
// "Mark with @HiddenDeclaration and @deprecated" "true"
import java.io.File
@HiddenDeclaration
@deprecated("Is replaced with automatic synthetic extension", ReplaceWith("name"))
val File.<caret>name: String
get() = getName()
@@ -990,23 +990,23 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
}
@TestMetadata("idea/testData/quickfix/migration/deleteRedundantExtension")
@TestMetadata("idea/testData/quickfix/migration/conflictingExtension")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DeleteRedundantExtension extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInDeleteRedundantExtension() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/deleteRedundantExtension"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
public static class ConflictingExtension extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInConflictingExtension() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/conflictingExtension"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
}
@TestMetadata("removeImports.before.Main.kt")
public void testRemoveImports() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/removeImports.before.Main.kt");
doTestWithExtraFile(fileName);
}
@TestMetadata("removeImportsOverloads.before.Main.kt")
public void testRemoveImportsOverloads() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/removeImportsOverloads.before.Main.kt");
doTestWithExtraFile(fileName);
}
}
@@ -3923,83 +3923,89 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("idea/testData/quickfix/migration/deleteRedundantExtension")
@TestMetadata("idea/testData/quickfix/migration/conflictingExtension")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DeleteRedundantExtension extends AbstractQuickFixTest {
public void testAllFilesPresentInDeleteRedundantExtension() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/deleteRedundantExtension"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
public static class ConflictingExtension extends AbstractQuickFixTest {
public void testAllFilesPresentInConflictingExtension() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/conflictingExtension"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("explicitThis.kt")
public void testExplicitThis() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/explicitThis.kt");
doTest(fileName);
}
@TestMetadata("markHiddenAndDeprecated.kt")
public void testMarkHiddenAndDeprecated() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/markHiddenAndDeprecated.kt");
doTest(fileName);
}
@TestMetadata("memberExtension.kt")
public void testMemberExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/memberExtension.kt");
doTest(fileName);
}
@TestMetadata("returnInGetter.kt")
public void testReturnInGetter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/returnInGetter.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/simple.kt");
doTest(fileName);
}
@TestMetadata("valInsteadOfVar.kt")
public void testValInsteadOfVar() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/valInsteadOfVar.kt");
doTest(fileName);
}
@TestMetadata("varInsteadOfVal.kt")
public void testVarInsteadOfVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/varInsteadOfVal.kt");
doTest(fileName);
}
@TestMetadata("withSetter.kt")
public void testWithSetter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/withSetter.kt");
doTest(fileName);
}
@TestMetadata("wrongExplicitThis.kt")
public void testWrongExplicitThis() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/wrongExplicitThis.kt");
doTest(fileName);
}
@TestMetadata("wrongExplicitThis2.kt")
public void testWrongExplicitThis2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/wrongExplicitThis2.kt");
doTest(fileName);
}
@TestMetadata("wrongGetter.kt")
public void testWrongGetter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/wrongGetter.kt");
doTest(fileName);
}
@TestMetadata("wrongGetter2.kt")
public void testWrongGetter2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/wrongGetter2.kt");
doTest(fileName);
}
@TestMetadata("wrongSetter.kt")
public void testWrongSetter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt");
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/conflictingExtension/wrongSetter.kt");
doTest(fileName);
}
}