From 859128744ed134817b31854ef5109c9574456a1e Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Thu, 28 May 2015 20:28:56 +0300 Subject: [PATCH] Fixed DeprecatedSymbolUsageInWholeProjectFix --- .../quickfix/DeprecatedSymbolUsageFixBase.kt | 20 +++++-------- .../DeprecatedSymbolUsageInWholeProjectFix.kt | 7 ++--- .../quickfix/ReplaceWithAnnotationAnalyzer.kt | 29 +++++++------------ .../wholeProject/function.after.kt | 5 ++++ .../wholeProject/function.before.Main.kt | 5 ++++ .../wholeProject/property.after.1.kt | 7 ++++- .../property.after.Declarations.kt | 2 ++ .../wholeProject/property.before.1.kt | 3 ++ .../property.before.Declarations.kt | 2 ++ 9 files changed, 44 insertions(+), 36 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt index 06c49148092..e2a3fde076c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageFixBase.kt @@ -152,10 +152,6 @@ public abstract class DeprecatedSymbolUsageFixBase( receiver?.mark(RECEIVER_VALUE_KEY) - for ((parameter, usages) in replacement.parameterUsages.entrySet()) { - usages.forEach { it.put(PARAMETER_USAGE_KEY, parameter) } - } - //TODO: this@ for (thisExpression in replacement.expression.collectDescendantsOfType()) { if (receiver != null) { @@ -179,8 +175,10 @@ public abstract class DeprecatedSymbolUsageFixBase( argument.expression.put(PARAMETER_VALUE_KEY, parameter) - val originalParameter = parameter.getOriginal() - val usages = replacement.expression.collectDescendantsOfType { it[PARAMETER_USAGE_KEY] == originalParameter } + val parameterName = parameter.getName() + val usages = replacement.expression.collectDescendantsOfType { + it[ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY] == parameterName + } usages.forEach { if (argument.isNamed) { (it.getParent() as? JetValueArgument)?.mark(MAKE_ARGUMENT_NAMED_KEY) @@ -293,7 +291,6 @@ public abstract class DeprecatedSymbolUsageFixBase( val expression: JetExpression, val wrapped: JetExpression, val expressionType: JetType?, - val isDefaultValue: Boolean = false, val isNamed: Boolean = false) private fun argumentForParameter( @@ -320,7 +317,7 @@ public abstract class DeprecatedSymbolUsageFixBase( val (expression, parameterUsages) = defaultValue for ((param, usages) in parameterUsages) { - usages.forEach { it.put(PARAMETER_USAGE_KEY, param) } + usages.forEach { it.put(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY, param.getName()) } } // we temporary wrap default values into parenthesis so that we can safely mark them with DEFAULT_PARAMETER_VALUE_KEY @@ -328,9 +325,9 @@ public abstract class DeprecatedSymbolUsageFixBase( wrapped.mark(DEFAULT_PARAMETER_VALUE_KEY) // clean up user data in original - expression.forEachDescendantOfType { it.clear(PARAMETER_USAGE_KEY) } + expression.forEachDescendantOfType { it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY) } - return Argument(wrapped.getExpression()!!, wrapped, null/*TODO*/, isDefaultValue = true) + return Argument(wrapped.getExpression()!!, wrapped, null/*TODO*/) } is VarargValueArgument -> { @@ -397,7 +394,7 @@ public abstract class DeprecatedSymbolUsageFixBase( // clean up user data it.forEachDescendantOfType { it.clear(USER_CODE_KEY) - it.clear(PARAMETER_USAGE_KEY) + it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY) it.clear(PARAMETER_VALUE_KEY) it.clear(RECEIVER_VALUE_KEY) it.clear(DEFAULT_PARAMETER_VALUE_KEY) @@ -589,7 +586,6 @@ public abstract class DeprecatedSymbolUsageFixBase( // keys below are used on expressions private val USER_CODE_KEY = Key("USER_CODE") - private val PARAMETER_USAGE_KEY = Key("PARAMETER_USAGE") private val PARAMETER_VALUE_KEY = Key("PARAMETER_VALUE") private val RECEIVER_VALUE_KEY = Key("RECEIVER_VALUE") private val DEFAULT_PARAMETER_VALUE_KEY = Key("DEFAULT_PARAMETER_VALUE") diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageInWholeProjectFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageInWholeProjectFix.kt index 1f25bd213db..e1329103e6c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageInWholeProjectFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedSymbolUsageInWholeProjectFix.kt @@ -127,17 +127,16 @@ public class DeprecatedSymbolUsageInWholeProjectFix( private fun replaceUsages(project: Project, usages: Collection, replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression) { UIUtil.invokeLaterIfNeeded { - var replacedCount = 0 project.executeCommand(getText()) { runWriteAction { for (usage in usages) { try { if (!usage.isValid()) continue // TODO: nested calls val bindingContext = usage.analyze(BodyResolveMode.PARTIAL) - val resolvedCall = element.getResolvedCall(bindingContext) ?: continue + val resolvedCall = usage.getResolvedCall(bindingContext) ?: continue if (!resolvedCall.getStatus().isSuccess()) continue - DeprecatedSymbolUsageFixBase.performReplacement(usage, bindingContext, resolvedCall, replacement) - replacedCount++ + // copy replacement expression because it is modified by performReplacement + DeprecatedSymbolUsageFixBase.performReplacement(usage, bindingContext, resolvedCall, replacement.copy()) } catch (e: Throwable) { LOG.error(e) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt index 4e13397a48c..97482a7d1c8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt @@ -26,16 +26,14 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.asExpression +import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType -import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression -import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -54,11 +52,14 @@ import java.util.LinkedHashSet data class ReplaceWith(val expression: String, vararg val imports: String) object ReplaceWithAnnotationAnalyzer { + public val PARAMETER_USAGE_KEY: Key = Key("PARAMETER_USAGE") + public data class ReplacementExpression( val expression: JetExpression, - val descriptorsToImport: Collection, - val parameterUsages: Map> - ) + val descriptorsToImport: Collection + ) { + fun copy() = ReplacementExpression(expression.copied(), descriptorsToImport) + } public fun analyze( annotation: ReplaceWith, @@ -99,8 +100,6 @@ object ReplaceWithAnnotationAnalyzer { val receiversToAdd = ArrayList>() - val parameterUsageKey = Key("parameterUsageKey") - expression.forEachDescendantOfType { expression -> val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType @@ -110,7 +109,7 @@ object ReplaceWithAnnotationAnalyzer { if (expression.getReceiverExpression() == null) { if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) { - expression.putCopyableUserData(parameterUsageKey, target) + expression.putCopyableUserData(PARAMETER_USAGE_KEY, target.getName()) } val resolvedCall = expression.getResolvedCall(bindingContext) @@ -138,15 +137,7 @@ object ReplaceWithAnnotationAnalyzer { } } - val parameterUsages = symbolDescriptor.getValueParameters() - .map { parameter -> parameter to expression.collectDescendantsOfType { it.getCopyableUserData(parameterUsageKey) == parameter } } - .toMap() - - expression.forEachDescendantOfType { - it.putCopyableUserData(parameterUsageKey, null) - } - - return ReplacementExpression(expression, descriptorsToImport, parameterUsages) + return ReplacementExpression(expression, descriptorsToImport) } private fun getResolutionScope(descriptor: DeclarationDescriptor): JetScope { diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.after.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.after.kt index 4d1539edeb6..a6af62825fc 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.after.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.after.kt @@ -5,4 +5,9 @@ import pack.oldFun fun foo() { newFun(0 + 1) + newFun(2 + 1) +} + +fun bar() { + newFun(3 + 1) } diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.before.Main.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.before.Main.kt index 0e23a9bd7d4..ea23142a37f 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.before.Main.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/function.before.Main.kt @@ -4,4 +4,9 @@ import pack.oldFun fun foo() { oldFun(0) + oldFun(2) +} + +fun bar() { + oldFun(3) } diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.1.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.1.kt index 6cea475e1c2..23bff9ff902 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.1.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.1.kt @@ -1,3 +1,8 @@ +import pack.newProp + fun x() { - pack.bar(pack.newProp) + pack.bar(newProp) } + +val v1 = newProp +val v2 = newProp diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.Declarations.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.Declarations.kt index 7be0078f90f..e8143bfff49 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.Declarations.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.after.Declarations.kt @@ -3,5 +3,7 @@ package pack @deprecated("", ReplaceWith("newProp")) val oldProp: String = "" +val newProp: String = "" + fun foo(s: String){} fun bar(s: String){} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.1.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.1.kt index eec52b0c439..e8d87880470 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.1.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.1.kt @@ -1,3 +1,6 @@ fun x() { pack.bar(pack.oldProp) } + +val v1 = pack.oldProp +val v2 = pack.oldProp diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.Declarations.kt b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.Declarations.kt index 7be0078f90f..e8143bfff49 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.Declarations.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/wholeProject/property.before.Declarations.kt @@ -3,5 +3,7 @@ package pack @deprecated("", ReplaceWith("newProp")) val oldProp: String = "" +val newProp: String = "" + fun foo(s: String){} fun bar(s: String){}