DeprecatedSymbolUsageFix: refactored code for easier handling of optional arguments
This commit is contained in:
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.core.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.core.OptionalParametersHelper
|
||||
import org.jetbrains.kotlin.idea.core.asExpression
|
||||
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.JetNameValidator
|
||||
import org.jetbrains.kotlin.idea.intentions.setType
|
||||
@@ -182,10 +179,14 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
it[ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY] == parameterName
|
||||
}
|
||||
usages.forEach {
|
||||
val usageArgument = it.getParent() as? JetValueArgument
|
||||
if (argument.isNamed) {
|
||||
(it.getParent() as? JetValueArgument)?.mark(MAKE_ARGUMENT_NAMED_KEY)
|
||||
usageArgument?.mark(MAKE_ARGUMENT_NAMED_KEY)
|
||||
}
|
||||
it.replace(argument.wrapped)
|
||||
if (argument.isDefaultValue) {
|
||||
usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
it.replace(argument.expression)
|
||||
}
|
||||
|
||||
//TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context
|
||||
@@ -195,8 +196,6 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
}
|
||||
|
||||
unwrapDefaultValues(replacement.expression)
|
||||
|
||||
val wrapper = ConstructedExpressionWrapper(replacement.expression, expressionToBeReplaced, bindingContext)
|
||||
|
||||
if (qualifiedExpression is JetSafeQualifiedExpression) {
|
||||
@@ -293,9 +292,9 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
|
||||
private class Argument(
|
||||
val expression: JetExpression,
|
||||
val wrapped: JetExpression,
|
||||
val expressionType: JetType?,
|
||||
val isNamed: Boolean = false)
|
||||
val isNamed: Boolean = false,
|
||||
val isDefaultValue: Boolean = false)
|
||||
|
||||
private fun argumentForParameter(
|
||||
parameter: ValueParameterDescriptor,
|
||||
@@ -311,7 +310,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
if (valueArgument is FunctionLiteralArgument) {
|
||||
expression.mark(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
|
||||
}
|
||||
return Argument(expression, expression, bindingContext.getType(expression), isNamed = valueArgument.isNamed())
|
||||
return Argument(expression, bindingContext.getType(expression), isNamed = valueArgument.isNamed())
|
||||
}
|
||||
|
||||
is DefaultValueArgument -> {
|
||||
@@ -322,14 +321,12 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
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
|
||||
val wrapped = JetPsiFactory(project).createExpressionByPattern("($0)", expression) as JetParenthesizedExpression
|
||||
wrapped.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
val expressionCopy = expression.copied()
|
||||
|
||||
// clean up user data in original
|
||||
expression.forEachDescendantOfType<JetExpression> { it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY) }
|
||||
|
||||
return Argument(wrapped.getExpression()!!, wrapped, null/*TODO*/)
|
||||
return Argument(expressionCopy, null/*TODO*/, isDefaultValue = true)
|
||||
}
|
||||
|
||||
is VarargValueArgument -> {
|
||||
@@ -337,7 +334,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
val single = arguments.singleOrNull()
|
||||
if (single != null && single.getSpreadElement() != null) {
|
||||
val expression = single.getArgumentExpression()!!.marked(USER_CODE_KEY)
|
||||
return Argument(expression, expression, bindingContext.getType(expression), isNamed = single.isNamed())
|
||||
return Argument(expression, bindingContext.getType(expression), isNamed = single.isNamed())
|
||||
}
|
||||
|
||||
val elementType = parameter.getVarargElementType()!!
|
||||
@@ -353,7 +350,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
appendFixedText(")")
|
||||
}
|
||||
return Argument(expression, expression, parameter.getType(), isNamed = single?.isNamed() ?: false)
|
||||
return Argument(expression, parameter.getType(), isNamed = single?.isNamed() ?: false)
|
||||
}
|
||||
|
||||
else -> error("Unknown argument type: $resolvedArgument")
|
||||
@@ -399,11 +396,11 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY)
|
||||
it.clear(PARAMETER_VALUE_KEY)
|
||||
it.clear(RECEIVER_VALUE_KEY)
|
||||
it.clear(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
it.clear(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
|
||||
}
|
||||
it.forEachDescendantOfType<JetValueArgument> {
|
||||
it.clear(MAKE_ARGUMENT_NAMED_KEY)
|
||||
it.clear(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,6 +431,11 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
val name = argumentMatch.valueParameter.getName().asString()
|
||||
//TODO: not always correct for vararg's
|
||||
val newArgument = psiFactory.createArgument(argument.getArgumentExpression()!!, name, argument.getSpreadElement() != null)
|
||||
|
||||
if (argument[DEFAULT_PARAMETER_VALUE_KEY]) {
|
||||
newArgument.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
|
||||
argument.replace(newArgument)
|
||||
}
|
||||
}
|
||||
@@ -445,9 +447,8 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
val argumentsToDrop = ArrayList<ValueArgument>()
|
||||
|
||||
// we drop only those arguments that added to the code from some parameter's default
|
||||
fun canDropArgument(argument: ValueArgument) = argument.getArgumentExpression()!![DEFAULT_PARAMETER_VALUE_KEY]
|
||||
fun canDropArgument(argument: ValueArgument) = (argument as JetValueArgument)[DEFAULT_PARAMETER_VALUE_KEY]
|
||||
|
||||
//TODO: other types of calls
|
||||
result.forEachDescendantOfType<JetCallExpression> { callExpression ->
|
||||
val resolvedCall = callExpression.getResolvedCall(newBindingContext) ?: return@forEachDescendantOfType
|
||||
|
||||
@@ -467,25 +468,6 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
}
|
||||
|
||||
private fun unwrapDefaultValues(expression: JetExpression) {
|
||||
val values = expression.collectDescendantsOfType<JetParenthesizedExpression> {
|
||||
it[DEFAULT_PARAMETER_VALUE_KEY] && !it.getParent()[DEFAULT_PARAMETER_VALUE_KEY]
|
||||
}
|
||||
|
||||
fun JetParenthesizedExpression.unwrap(): JetExpression {
|
||||
if (!this[DEFAULT_PARAMETER_VALUE_KEY]) return this
|
||||
var inner = getExpression()!!
|
||||
if (inner is JetParenthesizedExpression) {
|
||||
inner = inner.unwrap()
|
||||
}
|
||||
val result = replace(inner) as JetExpression
|
||||
result.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
return result
|
||||
}
|
||||
|
||||
values.forEach { it.unwrap() }
|
||||
}
|
||||
|
||||
private fun arrayOfFunctionName(elementType: JetType): String {
|
||||
return when {
|
||||
KotlinBuiltIns.isInt(elementType) -> "kotlin.intArrayOf"
|
||||
@@ -589,11 +571,11 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
private val USER_CODE_KEY = Key<Unit>("USER_CODE")
|
||||
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")
|
||||
private val WAS_FUNCTION_LITERAL_ARGUMENT_KEY = Key<Unit>("WAS_FUNCTION_LITERAL_ARGUMENT")
|
||||
|
||||
// this key is used on JetValueArgument
|
||||
// these keys are used on JetValueArgument
|
||||
private val MAKE_ARGUMENT_NAMED_KEY = Key<Unit>("MAKE_ARGUMENT_NAMED")
|
||||
private val DEFAULT_PARAMETER_VALUE_KEY = Key<Unit>("DEFAULT_PARAMETER_VALUE")
|
||||
}
|
||||
|
||||
class ConstructedExpressionWrapper(
|
||||
|
||||
Reference in New Issue
Block a user