Annotations supported
#KT-8912 Fixed
This commit is contained in:
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||
@@ -60,9 +59,7 @@ public class DeprecatedSymbolUsageFix(
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val nameExpression = diagnostic.psiElement as? JetSimpleNameExpression ?: return null
|
||||
val descriptor = Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.cast(diagnostic).a
|
||||
val replacement = DeprecatedSymbolUsageFixBase.replaceWithPattern(descriptor, nameExpression.project) ?: return null
|
||||
val (nameExpression, replacement) = DeprecatedSymbolUsageFixBase.extractDataFromDiagnostic(diagnostic) ?: return null
|
||||
return DeprecatedSymbolUsageFix(nameExpression, replacement)
|
||||
}
|
||||
|
||||
|
||||
+33
-1
@@ -22,8 +22,11 @@ import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.core.OptionalParametersHelper
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction
|
||||
import org.jetbrains.kotlin.psi.JetConstructorCalleeExpression
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -56,7 +59,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
editor: Editor?)
|
||||
|
||||
companion object {
|
||||
public fun replaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? {
|
||||
fun replaceWithPattern(descriptor: DeclarationDescriptor, project: Project): ReplaceWith? {
|
||||
val annotationClass = descriptor.builtIns.deprecatedAnnotation
|
||||
val annotation = descriptor.annotations.findAnnotation(DescriptorUtils.getFqNameSafe(annotationClass)) ?: return null
|
||||
val replaceWithValue = annotation.argumentValue(kotlin.deprecated::replaceWith.name) as? AnnotationDescriptor ?: return null
|
||||
@@ -72,5 +75,34 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
|
||||
return ReplaceWith(pattern, *imports.toTypedArray())
|
||||
}
|
||||
|
||||
data class Data(
|
||||
val nameExpression: JetSimpleNameExpression,
|
||||
val replaceWith: ReplaceWith,
|
||||
val descriptor: DeclarationDescriptor
|
||||
)
|
||||
|
||||
fun extractDataFromDiagnostic(deprecatedDiagnostic: Diagnostic): Data? {
|
||||
val psiElement = deprecatedDiagnostic.psiElement
|
||||
|
||||
//TODO: compiler crash here
|
||||
/*
|
||||
val nameExpression: JetSimpleNameExpression = when (psiElement) {
|
||||
is JetSimpleNameExpression -> psiElement
|
||||
is JetConstructorCalleeExpression -> psiElement.constructorReferenceExpression
|
||||
else -> null
|
||||
} ?: return null
|
||||
*/
|
||||
val nameExpression: JetSimpleNameExpression = (if (psiElement is JetSimpleNameExpression)
|
||||
psiElement
|
||||
else if (psiElement is JetConstructorCalleeExpression)
|
||||
psiElement.constructorReferenceExpression
|
||||
else
|
||||
null) ?: return null
|
||||
|
||||
val descriptor = Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.cast(deprecatedDiagnostic).a
|
||||
val replacement = DeprecatedSymbolUsageFixBase.replaceWithPattern(descriptor, nameExpression.project) ?: return null
|
||||
return Data(nameExpression, replacement, descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-11
@@ -28,7 +28,6 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||
@@ -36,10 +35,7 @@ import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||
import org.jetbrains.kotlin.psi.JetProperty
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.NameShortness
|
||||
@@ -61,12 +57,11 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
||||
|
||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||
if (!super.isAvailable(project, editor, file)) return false
|
||||
val targetPsiElement = element.mainReference.resolve()
|
||||
return targetPsiElement is JetNamedFunction || targetPsiElement is JetProperty //TODO
|
||||
return targetPsiElement() != null
|
||||
}
|
||||
|
||||
override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) {
|
||||
val psiElement = element.mainReference.resolve()!!
|
||||
val psiElement = targetPsiElement()!!
|
||||
|
||||
ProgressManager.getInstance().run(
|
||||
object : Task.Modal(project, "Applying '$text'", true) {
|
||||
@@ -82,6 +77,16 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
||||
})
|
||||
}
|
||||
|
||||
private fun targetPsiElement(): JetDeclaration? {
|
||||
val referenceTarget = element.mainReference.resolve()
|
||||
return when (referenceTarget) {
|
||||
is JetNamedFunction -> referenceTarget
|
||||
is JetProperty -> referenceTarget
|
||||
is JetConstructor<*> -> referenceTarget.getContainingClassOrObject() //TODO: constructor can be deprecated itself
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceUsages(project: Project, usages: Collection<JetSimpleNameExpression>, replacementStrategy: UsageReplacementStrategy) {
|
||||
UIUtil.invokeLaterIfNeeded {
|
||||
project.executeWriteCommand(text) {
|
||||
@@ -127,9 +132,7 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
||||
}
|
||||
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val nameExpression = diagnostic.psiElement as? JetSimpleNameExpression ?: return null
|
||||
val descriptor = Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.cast(diagnostic).a
|
||||
val replacement = DeprecatedSymbolUsageFixBase.replaceWithPattern(descriptor, nameExpression.project) ?: return null
|
||||
val (nameExpression, replacement, descriptor) = DeprecatedSymbolUsageFixBase.extractDataFromDiagnostic(diagnostic) ?: return null
|
||||
val descriptorName = RENDERER.render(descriptor)
|
||||
return DeprecatedSymbolUsageInWholeProjectFix(nameExpression, replacement, "Replace usages of '$descriptorName' in whole project")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package test
|
||||
|
||||
@deprecated("Replace with bar", ReplaceWith("test.Bar"))
|
||||
annotation class Foo
|
||||
|
||||
annotation class Bar
|
||||
|
||||
@Foo<caret> class C {}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package test
|
||||
|
||||
@deprecated("Replace with bar", ReplaceWith("test.Bar"))
|
||||
annotation class Foo
|
||||
|
||||
annotation class Bar
|
||||
|
||||
@Bar class C {}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package test
|
||||
|
||||
@deprecated("Replace with bar", ReplaceWith("test.Bar"))
|
||||
annotation class Foo(val p1: String, val p2: Int)
|
||||
|
||||
annotation class Bar(val p1: String, val p2: Int)
|
||||
|
||||
@Foo<caret>("", 1) class C {}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package test
|
||||
|
||||
@deprecated("Replace with bar", ReplaceWith("test.Bar"))
|
||||
annotation class Foo(val p1: String, val p2: Int)
|
||||
|
||||
annotation class Bar(val p1: String, val p2: Int)
|
||||
|
||||
@Bar("", 1) class C {}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
package dependency
|
||||
|
||||
@deprecated("", ReplaceWith("dependency.NewAnnotation"))
|
||||
annotation class OldAnnotation(val p: Int = 0)
|
||||
|
||||
annotation class NewAnnotation(val p: Int = 0, val newP: String = "")
|
||||
|
||||
@NewAnnotation class C
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package x
|
||||
|
||||
import dependency.*
|
||||
|
||||
annotation class A(val a: NewAnnotation)
|
||||
|
||||
@A(NewAnnotation()) class Y
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace usages of 'OldAnnotation' in whole project" "true"
|
||||
|
||||
package test
|
||||
|
||||
import dependency.NewAnnotation
|
||||
|
||||
fun foo(a: NewAnnotation) {
|
||||
}
|
||||
|
||||
@NewAnnotation(1) class X
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
package dependency
|
||||
|
||||
@deprecated("", ReplaceWith("dependency.NewAnnotation"))
|
||||
annotation class OldAnnotation(val p: Int = 0)
|
||||
|
||||
annotation class NewAnnotation(val p: Int = 0, val newP: String = "")
|
||||
|
||||
@OldAnnotation class C
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace usages of 'OldAnnotation' in whole project" "true"
|
||||
|
||||
package test
|
||||
|
||||
import dependency.OldAnnotation
|
||||
|
||||
fun foo(a: OldAnnotation) {
|
||||
}
|
||||
|
||||
@<caret>OldAnnotation(1) class X
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with 'test.Bar'" "true"
|
||||
|
||||
package x
|
||||
|
||||
import dependency.*
|
||||
|
||||
annotation class A(val a: OldAnnotation)
|
||||
|
||||
@A(OldAnnotation()) class Y
|
||||
@@ -919,6 +919,12 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
public void testAllFilesPresentInClassUsages() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/classUsages"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("inWholeProject.before.Main.kt")
|
||||
public void testInWholeProject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/inWholeProject.before.Main.kt");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/imports")
|
||||
|
||||
@@ -3312,6 +3312,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/classUsages"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotation1.kt")
|
||||
public void testAnnotation1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/annotation1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("annotation2.kt")
|
||||
public void testAnnotation2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/annotation2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constructorUsage1.kt")
|
||||
public void testConstructorUsage1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/constructorUsage1.kt");
|
||||
|
||||
Reference in New Issue
Block a user