diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt index 95138a02eef..9f96a3da45c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/psiUtils.kt @@ -136,9 +136,16 @@ public fun PsiElement.isInsideOf(elements: Iterable): Boolean = elem // -------------------- Recursive tree visiting -------------------------------------------------------------------------------------------- public inline fun PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) { + forEachDescendantOfType({true}, action) +} + +public inline fun PsiElement.forEachDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline action: (T) -> Unit) { this.accept(object : PsiRecursiveElementVisitor(){ override fun visitElement(element: PsiElement) { - super.visitElement(element) + if (canGoInside(element)) { + super.visitElement(element) + } + if (element is T) { action(element) } @@ -147,27 +154,43 @@ public inline fun PsiElement.forEachDescendantOfType(no } public inline fun PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean = { true }): Boolean { - return findDescendantOfType(predicate) != null + return findDescendantOfType(predicate) != null +} + +public inline fun PsiElement.anyDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): Boolean { + return findDescendantOfType(canGoInside, predicate) != null } public inline fun PsiElement.findDescendantOfType(noinline predicate: (T) -> Boolean = { true }): T? { + return findDescendantOfType({ true}, predicate) +} + +public inline fun PsiElement.findDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): T? { var result: T? = null this.accept(object : PsiRecursiveElementVisitor(){ override fun visitElement(element: PsiElement) { if (result != null) return + if (element is T && predicate(element)) { result = element return } - super.visitElement(element) + + if (canGoInside(element)) { + super.visitElement(element) + } } }) return result } public inline fun PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List { + return collectDescendantsOfType({ true }, predicate) +} + +public inline fun PsiElement.collectDescendantsOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): List { val result = ArrayList() - forEachDescendantOfType { + forEachDescendantOfType(canGoInside) { if (predicate(it)) { result.add(it) } diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt index 8268e109bed..c205f0b953c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArguments import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange 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.replaced import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* @@ -251,7 +252,7 @@ private fun addDebugExpressionBeforeContextElement(codeFragment: JetCodeFragment private fun replaceByRunFunction(expression: JetExpression): JetCallExpression { val callExpression = JetPsiFactory(expression).createExpression("run { \n${expression.getText()} \n}") as JetCallExpression val replaced = expression.replaced(callExpression) - val typeArguments = InsertExplicitTypeArguments.createTypeArguments(replaced) + val typeArguments = InsertExplicitTypeArguments.createTypeArguments(replaced, replaced.analyze()) if (typeArguments?.getArguments()?.isNotEmpty() ?: false) { val calleeExpression = replaced.getCalleeExpression() replaced.addAfter(typeArguments!!, calleeExpression) diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArguments.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArguments.kt index e37da66706a..5858d41507b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArguments.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/InsertExplicitTypeArguments.kt @@ -16,29 +16,26 @@ package org.jetbrains.kotlin.idea.intentions +import com.intellij.codeInsight.intention.LowPriorityAction 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.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.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.types.ErrorUtils -public class InsertExplicitTypeArguments : JetSelfTargetingIntention(javaClass(), "Add explicit type arguments") { - override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean { - if (!element.getTypeArguments().isEmpty()) return false - 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) } +public class InsertExplicitTypeArguments : JetSelfTargetingRangeIntention(javaClass(), "Add explicit type arguments"), LowPriorityAction { + override fun applicabilityRange(element: JetCallExpression): TextRange? { + return if (isApplicableTo(element, element.analyze())) element.getCalleeExpression()!!.getTextRange() else null } override fun applyTo(element: JetCallExpression, editor: Editor) { - val argumentList = createTypeArguments(element)!! + val argumentList = createTypeArguments(element, element.analyze())!! val callee = element.getCalleeExpression()!! val newArgumentList = element.addAfter(argumentList, callee) as JetTypeArgumentList @@ -47,8 +44,17 @@ public class InsertExplicitTypeArguments : JetSelfTargetingIntention { + 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) if (qualifiedExpression is JetSafeQualifiedExpression) { @@ -227,15 +249,16 @@ public abstract class DeprecatedSymbolUsageFixBase( .flatMap { file.resolveImportReference(it) } .forEach { ImportInsertHelper.getInstance(project).importDescriptor(file, it) } - result = postProcessInsertedExpression(result, wrapper.addedStatements) - - val resultRange = if (wrapper.addedStatements.isEmpty()) + var resultRange = if (wrapper.addedStatements.isEmpty()) PsiChildRange.singleElement(result) else PsiChildRange(wrapper.addedStatements.first(), result) + + resultRange = postProcessInsertedExpression(resultRange) + commentSaver.restore(resultRange) - return result + return resultRange.last as JetExpression } private fun ConstructedExpressionWrapper.wrapExpressionForSafeCall(receiver: JetExpression, receiverType: JetType?) { @@ -358,16 +381,20 @@ public abstract class DeprecatedSymbolUsageFixBase( } } - private fun postProcessInsertedExpression(result: JetExpression, additionalStatements: Collection): JetExpression { - var allExpressions = listOf(result) + additionalStatements + private fun postProcessInsertedExpression(range: PsiChildRange): PsiChildRange { + val expressions = range.filterIsInstance().toList() - allExpressions.forEach { + expressions.forEach { introduceNamedArguments(it) restoreFunctionLiteralArguments(it) //TODO: do this earlier 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 } - allExpressions.forEach { - simplifySpreadArrayOfArguments(it) - + newExpressions.forEach { // clean up user data it.forEachDescendantOfType { it.clear(USER_CODE_KEY) it.clear(ReplaceWithAnnotationAnalyzer.PARAMETER_USAGE_KEY) + it.clear(ReplaceWithAnnotationAnalyzer.TYPE_PARAMETER_USAGE_KEY) it.clear(PARAMETER_VALUE_KEY) it.clear(RECEIVER_VALUE_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) { @@ -484,32 +510,27 @@ public abstract class DeprecatedSymbolUsageFixBase( } } + private fun removeExplicitTypeArguments(result: JetExpression) { + val intention = RemoveExplicitTypeArgumentsIntention() + result.collectDescendantsOfType(canGoInside = { !it[USER_CODE_KEY] }) { intention.isApplicableTo(it) } + .forEach { it.delete() } + } + private fun simplifySpreadArrayOfArguments(expression: JetExpression) { //TODO: test for nested val argumentsToExpand = ArrayList>>() - expression.accept(object : JetTreeVisitorVoid() { - override fun visitArgument(argument: JetValueArgument) { - super.visitArgument(argument) - - if (argument.getSpreadElement() != null && !argument.isNamed()) { - val call = argument.getArgumentExpression() as? JetCallExpression - if (call != null) { - val resolvedCall = call.getResolvedCall(call.analyze(BodyResolveMode.PARTIAL)) - if (resolvedCall != null && CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) { - argumentsToExpand.add(argument to call.getValueArguments()) - } - } + expression.forEachDescendantOfType(canGoInside = { !it[USER_CODE_KEY] }) { argument -> + if (argument.getSpreadElement() != null && !argument.isNamed()) { + val argumentExpression = argument.getArgumentExpression() ?: return@forEachDescendantOfType + val resolvedCall = argumentExpression.getResolvedCall(argumentExpression.analyze(BodyResolveMode.PARTIAL)) ?: return@forEachDescendantOfType + val callExpression = resolvedCall.getCall().getCallElement() as? JetCallExpression ?: return@forEachDescendantOfType + if (CompileTimeConstantUtils.isArrayMethodCall(resolvedCall)) { + argumentsToExpand.add(argument to callExpression.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) { argument.replaceByMultiple(replacements) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt index 46bbf27de10..5774b3029a0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceWithAnnotationAnalyzer.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport 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.FqNameUnsafe import org.jetbrains.kotlin.name.Name @@ -53,6 +54,7 @@ data class ReplaceWith(val expression: String, vararg val imports: String) object ReplaceWithAnnotationAnalyzer { public val PARAMETER_USAGE_KEY: Key = Key("PARAMETER_USAGE") + public val TYPE_PARAMETER_USAGE_KEY: Key = Key("TYPE_PARAMETER_USAGE") public data class ReplacementExpression( val expression: JetExpression, @@ -94,7 +96,23 @@ object ReplaceWithAnnotationAnalyzer { val symbolScope = getResolutionScope(symbolDescriptor) val scope = ChainedScope(symbolDescriptor, "ReplaceWith resolution scope", ExplicitImportsScope(explicitlyImportedSymbols), symbolScope) - val bindingContext = expression.analyzeInContext(scope) + var bindingContext = expression.analyzeInContext(scope) + + val typeArgsToAdd = ArrayList>() + expression.forEachDescendantOfType { + 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>() @@ -109,6 +127,9 @@ object ReplaceWithAnnotationAnalyzer { if (target is ValueParameterDescriptor && target.getContainingDeclaration() == symbolDescriptor) { 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) if (resolvedCall != null && resolvedCall.getStatus().isSuccess()) { diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt new file mode 100644 index 00000000000..8e4585a59b5 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt @@ -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() { + oldFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt.after new file mode 100644 index 00000000000..3ccf3980b76 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/argumentSideEffects/complexExpressionNotUsedShortenRefsRuntime.kt.after @@ -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() + newFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt new file mode 100644 index 00000000000..a3e57899a51 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt @@ -0,0 +1,12 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + oldFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt.after new file mode 100644 index 00000000000..fe5d1189173 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/emptyVarargRuntime.kt.after @@ -0,0 +1,12 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + newFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt new file mode 100644 index 00000000000..2f78f039ad6 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt @@ -0,0 +1,12 @@ +// "Replace with 'newFun()'" "true" + +@deprecated("", ReplaceWith("newFun()")) +fun oldFun(): T? { + return newFun() +} + +fun newFun(): T? = null + +fun foo(): String? { + return oldFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt.after new file mode 100644 index 00000000000..dabcc69ac22 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitInPatternImplicitInUsage.kt.after @@ -0,0 +1,12 @@ +// "Replace with 'newFun()'" "true" + +@deprecated("", ReplaceWith("newFun()")) +fun oldFun(): T? { + return newFun() +} + +fun newFun(): T? = null + +fun foo(): String? { + return newFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt new file mode 100644 index 00000000000..33ac9fc6e02 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt @@ -0,0 +1,12 @@ +// "Replace with 'newFun()'" "true" + +@deprecated("", ReplaceWith("newFun()")) +fun oldFun() { + newFun() +} + +fun newFun(){} + +fun foo() { + oldFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt.after new file mode 100644 index 00000000000..30fc9bbf986 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/explicitTypeArg.kt.after @@ -0,0 +1,12 @@ +// "Replace with 'newFun()'" "true" + +@deprecated("", ReplaceWith("newFun()")) +fun oldFun() { + newFun() +} + +fun newFun(){} + +fun foo() { + newFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt new file mode 100644 index 00000000000..94bf7597000 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt @@ -0,0 +1,12 @@ +// "Replace with 'newFun(p)'" "true" + +@deprecated("", ReplaceWith("newFun(p)")) +fun oldFun(p: List) { + newFun(p) +} + +fun newFun(p: List){} + +fun foo() { + oldFun(listOf("a")) +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt.after new file mode 100644 index 00000000000..5cdd03109c9 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/keepInUserCodeRuntime.kt.after @@ -0,0 +1,12 @@ +// "Replace with 'newFun(p)'" "true" + +@deprecated("", ReplaceWith("newFun(p)")) +fun oldFun(p: List) { + newFun(p) +} + +fun newFun(p: List){} + +fun foo() { + newFun(listOf("a")) +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt new file mode 100644 index 00000000000..b171a762bb4 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt @@ -0,0 +1,14 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + oldFun(bar()) +} + +fun bar(): java.io.File? = null diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt.after new file mode 100644 index 00000000000..501a627a09c --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/noImplicitTypeArgImportRuntime.kt.after @@ -0,0 +1,14 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + newFun(bar()) +} + +fun bar(): java.io.File? = null diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt new file mode 100644 index 00000000000..68c1efb5145 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt @@ -0,0 +1,12 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + oldFun("a") +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt.after new file mode 100644 index 00000000000..ab7aa14cefc --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/typeArguments/nonEmptyVarargRuntime.kt.after @@ -0,0 +1,12 @@ +// "Replace with 'newFun(*elements)'" "true" + +@deprecated("", ReplaceWith("newFun(*elements)")) +fun oldFun(vararg elements: T) { + newFun(*elements) +} + +fun newFun(vararg elements: T){} + +fun foo() { + newFun("a") +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt b/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt new file mode 100644 index 00000000000..77dc934fa37 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt @@ -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() { + oldFun() +} diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt.after b/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt.after new file mode 100644 index 00000000000..e87945ce804 --- /dev/null +++ b/idea/testData/quickfix/deprecatedSymbolUsage/vararg/noImportRuntime.kt.after @@ -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() { + newFun() +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index cd4516a04bf..1ff6bd060cf 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -3126,6 +3126,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { 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") public void testComplexExpressionUsedTwice() throws Exception { 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") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -3546,6 +3597,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { 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") public void testShortArrayRuntime() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/vararg/shortArrayRuntime.kt");