Fixed DeprecatedSymbolUsageInWholeProjectFix

This commit is contained in:
Valentin Kipyatkov
2015-05-28 20:28:56 +03:00
parent eef0e8e447
commit 859128744e
9 changed files with 44 additions and 36 deletions
@@ -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<JetThisExpression>()) {
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<JetExpression> { it[PARAMETER_USAGE_KEY] == originalParameter }
val parameterName = parameter.getName()
val usages = replacement.expression.collectDescendantsOfType<JetExpression> {
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<JetExpression> { it.clear(PARAMETER_USAGE_KEY) }
expression.forEachDescendantOfType<JetExpression> { 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<JetExpression> {
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<Unit>("USER_CODE")
private val PARAMETER_USAGE_KEY = Key<ValueParameterDescriptor>("PARAMETER_USAGE")
private val PARAMETER_VALUE_KEY = Key<ValueParameterDescriptor>("PARAMETER_VALUE")
private val RECEIVER_VALUE_KEY = Key<Unit>("RECEIVER_VALUE")
private val DEFAULT_PARAMETER_VALUE_KEY = Key<Unit>("DEFAULT_PARAMETER_VALUE")
@@ -127,17 +127,16 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
private fun replaceUsages(project: Project, usages: Collection<JetSimpleNameExpression>, 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)
@@ -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<Name> = Key("PARAMETER_USAGE")
public data class ReplacementExpression(
val expression: JetExpression,
val descriptorsToImport: Collection<DeclarationDescriptor>,
val parameterUsages: Map<ValueParameterDescriptor, Collection<JetExpression>>
)
val descriptorsToImport: Collection<DeclarationDescriptor>
) {
fun copy() = ReplacementExpression(expression.copied(), descriptorsToImport)
}
public fun analyze(
annotation: ReplaceWith,
@@ -99,8 +100,6 @@ object ReplaceWithAnnotationAnalyzer {
val receiversToAdd = ArrayList<Pair<JetExpression, JetExpression>>()
val parameterUsageKey = Key<ValueParameterDescriptor>("parameterUsageKey")
expression.forEachDescendantOfType<JetSimpleNameExpression> { 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<JetExpression> { it.getCopyableUserData(parameterUsageKey) == parameter } }
.toMap()
expression.forEachDescendantOfType<JetExpression> {
it.putCopyableUserData(parameterUsageKey, null)
}
return ReplacementExpression(expression, descriptorsToImport, parameterUsages)
return ReplacementExpression(expression, descriptorsToImport)
}
private fun getResolutionScope(descriptor: DeclarationDescriptor): JetScope {
@@ -5,4 +5,9 @@ import pack.oldFun
fun foo() {
<caret>newFun(0 + 1)
newFun(2 + 1)
}
fun bar() {
newFun(3 + 1)
}
@@ -4,4 +4,9 @@ import pack.oldFun
fun foo() {
<caret>oldFun(0)
oldFun(2)
}
fun bar() {
oldFun(3)
}
@@ -1,3 +1,8 @@
import pack.newProp
fun x() {
pack.bar(pack.newProp)
pack.bar(newProp)
}
val v1 = newProp
val v2 = newProp
@@ -3,5 +3,7 @@ package pack
@deprecated("", ReplaceWith("newProp"))
val oldProp: String = ""
val newProp: String = ""
fun foo(s: String){}
fun bar(s: String){}
@@ -1,3 +1,6 @@
fun x() {
pack.bar(pack.oldProp)
}
val v1 = pack.oldProp
val v2 = pack.oldProp
@@ -3,5 +3,7 @@ package pack
@deprecated("", ReplaceWith("newProp"))
val oldProp: String = ""
val newProp: String = ""
fun foo(s: String){}
fun bar(s: String){}