DeprecatedSymbolUsageFix: support for optional parameters (not complete)
This commit is contained in:
@@ -66,6 +66,7 @@ public class JetValueArgumentList extends JetElementImpl {
|
||||
}
|
||||
|
||||
public void removeArgument(@NotNull JetValueArgument argument) {
|
||||
assert argument.getParent() == this;
|
||||
EditCommaSeparatedListHelper.INSTANCE$.removeItem(argument);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,33 +546,54 @@ public fun PsiElement.getElementTextWithContext(): String {
|
||||
|
||||
// Calls `block` on each descendant of T type
|
||||
// Note, that calls happen in order of DFS-exit, so deeper nodes are applied earlier
|
||||
inline fun <reified T : JetElement> forEachDescendantOfTypeVisitor(
|
||||
noinline block: (T) -> Unit
|
||||
): JetVisitorVoid =
|
||||
object : JetTreeVisitorVoid() {
|
||||
override fun visitJetElement(element: JetElement) {
|
||||
super.visitJetElement(element)
|
||||
if (element is T) {
|
||||
block(element)
|
||||
}
|
||||
public inline fun <reified T : JetElement> forEachDescendantOfTypeVisitor(noinline block: (T) -> Unit): JetVisitorVoid {
|
||||
return object : JetTreeVisitorVoid() {
|
||||
override fun visitJetElement(element: JetElement) {
|
||||
super.visitJetElement(element)
|
||||
if (element is T) {
|
||||
block(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : JetElement, R> flatMapDescendantsOfTypeVisitor(
|
||||
accumulator: MutableCollection<R>,
|
||||
noinline map: (T) -> Collection<R>
|
||||
): JetVisitorVoid = forEachDescendantOfTypeVisitor<T> { accumulator.addAll(map(it)) }
|
||||
public inline fun <reified T : JetElement, R> flatMapDescendantsOfTypeVisitor(accumulator: MutableCollection<R>, noinline map: (T) -> Collection<R>): JetVisitorVoid {
|
||||
return forEachDescendantOfTypeVisitor<T> { accumulator.addAll(map(it)) }
|
||||
}
|
||||
|
||||
inline fun <reified T : JetElement> PsiElement.forEachDescendantsOfType(noinline block: (T) -> Unit) =
|
||||
accept(forEachDescendantOfTypeVisitor(block))
|
||||
|
||||
inline fun <reified T : JetElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean): Boolean {
|
||||
var result = false
|
||||
accept(forEachDescendantOfTypeVisitor<T> {
|
||||
if (!result && predicate(it)) {
|
||||
result = true
|
||||
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
super.visitElement(element)
|
||||
if (element is T) {
|
||||
action(element)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean): Boolean {
|
||||
var result = false
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (result) return
|
||||
if (element is T && predicate(element)) {
|
||||
result = true
|
||||
return
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): Collection<T> {
|
||||
val result = ArrayList<T>()
|
||||
forEachDescendantOfType<T> {
|
||||
if (predicate(it)) {
|
||||
result.add(it)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -636,21 +657,3 @@ public fun JetExpression.getAnnotationEntries(): List<JetAnnotationEntry> {
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: it can be default value for parameter but it's not supported yet by the compiler
|
||||
public inline fun <reified TElement> PsiElement.collectElementsOfType(): Collection<TElement> {
|
||||
return collectElementsOfType { true }
|
||||
}
|
||||
|
||||
public inline fun <reified TElement> PsiElement.collectElementsOfType(@inlineOptions(InlineOption.ONLY_LOCAL_RETURN) predicate: (TElement) -> Boolean): Collection<TElement> {
|
||||
val result = ArrayList<TElement>()
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (element is TElement && predicate(element)) {
|
||||
result.add(element)
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.psi.JetParameter
|
||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.copied
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
|
||||
public object OptionalParametersHelper {
|
||||
public fun detectArgumentsToDropForDefaults(
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
project: Project,
|
||||
canDrop: (ValueArgument) -> Boolean = { true }
|
||||
): Collection<ValueArgument> {
|
||||
if (!resolvedCall.getStatus().isSuccess()) return emptyList()
|
||||
val descriptor = resolvedCall.getResultingDescriptor()
|
||||
|
||||
val parameterToDefaultValue = descriptor.getValueParameters()
|
||||
.map { parameter -> defaultParameterValue(parameter, project)?.let { parameter to it } }
|
||||
.filterNotNull()
|
||||
.toMap()
|
||||
if (parameterToDefaultValue.isEmpty()) return emptyList()
|
||||
|
||||
val arguments = resolvedCall.getCall().getValueArguments()
|
||||
val argumentsToDrop = ArrayList<ValueArgument>()
|
||||
for (argument in arguments.reverse()) {
|
||||
if (!canDrop(argument)) break // TODO: not correct because of named arguments
|
||||
if (!argument.matchesDefault(resolvedCall, parameterToDefaultValue)) break // TODO: not correct because of named arguments
|
||||
argumentsToDrop.add(argument)
|
||||
}
|
||||
return argumentsToDrop
|
||||
}
|
||||
|
||||
private fun ValueArgument.matchesDefault(resolvedCall: ResolvedCall<out CallableDescriptor>, parameterToDefaultValue: Map<ValueParameterDescriptor, DefaultValue>): Boolean {
|
||||
val parameter = resolvedCall.getParameterForArgument(this) ?: return false
|
||||
val defaultValue = parameterToDefaultValue[parameter] ?: return false
|
||||
val expression = defaultValue.substituteArguments(resolvedCall)
|
||||
val argumentExpression = getArgumentExpression()!!
|
||||
return argumentExpression.getText() == expression.getText() //TODO
|
||||
}
|
||||
|
||||
private fun DefaultValue.substituteArguments(resolvedCall: ResolvedCall<out CallableDescriptor>): JetExpression {
|
||||
if (parameterUsages.isEmpty()) return expression
|
||||
|
||||
val key = Key<JetExpression>("SUBSTITUTION")
|
||||
|
||||
for ((parameter, usages) in parameterUsages) {
|
||||
val resolvedArgument = resolvedCall.getValueArguments()[parameter]!!
|
||||
if (resolvedArgument is ExpressionValueArgument) {
|
||||
val argument = resolvedArgument.getValueArgument()!!.getArgumentExpression()!!
|
||||
usages.forEach { it.putCopyableUserData(key, argument) }
|
||||
}
|
||||
//TODO: vararg
|
||||
}
|
||||
|
||||
var expressionCopy = expression.copied()
|
||||
|
||||
expression.forEachDescendantOfType<JetExpression> { it.putCopyableUserData(key, null) }
|
||||
|
||||
val replacements = ArrayList<Pair<JetExpression, JetExpression>>()
|
||||
expressionCopy.forEachDescendantOfType<JetExpression> {
|
||||
val replacement = it.getCopyableUserData(key)
|
||||
if (replacement != null) {
|
||||
replacements.add(it to replacement)
|
||||
}
|
||||
}
|
||||
|
||||
for ((expression, replacement) in replacements) {
|
||||
val replaced = expression.replace(replacement) as JetExpression
|
||||
if (expression == expressionCopy) {
|
||||
expressionCopy = replaced
|
||||
}
|
||||
}
|
||||
|
||||
return expressionCopy
|
||||
}
|
||||
|
||||
public data class DefaultValue(
|
||||
public val expression: JetExpression,
|
||||
public val parameterUsages: Map<ValueParameterDescriptor, Collection<JetExpression>>
|
||||
)
|
||||
|
||||
//TODO: handle imports
|
||||
//TODO: handle implicit receivers
|
||||
public fun defaultParameterValue(parameter: ValueParameterDescriptor, project: Project): DefaultValue? {
|
||||
if (!parameter.hasDefaultValue()) return null
|
||||
//TODO: parameter in overriding method!
|
||||
val sourceParameter = DescriptorToSourceUtilsIde.getAnyDeclaration(project, parameter) as? JetParameter ?: return null
|
||||
//TODO: use JetSourceNavigationHelper
|
||||
val expression = sourceParameter.getDefaultValue() ?: return null
|
||||
|
||||
val allParameters = (parameter.getContainingDeclaration() as CallableDescriptor).getValueParameters().toSet()
|
||||
|
||||
val parameterUsages = HashMap<ValueParameterDescriptor, MutableCollection<JetExpression>>()
|
||||
|
||||
val bindingContext = expression.analyze()
|
||||
expression.forEachDescendantOfType<JetSimpleNameExpression> {
|
||||
val target = bindingContext[BindingContext.REFERENCE_TARGET, it]
|
||||
if (target is ValueParameterDescriptor && target in allParameters) {
|
||||
parameterUsages.getOrPut(target) { ArrayList() }.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
return DefaultValue(expression, parameterUsages)
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||
import org.jetbrains.kotlin.analyzer.analyzeInContext
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -30,6 +28,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.OptionalParametersHelper
|
||||
import org.jetbrains.kotlin.idea.core.asExpression
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.JetNameValidator
|
||||
@@ -39,17 +38,18 @@ import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.renderName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectElementsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
@@ -122,7 +122,6 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression
|
||||
): JetExpression {
|
||||
var (expression, imports, parameterUsages) = replacement
|
||||
val project = element.getProject()
|
||||
val psiFactory = JetPsiFactory(project)
|
||||
val descriptor = resolvedCall.getResultingDescriptor()
|
||||
@@ -131,87 +130,100 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
val qualifiedExpression = callExpression.getParent() as? JetQualifiedExpression
|
||||
val expressionToReplace = qualifiedExpression ?: callExpression
|
||||
|
||||
var receiver = element.getReceiverExpression()
|
||||
receiver?.putCopyableUserData(USER_CODE_KEY, Unit)
|
||||
var receiver = element.getReceiverExpression()?.marked(USER_CODE_KEY)
|
||||
var receiverType = if (receiver != null) bindingContext.getType(receiver) else null
|
||||
|
||||
if (receiver == null) {
|
||||
val receiverValue = if (descriptor.isExtension) resolvedCall.getExtensionReceiver() else resolvedCall.getDispatchReceiver()
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, expressionToReplace]
|
||||
if (receiverValue is ThisReceiver && resolutionScope != null) {
|
||||
receiver = receiverValue.asExpression(resolutionScope, psiFactory)
|
||||
receiverType = receiverValue.getType()
|
||||
}
|
||||
}
|
||||
|
||||
receiver?.putCopyableUserData(FROM_THIS_KEY, Unit)
|
||||
receiver?.mark(RECEIVER_VALUE_KEY)
|
||||
|
||||
for ((parameter, usages) in replacement.parameterUsages.entrySet()) {
|
||||
usages.forEach { it.put(PARAMETER_USAGE_KEY, parameter) }
|
||||
}
|
||||
|
||||
var expression = replacement.expression
|
||||
|
||||
//TODO: this@
|
||||
for (thisExpression in expression.collectElementsOfType<JetThisExpression>()) {
|
||||
for (thisExpression in expression.collectDescendantsOfType<JetThisExpression>()) {
|
||||
if (receiver != null) {
|
||||
thisExpression.replace(receiver)
|
||||
}
|
||||
else {
|
||||
thisExpression.putCopyableUserData(FROM_THIS_KEY, Unit)
|
||||
thisExpression.mark(RECEIVER_VALUE_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
fun argumentForParameter(parameter: ValueParameterDescriptor): JetExpression? {
|
||||
//TODO: optional parameters
|
||||
val arguments = resolvedCall.getValueArguments()[parameter] ?: return null //TODO: what if not? vararg?
|
||||
return arguments.getArguments().firstOrNull()?.getArgumentExpression() //TODO: what if multiple?
|
||||
}
|
||||
@data class IntroduceValueForParameter(
|
||||
val parameter: ValueParameterDescriptor,
|
||||
val value: JetExpression,
|
||||
val valueType: JetType?)
|
||||
|
||||
val introduceValuesForParameters = ArrayList<Pair<ValueParameterDescriptor, JetExpression>>()
|
||||
val introduceValuesForParameters = ArrayList<IntroduceValueForParameter>()
|
||||
|
||||
for (parameter in descriptor.getValueParameters()) {
|
||||
val argument = argumentForParameter(parameter) ?: continue
|
||||
argument.putCopyableUserData(FROM_PARAMETER_KEY, parameter)
|
||||
argument.putCopyableUserData(USER_CODE_KEY, Unit)
|
||||
// process parameters in reverse order because default values can use previous parameters
|
||||
for (parameter in descriptor.getValueParameters().reverse()) {
|
||||
val argument = argumentForParameter(parameter, resolvedCall, bindingContext, project) ?: continue
|
||||
|
||||
val usages = parameterUsages[parameter.getOriginal()]!!
|
||||
usages.forEach { it.replace(argument) }
|
||||
argument.expression.put(PARAMETER_VALUE_KEY, parameter)
|
||||
|
||||
if (argument.shouldKeepValue(usages.size())) {
|
||||
introduceValuesForParameters.add(parameter to argument)
|
||||
val originalParameter = parameter.getOriginal()
|
||||
val usages = expression.collectDescendantsOfType<JetExpression> { it[PARAMETER_USAGE_KEY] == originalParameter }
|
||||
usages.forEach { it.replace(argument.wrapped) }
|
||||
|
||||
if (argument.expression.shouldKeepValue(usages.size())) {
|
||||
introduceValuesForParameters.add(IntroduceValueForParameter(parameter, argument.expression, argument.expressionType))
|
||||
}
|
||||
}
|
||||
|
||||
unwrapDefaultValues(expression)
|
||||
|
||||
if (qualifiedExpression is JetSafeQualifiedExpression) {
|
||||
expression = expression.wrapExpressionForSafeCall(expressionToReplace, receiver!!, bindingContext)
|
||||
expression = expression.wrapExpressionForSafeCall(expressionToReplace, receiver!!, receiverType, bindingContext)
|
||||
}
|
||||
else if (callExpression is JetBinaryExpression && callExpression.getOperationToken() == JetTokens.IDENTIFIER) {
|
||||
expression = expression.keepInfixFormIfPossible()
|
||||
}
|
||||
|
||||
if (receiver != null) {
|
||||
val thisReplaced = expression.collectElementsOfType<JetExpression> { it.getCopyableUserData(FROM_THIS_KEY) != null }
|
||||
val thisReplaced = expression.collectDescendantsOfType<JetExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
if (receiver.shouldKeepValue(thisReplaced.size())) {
|
||||
expression = expression.introduceValue(receiver, expressionToReplace, bindingContext, thisReplaced)
|
||||
expression = expression.introduceValue(receiver, receiverType, expressionToReplace, bindingContext, thisReplaced)
|
||||
}
|
||||
}
|
||||
|
||||
for ((parameter, value) in introduceValuesForParameters) {
|
||||
val usagesReplaced = expression.collectElementsOfType<JetExpression> { it.getCopyableUserData(FROM_PARAMETER_KEY) == parameter }
|
||||
expression = expression.introduceValue(value, expressionToReplace, bindingContext, usagesReplaced, nameSuggestion = parameter.getName().asString())
|
||||
for ((parameter, value, valueType) in introduceValuesForParameters) {
|
||||
val usagesReplaced = expression.collectDescendantsOfType<JetExpression> { it[PARAMETER_VALUE_KEY] == parameter }
|
||||
expression = expression.introduceValue(value, valueType, expressionToReplace, bindingContext, usagesReplaced, nameSuggestion = parameter.getName().asString())
|
||||
}
|
||||
|
||||
var result = expressionToReplace.replaced(expression)
|
||||
var result = expressionToReplace.replace(expression) as JetExpression
|
||||
|
||||
//TODO: drop import of old function (if not needed anymore)?
|
||||
|
||||
val file = result.getContainingJetFile()
|
||||
for (importFqName in imports) {
|
||||
for (importFqName in replacement.imports) {
|
||||
val descriptors = file.getResolutionFacade().resolveImportReference(file, importFqName)
|
||||
val descriptorToImport = descriptors.firstOrNull() ?: continue
|
||||
ImportInsertHelper.getInstance(project).importDescriptor(file, descriptorToImport)
|
||||
}
|
||||
|
||||
//TODO: do this earlier
|
||||
dropArgumentsForDefaultValues(result)
|
||||
|
||||
val shortenFilter = { element: PsiElement ->
|
||||
if (element.getCopyableUserData(USER_CODE_KEY) != null) {
|
||||
if (element[USER_CODE_KEY]) {
|
||||
ShortenReferences.FilterResult.SKIP
|
||||
}
|
||||
else {
|
||||
val thisReceiver = (element as? JetQualifiedExpression)?.getReceiverExpression() as? JetThisExpression
|
||||
if (thisReceiver != null && thisReceiver.getCopyableUserData(USER_CODE_KEY) != null) // don't remove explicit 'this' coming from user's code
|
||||
if (thisReceiver != null && thisReceiver[USER_CODE_KEY]) // don't remove explicit 'this' coming from user's code
|
||||
ShortenReferences.FilterResult.GO_INSIDE
|
||||
else
|
||||
ShortenReferences.FilterResult.PROCESS
|
||||
@@ -220,13 +232,13 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
result = ShortenReferences({ ShortenReferences.Options(removeThis = true) }).process(result, shortenFilter) as JetExpression
|
||||
|
||||
// clean up user data
|
||||
result.accept(object : PsiRecursiveElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
element.putCopyableUserData(USER_CODE_KEY, null)
|
||||
element.putCopyableUserData(FROM_PARAMETER_KEY, null)
|
||||
element.putCopyableUserData(FROM_THIS_KEY, null)
|
||||
}
|
||||
})
|
||||
result.forEachDescendantOfType<JetExpression> {
|
||||
it.clear(USER_CODE_KEY)
|
||||
it.clear(PARAMETER_USAGE_KEY)
|
||||
it.clear(PARAMETER_VALUE_KEY)
|
||||
it.clear(RECEIVER_VALUE_KEY)
|
||||
it.clear(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -234,12 +246,13 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
private fun JetExpression.wrapExpressionForSafeCall(
|
||||
expressionToReplace: JetExpression,
|
||||
receiver: JetExpression,
|
||||
receiverType: JetType?,
|
||||
bindingContext: BindingContext
|
||||
): JetExpression {
|
||||
val psiFactory = JetPsiFactory(this)
|
||||
val qualified = this as? JetQualifiedExpression
|
||||
if (qualified != null) {
|
||||
if (qualified.getReceiverExpression().getCopyableUserData(FROM_THIS_KEY) != null) {
|
||||
if (qualified.getReceiverExpression()[RECEIVER_VALUE_KEY]) {
|
||||
if (qualified is JetSafeQualifiedExpression) return this // already safe
|
||||
val selector = qualified.getSelectorExpression()
|
||||
if (selector != null) {
|
||||
@@ -249,8 +262,8 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
|
||||
if (expressionToReplace.isUsedAsExpression(bindingContext)) {
|
||||
val thisReplaced = this.collectElementsOfType<JetExpression> { it.getCopyableUserData(FROM_THIS_KEY) != null }
|
||||
return this.introduceValue(receiver, expressionToReplace, bindingContext, thisReplaced, safeCall = true)
|
||||
val thisReplaced = this.collectDescendantsOfType<JetExpression> { it[RECEIVER_VALUE_KEY] }
|
||||
return this.introduceValue(receiver, receiverType, expressionToReplace, bindingContext, thisReplaced, safeCall = true)
|
||||
}
|
||||
else {
|
||||
return psiFactory.createExpressionByPattern("if ($0 != null) { $1 }", receiver, this)
|
||||
@@ -260,7 +273,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
private fun JetExpression.keepInfixFormIfPossible(): JetExpression {
|
||||
if (this !is JetDotQualifiedExpression) return this
|
||||
val receiver = getReceiverExpression()
|
||||
if (receiver.getCopyableUserData(FROM_THIS_KEY) == null) return this
|
||||
if (!receiver[RECEIVER_VALUE_KEY]) return this
|
||||
val call = getSelectorExpression() as? JetCallExpression ?: return this
|
||||
val nameExpression = call.getCalleeExpression() as? JetSimpleNameExpression ?: return this
|
||||
val argument = call.getValueArguments().singleOrNull() ?: return this
|
||||
@@ -271,6 +284,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
|
||||
private fun JetExpression.introduceValue(
|
||||
value: JetExpression,
|
||||
valueType: JetType?,
|
||||
insertDeclarationsBefore: JetExpression,
|
||||
bindingContext: BindingContext,
|
||||
usages: Collection<JetExpression>,
|
||||
@@ -281,7 +295,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
|
||||
val psiFactory = JetPsiFactory(this)
|
||||
|
||||
fun nameInCode(name: String) = IdeDescriptorRenderers.SOURCE_CODE.renderName(Name.identifier(name))
|
||||
fun nameInCode(name: String) = Name.identifier(name).renderName()
|
||||
|
||||
fun replaceUsages(name: String) {
|
||||
val nameInCode = psiFactory.createExpression(nameInCode(name))
|
||||
@@ -306,7 +320,6 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, insertDeclarationsBefore]
|
||||
|
||||
if (usages.isNotEmpty()) {
|
||||
val valueType = bindingContext.getType(value)
|
||||
var explicitType: JetType? = null
|
||||
if (valueType != null && !ErrorUtils.containsErrorType(valueType)) {
|
||||
val valueTypeWithoutExpectedType = value.analyzeInContext(
|
||||
@@ -358,7 +371,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
|
||||
private fun collectNameUsages(scope: JetExpression, name: String)
|
||||
= scope.collectElementsOfType<JetSimpleNameExpression> { it.getReceiverExpression() == null && it.getReferencedName() == name }
|
||||
= scope.collectDescendantsOfType<JetSimpleNameExpression> { it.getReceiverExpression() == null && it.getReferencedName() == name }
|
||||
|
||||
private fun JetExpression?.shouldKeepValue(usageCount: Int): Boolean {
|
||||
if (usageCount == 1) return false
|
||||
@@ -381,8 +394,108 @@ public abstract class DeprecatedSymbolUsageFixBase(
|
||||
}
|
||||
}
|
||||
|
||||
private class Argument(
|
||||
val expression: JetExpression,
|
||||
val wrapped: JetExpression,
|
||||
val expressionType: JetType?,
|
||||
val isDefaultValue: Boolean)
|
||||
|
||||
private fun argumentForParameter(
|
||||
parameter: ValueParameterDescriptor,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
bindingContext: BindingContext,
|
||||
project: Project): Argument? {
|
||||
//TODO: named parameters - keep named form if makes sense
|
||||
//TODO: keep functional literal argument form
|
||||
val resolvedArgument = resolvedCall.getValueArguments()[parameter]!!
|
||||
when (resolvedArgument) {
|
||||
is ExpressionValueArgument -> {
|
||||
val expression = resolvedArgument.getValueArgument()!!.getArgumentExpression()!!
|
||||
expression.mark(USER_CODE_KEY)
|
||||
return Argument(expression, expression, bindingContext.getType(expression), isDefaultValue = false)
|
||||
}
|
||||
|
||||
is DefaultValueArgument -> {
|
||||
val defaultValue = OptionalParametersHelper.defaultParameterValue(parameter, project) ?: return null
|
||||
val (expression, parameterUsages) = defaultValue
|
||||
|
||||
for ((param, usages) in parameterUsages) {
|
||||
usages.forEach { it.put(PARAMETER_USAGE_KEY, param) }
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// clean up user data in original
|
||||
expression.forEachDescendantOfType<JetExpression> { it.clear(PARAMETER_USAGE_KEY) }
|
||||
|
||||
return Argument(wrapped.getExpression()!!, wrapped, null/*TODO*/, isDefaultValue = true)
|
||||
}
|
||||
|
||||
is VarargValueArgument -> /*TODO*/ return null
|
||||
|
||||
else -> error("Unknown argument type: $resolvedArgument")
|
||||
}
|
||||
}
|
||||
|
||||
private fun dropArgumentsForDefaultValues(result: JetExpression) {
|
||||
val project = result.getProject()
|
||||
val newBindingContext = result.analyze()
|
||||
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]
|
||||
|
||||
//TODO: other types of calls
|
||||
result.forEachDescendantOfType<JetCallExpression> { callExpression ->
|
||||
val resolvedCall = callExpression.getResolvedCall(newBindingContext) ?: return@forEachDescendantOfType
|
||||
|
||||
argumentsToDrop.addAll(OptionalParametersHelper.detectArgumentsToDropForDefaults(resolvedCall, project, ::canDropArgument))
|
||||
}
|
||||
|
||||
for (argument in argumentsToDrop) {
|
||||
argument as JetValueArgument
|
||||
val argumentList = argument.getParent() as JetValueArgumentList
|
||||
argumentList.removeArgument(argument)
|
||||
}
|
||||
}
|
||||
|
||||
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() }
|
||||
}
|
||||
|
||||
//TODO: making functions below private causes VerifyError
|
||||
fun <T: Any> PsiElement.get(key: Key<T>): T? = getCopyableUserData(key)
|
||||
fun PsiElement.get(key: Key<Unit>): Boolean = getCopyableUserData(key) != null
|
||||
fun <T: Any> JetExpression.clear(key: Key<T>) = putCopyableUserData(key, null)
|
||||
fun <T: Any> JetExpression.put(key: Key<T>, value: T) = putCopyableUserData(key, value)
|
||||
fun JetExpression.mark(key: Key<Unit>) = putCopyableUserData(key, Unit)
|
||||
fun <T: JetExpression> T.marked(key: Key<Unit>): T {
|
||||
putCopyableUserData(key, Unit)
|
||||
return this
|
||||
}
|
||||
|
||||
private val USER_CODE_KEY = Key<Unit>("USER_CODE")
|
||||
private val FROM_PARAMETER_KEY = Key<ValueParameterDescriptor>("FROM_PARAMETER")
|
||||
private val FROM_THIS_KEY = Key<Unit>("FROM_THIS")
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionFactory
|
||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
@@ -63,7 +63,7 @@ public class RemoveNameFromFunctionExpressionFix(element: JetNamedFunction) : Je
|
||||
var wereAutoLabelUsages = false
|
||||
val name = function.getName() ?: return
|
||||
|
||||
function.forEachDescendantsOfType<JetReturnExpression> {
|
||||
function.forEachDescendantOfType<JetReturnExpression> {
|
||||
if (!wereAutoLabelUsages && it.getLabelName() == name) {
|
||||
wereAutoLabelUsages = it.analyze().get(BindingContext.LABEL_TARGET, it.getTargetLabel()) == function
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ 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.collectElementsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.replaced
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -144,7 +144,7 @@ object ReplaceWithAnnotationAnalyzer {
|
||||
}
|
||||
|
||||
val parameterUsages = symbolDescriptor.getValueParameters()
|
||||
.map { parameter -> parameter to expression.collectElementsOfType<JetExpression> { it.getCopyableUserData(parameterUsageKey) == parameter } }
|
||||
.map { parameter -> parameter to expression.collectDescendantsOfType<JetExpression> { it.getCopyableUserData(parameterUsageKey) == parameter } }
|
||||
.toMap()
|
||||
|
||||
expression.accept(object : PsiRecursiveElementVisitor() {
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -66,7 +66,7 @@ private fun renderClassNameForKClassLiteral(type: JetType): String? {
|
||||
fun createReplacementTasks(element: JetElement, anyJavaClass: Boolean = false): List<ReplacementTask> {
|
||||
val replacementTasks = arrayListOf<ReplacementTask>()
|
||||
|
||||
element.forEachDescendantsOfType(fun(expression: JetCallExpression) {
|
||||
element.forEachDescendantOfType(fun(expression: JetCallExpression) {
|
||||
val context = expression.analyze()
|
||||
val resolvedCall = expression.getResolvedCall(context) ?: return
|
||||
|
||||
@@ -94,7 +94,7 @@ fun createReplacementTasksForAnnotationClass(element: JetClass): List<Replacemen
|
||||
replacementTasks.add(JavaClassParameterReplacementTask(typeReference, classTypeArgText))
|
||||
}
|
||||
|
||||
element.forEachDescendantsOfType(fun(parameter: JetParameter) {
|
||||
element.forEachDescendantOfType(fun(parameter: JetParameter) {
|
||||
val valueParameterDescriptor = parameter.descriptor as? ValueParameterDescriptor ?: return
|
||||
val type = valueParameterDescriptor.getType()
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3, p4, p5)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3, p4, p5)"))
|
||||
fun oldFun(p1: String, p2: Int = 0, p3: String? = null, p4: String = p1, p5: Int = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String?, p4: String, p5: Int)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("a")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3, p4, p5)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3, p4, p5)"))
|
||||
fun oldFun(p1: String, p2: Int = 0, p3: String? = null, p4: String = p1, p5: Int = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String?, p4: String, p5: Int)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("a", 0.toString(), null, "a", 0)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3)"))
|
||||
fun oldFun(p1: String, p2: Int = 0, p3: String? = null)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String? = null)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("a")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3)"))
|
||||
fun oldFun(p1: String, p2: Int = 0, p3: String? = null)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String? = null)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("a", 0.toString())
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3)"))
|
||||
fun oldFun(p1: String, p2: Int, p3: String?)
|
||||
|
||||
fun newFun(p1: String, p2: String = "", p3: String? = null)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("a", 0, null)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2.toString(), p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2.toString(), p3)"))
|
||||
fun oldFun(p1: String, p2: Int, p3: String?)
|
||||
|
||||
fun newFun(p1: String, p2: String = "", p3: String? = null)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("a", 0.toString(), null)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: Int = p1.length(), p3: String? = p1)
|
||||
|
||||
fun newFun(x: String, y: Int = x.length(), z: String? = "a")
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("a")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: Int = p1.length(), p3: String? = p1)
|
||||
|
||||
fun newFun(x: String, y: Int = x.length(), z: String? = "a")
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("a")
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2)"))
|
||||
fun oldFun(p1: String, p2: String = p1)
|
||||
|
||||
fun newFun(p1: String, p2: String)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun(bar())
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,15 @@
|
||||
// "Replace with 'newFun(p1, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2)"))
|
||||
fun oldFun(p1: String, p2: String = p1)
|
||||
|
||||
fun newFun(p1: String, p2: String)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
val p1 = bar()
|
||||
i.<caret>newFun(p1, p1)
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2)"))
|
||||
fun oldFun(p1: String, p2: String = p1)
|
||||
|
||||
fun newFun(p1: String, p2: String = p2)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun(bar())
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2)"))
|
||||
fun oldFun(p1: String, p2: String = p1)
|
||||
|
||||
fun newFun(p1: String, p2: String = p2)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun(bar())
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: String = bar(), p3: String = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("")
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,15 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: String = bar(), p3: String = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
val p2 = bar()
|
||||
i.<caret>newFun("", p2, p2)
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: String = bar(), p3: String = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String = p2)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("", bar())
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with 'newFun(p1, p2, p3)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p2, p3)"))
|
||||
fun oldFun(p1: String, p2: String = bar(), p3: String = p2)
|
||||
|
||||
fun newFun(p1: String, p2: String, p3: String = p2)
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("")
|
||||
}
|
||||
|
||||
fun bar(): String = ""
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p3, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p3, p2)"))
|
||||
fun oldFun(p1: String, p2: String = "", p3: Int = -1)
|
||||
|
||||
fun newFun(p1: String, p2: Int = -1, p3: String = "")
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>oldFun("")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with 'newFun(p1, p3, p2)'" "true"
|
||||
|
||||
interface I {
|
||||
@deprecated("", ReplaceWith("newFun(p1, p3, p2)"))
|
||||
fun oldFun(p1: String, p2: String = "", p3: Int = -1)
|
||||
|
||||
fun newFun(p1: String, p2: Int = -1, p3: String = "")
|
||||
}
|
||||
|
||||
fun foo(i: I) {
|
||||
i.<caret>newFun("")
|
||||
}
|
||||
@@ -3124,6 +3124,48 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters1.kt")
|
||||
public void testOptionalParameters1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters2.kt")
|
||||
public void testOptionalParameters2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters3.kt")
|
||||
public void testOptionalParameters3() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters4.kt")
|
||||
public void testOptionalParameters4() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters4.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters5.kt")
|
||||
public void testOptionalParameters5() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters5.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters7.kt")
|
||||
public void testOptionalParameters7() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters7.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("optionalParameters9.kt")
|
||||
public void testOptionalParameters9() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/optionalParameters9.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameters.kt")
|
||||
public void testParameters() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/parameters.kt");
|
||||
|
||||
Reference in New Issue
Block a user