KT-7895 Auto replace for deprecated (ReplaceWith) loses generic type

#KT-7895 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-06-03 21:31:15 +03:00
parent f14615315d
commit a26c62ab0f
22 changed files with 386 additions and 54 deletions
@@ -136,9 +136,16 @@ public fun PsiElement.isInsideOf(elements: Iterable<PsiElement>): Boolean = elem
// -------------------- Recursive tree visiting -------------------------------------------------------------------------------------------- // -------------------- Recursive tree visiting --------------------------------------------------------------------------------------------
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) { public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) {
forEachDescendantOfType<T>({true}, action)
}
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline action: (T) -> Unit) {
this.accept(object : PsiRecursiveElementVisitor(){ this.accept(object : PsiRecursiveElementVisitor(){
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
super.visitElement(element) if (canGoInside(element)) {
super.visitElement(element)
}
if (element is T) { if (element is T) {
action(element) action(element)
} }
@@ -147,27 +154,43 @@ public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(no
} }
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean = { true }): Boolean { public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean = { true }): Boolean {
return findDescendantOfType(predicate) != null return findDescendantOfType<T>(predicate) != null
}
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): Boolean {
return findDescendantOfType<T>(canGoInside, predicate) != null
} }
public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(noinline predicate: (T) -> Boolean = { true }): T? { public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(noinline predicate: (T) -> Boolean = { true }): T? {
return findDescendantOfType<T>({ true}, predicate)
}
public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): T? {
var result: T? = null var result: T? = null
this.accept(object : PsiRecursiveElementVisitor(){ this.accept(object : PsiRecursiveElementVisitor(){
override fun visitElement(element: PsiElement) { override fun visitElement(element: PsiElement) {
if (result != null) return if (result != null) return
if (element is T && predicate(element)) { if (element is T && predicate(element)) {
result = element result = element
return return
} }
super.visitElement(element)
if (canGoInside(element)) {
super.visitElement(element)
}
} }
}) })
return result return result
} }
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> { public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
return collectDescendantsOfType<T>({ true }, predicate)
}
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): List<T> {
val result = ArrayList<T>() val result = ArrayList<T>()
forEachDescendantOfType<T> { forEachDescendantOfType<T>(canGoInside) {
if (predicate(it)) { if (predicate(it)) {
result.add(it) result.add(it)
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArguments import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArguments
import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.refactoring.createTempCopy import org.jetbrains.kotlin.idea.core.refactoring.createTempCopy
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
@@ -251,7 +252,7 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: JetCodeFragment
private fun replaceByRunFunction(expression: JetExpression): JetCallExpression { private fun replaceByRunFunction(expression: JetExpression): JetCallExpression {
val callExpression = JetPsiFactory(expression).createExpression("run { \n${expression.getText()} \n}") as JetCallExpression val callExpression = JetPsiFactory(expression).createExpression("run { \n${expression.getText()} \n}") as JetCallExpression
val replaced = expression.replaced(callExpression) val replaced = expression.replaced(callExpression)
val typeArguments = InsertExplicitTypeArguments.createTypeArguments(replaced) val typeArguments = InsertExplicitTypeArguments.createTypeArguments(replaced, replaced.analyze())
if (typeArguments?.getArguments()?.isNotEmpty() ?: false) { if (typeArguments?.getArguments()?.isNotEmpty() ?: false) {
val calleeExpression = replaced.getCalleeExpression() val calleeExpression = replaced.getCalleeExpression()
replaced.addAfter(typeArguments!!, calleeExpression) replaced.addAfter(typeArguments!!, calleeExpression)
@@ -16,29 +16,26 @@
package org.jetbrains.kotlin.idea.intentions package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.psi.JetCallExpression import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.psi.JetTypeArgumentList import org.jetbrains.kotlin.psi.JetTypeArgumentList
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.types.ErrorUtils
public class InsertExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Add explicit type arguments") { public class InsertExplicitTypeArguments : JetSelfTargetingRangeIntention<JetCallExpression>(javaClass(), "Add explicit type arguments"), LowPriorityAction {
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean { override fun applicabilityRange(element: JetCallExpression): TextRange? {
if (!element.getTypeArguments().isEmpty()) return false return if (isApplicableTo(element, element.analyze())) element.getCalleeExpression()!!.getTextRange() else null
val callee = element.getCalleeExpression() ?: return false
if (!callee.getTextRange().containsOffset(caretOffset)) return false
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
val typeArgs = resolvedCall.getTypeArguments()
return !typeArgs.isEmpty() && typeArgs.values().none { ErrorUtils.containsErrorType(it) }
} }
override fun applyTo(element: JetCallExpression, editor: Editor) { override fun applyTo(element: JetCallExpression, editor: Editor) {
val argumentList = createTypeArguments(element)!! val argumentList = createTypeArguments(element, element.analyze())!!
val callee = element.getCalleeExpression()!! val callee = element.getCalleeExpression()!!
val newArgumentList = element.addAfter(argumentList, callee) as JetTypeArgumentList val newArgumentList = element.addAfter(argumentList, callee) as JetTypeArgumentList
@@ -47,8 +44,17 @@ public class InsertExplicitTypeArguments : JetSelfTargetingIntention<JetCallExpr
} }
companion object { companion object {
public fun createTypeArguments(element: JetCallExpression): JetTypeArgumentList? { public fun isApplicableTo(element: JetCallExpression, bindingContext: BindingContext): Boolean {
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null if (!element.getTypeArguments().isEmpty()) return false
if (element.getCalleeExpression() == null) return false
val resolvedCall = element.getResolvedCall(bindingContext) ?: return false
val typeArgs = resolvedCall.getTypeArguments()
return typeArgs.isNotEmpty() && typeArgs.values().none { ErrorUtils.containsErrorType(it) }
}
public fun createTypeArguments(element: JetCallExpression, bindingContext: BindingContext): JetTypeArgumentList? {
val resolvedCall = element.getResolvedCall(bindingContext) ?: return null
val args = resolvedCall.getTypeArguments() val args = resolvedCall.getTypeArguments()
val types = resolvedCall.getCandidateDescriptor().getTypeParameters() val types = resolvedCall.getCandidateDescriptor().getTypeParameters()
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
import org.jetbrains.kotlin.idea.core.* import org.jetbrains.kotlin.idea.core.*
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
import org.jetbrains.kotlin.idea.core.refactoring.JetNameValidator import org.jetbrains.kotlin.idea.core.refactoring.JetNameValidator
import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeArgumentsIntention
import org.jetbrains.kotlin.idea.intentions.setType import org.jetbrains.kotlin.idea.intentions.setType
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.idea.util.ImportInsertHelper
@@ -197,6 +198,27 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
} }
for (typeParameter in descriptor.getOriginal().getTypeParameters()) {
val parameterName = typeParameter.getName()
val usages = replacement.expression.collectDescendantsOfType<JetExpression> {
it[ReplaceWithAnnotationAnalyzer.TYPE_PARAMETER_USAGE_KEY] == parameterName
}
val type = resolvedCall.getTypeArguments()[typeParameter]!!
val typeString = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
for (usage in usages) {
val parent = usage.getParent()
if (parent is JetUserType) {
val typeReference = psiFactory.createType(typeString)
parent.replace(typeReference.getTypeElement()!!)
}
else { //TODO: tests for this?
usage.replace(psiFactory.createExpression(typeString))
}
}
}
val wrapper = ConstructedExpressionWrapper(replacement.expression, expressionToBeReplaced, bindingContext) val wrapper = ConstructedExpressionWrapper(replacement.expression, expressionToBeReplaced, bindingContext)
if (qualifiedExpression is JetSafeQualifiedExpression) { if (qualifiedExpression is JetSafeQualifiedExpression) {
@@ -227,15 +249,16 @@ public abstract class DeprecatedSymbolUsageFixBase(
.flatMap { file.resolveImportReference(it) } .flatMap { file.resolveImportReference(it) }
.forEach { ImportInsertHelper.getInstance(project).importDescriptor(file, it) } .forEach { ImportInsertHelper.getInstance(project).importDescriptor(file, it) }
result = postProcessInsertedExpression(result, wrapper.addedStatements) var resultRange = if (wrapper.addedStatements.isEmpty())
val resultRange = if (wrapper.addedStatements.isEmpty())
PsiChildRange.singleElement(result) PsiChildRange.singleElement(result)
else else
PsiChildRange(wrapper.addedStatements.first(), result) PsiChildRange(wrapper.addedStatements.first(), result)
resultRange = postProcessInsertedExpression(resultRange)
commentSaver.restore(resultRange) commentSaver.restore(resultRange)
return result return resultRange.last as JetExpression
} }
private fun ConstructedExpressionWrapper.wrapExpressionForSafeCall(receiver: JetExpression, receiverType: JetType?) { private fun ConstructedExpressionWrapper.wrapExpressionForSafeCall(receiver: JetExpression, receiverType: JetType?) {
@@ -358,16 +381,20 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
} }
private fun postProcessInsertedExpression(result: JetExpression, additionalStatements: Collection<JetExpression>): JetExpression { private fun postProcessInsertedExpression(range: PsiChildRange): PsiChildRange {
var allExpressions = listOf(result) + additionalStatements val expressions = range.filterIsInstance<JetExpression>().toList()
allExpressions.forEach { expressions.forEach {
introduceNamedArguments(it) introduceNamedArguments(it)
restoreFunctionLiteralArguments(it) restoreFunctionLiteralArguments(it)
//TODO: do this earlier //TODO: do this earlier
dropArgumentsForDefaultValues(it) dropArgumentsForDefaultValues(it)
simplifySpreadArrayOfArguments(it)
removeExplicitTypeArguments(it)
} }
@@ -384,17 +411,16 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
} }
allExpressions = allExpressions.map { val newExpressions = expressions.map {
ShortenReferences({ ShortenReferences.Options(removeThis = true) }).process(it, shortenFilter) as JetExpression ShortenReferences({ ShortenReferences.Options(removeThis = true) }).process(it, shortenFilter) as JetExpression
} }
allExpressions.forEach { newExpressions.forEach {
simplifySpreadArrayOfArguments(it)
// clean up user data // clean up user data
it.forEachDescendantOfType<JetExpression> { it.forEachDescendantOfType<JetExpression> {
it.clear(USER_CODE_KEY) it.clear(USER_CODE_KEY)
it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY) it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY)
it.clear(ReplaceWithAnnotationAnalyzer.TYPE_PARAMETER_USAGE_KEY)
it.clear(PARAMETER_VALUE_KEY) it.clear(PARAMETER_VALUE_KEY)
it.clear(RECEIVER_VALUE_KEY) it.clear(RECEIVER_VALUE_KEY)
it.clear(WAS_FUNCTION_LITERAL_ARGUMENT_KEY) it.clear(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
@@ -405,7 +431,7 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
} }
return allExpressions.first() return PsiChildRange(newExpressions.first(), newExpressions.last())
} }
private fun introduceNamedArguments(result: JetExpression) { private fun introduceNamedArguments(result: JetExpression) {
@@ -484,32 +510,27 @@ public abstract class DeprecatedSymbolUsageFixBase(
} }
} }
private fun removeExplicitTypeArguments(result: JetExpression) {
val intention = RemoveExplicitTypeArgumentsIntention()
result.collectDescendantsOfType<JetTypeArgumentList>(canGoInside = { !it[USER_CODE_KEY] }) { intention.isApplicableTo(it) }
.forEach { it.delete() }
}
private fun simplifySpreadArrayOfArguments(expression: JetExpression) { private fun simplifySpreadArrayOfArguments(expression: JetExpression) {
//TODO: test for nested //TODO: test for nested
val argumentsToExpand = ArrayList<Pair<JetValueArgument, Collection<JetValueArgument>>>() val argumentsToExpand = ArrayList<Pair<JetValueArgument, Collection<JetValueArgument>>>()
expression.accept(object : JetTreeVisitorVoid() { expression.forEachDescendantOfType<JetValueArgument>(canGoInside = { !it[USER_CODE_KEY] }) { argument ->
override fun visitArgument(argument: JetValueArgument) { if (argument.getSpreadElement() != null && !argument.isNamed()) {
super.visitArgument(argument) val argumentExpression = argument.getArgumentExpression() ?: return@forEachDescendantOfType
val resolvedCall = argumentExpression.getResolvedCall(argumentExpression.analyze(BodyResolveMode.PARTIAL)) ?: return@forEachDescendantOfType
if (argument.getSpreadElement() != null && !argument.isNamed()) { val callExpression = resolvedCall.getCall().getCallElement() as? JetCallExpression ?: return@forEachDescendantOfType
val call = argument.getArgumentExpression() as? JetCallExpression if (CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
if (call != null) { argumentsToExpand.add(argument to callExpression.getValueArguments())
val resolvedCall = call.getResolvedCall(call.analyze(BodyResolveMode.PARTIAL))
if (resolvedCall != null && CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) {
argumentsToExpand.add(argument to call.getValueArguments())
}
}
} }
} }
}
override fun visitJetElement(element: JetElement) {
if (!element[USER_CODE_KEY]) { // do not go inside original user's code
super.visitJetElement(element)
}
}
})
for ((argument, replacements) in argumentsToExpand) { for ((argument, replacements) in argumentsToExpand) {
argument.replaceByMultiple(replacements) argument.replaceByMultiple(replacements)
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.core.copied
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArguments
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -53,6 +54,7 @@ data class ReplaceWith(val expression: String, vararg val imports: String)
object ReplaceWithAnnotationAnalyzer { object ReplaceWithAnnotationAnalyzer {
public val PARAMETER_USAGE_KEY: Key<Name> = Key("PARAMETER_USAGE") public val PARAMETER_USAGE_KEY: Key<Name> = Key("PARAMETER_USAGE")
public val TYPE_PARAMETER_USAGE_KEY: Key<Name> = Key("TYPE_PARAMETER_USAGE")
public data class ReplacementExpression( public data class ReplacementExpression(
val expression: JetExpression, val expression: JetExpression,
@@ -94,7 +96,23 @@ object ReplaceWithAnnotationAnalyzer {
val symbolScope = getResolutionScope(symbolDescriptor) val symbolScope = getResolutionScope(symbolDescriptor)
val scope = ChainedScope(symbolDescriptor, "ReplaceWith resolution scope", ExplicitImportsScope(explicitlyImportedSymbols), symbolScope) val scope = ChainedScope(symbolDescriptor, "ReplaceWith resolution scope", ExplicitImportsScope(explicitlyImportedSymbols), symbolScope)
val bindingContext = expression.analyzeInContext(scope) var bindingContext = expression.analyzeInContext(scope)
val typeArgsToAdd = ArrayList<Pair<JetCallExpression, JetTypeArgumentList>>()
expression.forEachDescendantOfType<JetCallExpression> {
if (InsertExplicitTypeArguments.isApplicableTo(it, bindingContext)) {
typeArgsToAdd.add(it to InsertExplicitTypeArguments.createTypeArguments(it, bindingContext)!!)
}
}
if (typeArgsToAdd.isNotEmpty()) {
for ((callExpr, typeArgs) in typeArgsToAdd) {
callExpr.addAfter(typeArgs, callExpr.getCalleeExpression())
}
// reanalyze expression - new usages of type parameters may be added
bindingContext = expression.analyzeInContext(scope)
}
val receiversToAdd = ArrayList<Pair<JetExpression, JetExpression>>() val receiversToAdd = ArrayList<Pair<JetExpression, JetExpression>>()
@@ -109,6 +127,9 @@ object ReplaceWithAnnotationAnalyzer {
if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) { if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) {
expression.putCopyableUserData(PARAMETER_USAGE_KEY, target.getName()) expression.putCopyableUserData(PARAMETER_USAGE_KEY, target.getName())
} }
else if (target is TypeParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) {
expression.putCopyableUserData(TYPE_PARAMETER_USAGE_KEY, target.getName())
}
val resolvedCall = expression.getResolvedCall(bindingContext) val resolvedCall = expression.getResolvedCall(bindingContext)
if (resolvedCall != null && resolvedCall.getStatus().isSuccess()) { if (resolvedCall != null && resolvedCall.getStatus().isSuccess()) {
@@ -0,0 +1,15 @@
// "Replace with 'newFun()'" "true"
package ppp
fun bar(): Int = 0
@deprecated("", ReplaceWith("newFun()"))
fun oldFun(p: Int = ppp.bar()) {
newFun()
}
fun newFun(){}
fun foo() {
<caret>oldFun()
}
@@ -0,0 +1,16 @@
// "Replace with 'newFun()'" "true"
package ppp
fun bar(): Int = 0
@deprecated("", ReplaceWith("newFun()"))
fun oldFun(p: Int = ppp.bar()) {
newFun()
}
fun newFun(){}
fun foo() {
bar()
<caret>newFun()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
<caret>oldFun<String>()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
newFun<String>()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun<T>()'" "true"
@deprecated("", ReplaceWith("newFun<T>()"))
fun <T : Any> oldFun(): T? {
return newFun<T>()
}
fun <T : Any> newFun(): T? = null
fun foo(): String? {
return <caret>oldFun()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun<T>()'" "true"
@deprecated("", ReplaceWith("newFun<T>()"))
fun <T : Any> oldFun(): T? {
return newFun<T>()
}
fun <T : Any> newFun(): T? = null
fun foo(): String? {
return newFun()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun<T>()'" "true"
@deprecated("", ReplaceWith("newFun<T>()"))
fun <T> oldFun() {
newFun<T>()
}
fun <T> newFun(){}
fun foo() {
<caret>oldFun<String>()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun<T>()'" "true"
@deprecated("", ReplaceWith("newFun<T>()"))
fun <T> oldFun() {
newFun<T>()
}
fun <T> newFun(){}
fun foo() {
newFun<String>()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(p)'" "true"
@deprecated("", ReplaceWith("newFun(p)"))
fun oldFun(p: List<String>) {
newFun(p)
}
fun newFun(p: List<String>){}
fun foo() {
<caret>oldFun(listOf<String>("a"))
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(p)'" "true"
@deprecated("", ReplaceWith("newFun(p)"))
fun oldFun(p: List<String>) {
newFun(p)
}
fun newFun(p: List<String>){}
fun foo() {
<caret>newFun(listOf<String>("a"))
}
@@ -0,0 +1,14 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
<caret>oldFun(bar())
}
fun bar(): java.io.File? = null
@@ -0,0 +1,14 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
<caret>newFun(bar())
}
fun bar(): java.io.File? = null
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
<caret>oldFun("a")
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun <T> oldFun(vararg elements: T) {
newFun(*elements)
}
fun <T> newFun(vararg elements: T){}
fun foo() {
newFun("a")
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun oldFun(vararg elements: java.io.File?) {
newFun(*elements)
}
fun newFun(vararg elements: java.io.File?){}
fun foo() {
<caret>oldFun()
}
@@ -0,0 +1,12 @@
// "Replace with 'newFun(*elements)'" "true"
@deprecated("", ReplaceWith("newFun(*elements)"))
fun oldFun(vararg elements: java.io.File?) {
newFun(*elements)
}
fun newFun(vararg elements: java.io.File?){}
fun foo() {
<caret>newFun()
}
@@ -3126,6 +3126,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("complexExpressionNotUsedShortenRefsRuntime.kt")
public void testComplexExpressionNotUsedShortenRefsRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt");
doTest(fileName);
}
@TestMetadata("complexExpressionUsedTwice.kt") @TestMetadata("complexExpressionUsedTwice.kt")
public void testComplexExpressionUsedTwice() throws Exception { public void testComplexExpressionUsedTwice() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionUsedTwice.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionUsedTwice.kt");
@@ -3460,6 +3466,51 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
} }
} }
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TypeArguments extends AbstractQuickFixTest {
public void testAllFilesPresentInTypeArguments() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
}
@TestMetadata("emptyVarargRuntime.kt")
public void testEmptyVarargRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt");
doTest(fileName);
}
@TestMetadata("explicitInPatternImplicitInUsage.kt")
public void testExplicitInPatternImplicitInUsage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt");
doTest(fileName);
}
@TestMetadata("explicitTypeArg.kt")
public void testExplicitTypeArg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt");
doTest(fileName);
}
@TestMetadata("keepInUserCodeRuntime.kt")
public void testKeepInUserCodeRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt");
doTest(fileName);
}
@TestMetadata("noImplicitTypeArgImportRuntime.kt")
public void testNoImplicitTypeArgImportRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt");
doTest(fileName);
}
@TestMetadata("nonEmptyVarargRuntime.kt")
public void testNonEmptyVarargRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg") @TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -3546,6 +3597,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("noImportRuntime.kt")
public void testNoImportRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt");
doTest(fileName);
}
@TestMetadata("shortArrayRuntime.kt") @TestMetadata("shortArrayRuntime.kt")
public void testShortArrayRuntime() throws Exception { public void testShortArrayRuntime() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg/shortArrayRuntime.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg/shortArrayRuntime.kt");