Initial support for class usages replacement with ReplaceWith
This commit is contained in:
@@ -16,9 +16,9 @@
|
|||||||
|
|
||||||
package kotlin
|
package kotlin
|
||||||
|
|
||||||
import kotlin.annotation.*
|
import kotlin.annotation.AnnotationRetention.BINARY
|
||||||
|
import kotlin.annotation.AnnotationRetention.SOURCE
|
||||||
import kotlin.annotation.AnnotationTarget.*
|
import kotlin.annotation.AnnotationTarget.*
|
||||||
import kotlin.annotation.AnnotationRetention.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the annotated class as a data class. The compiler automatically generates
|
* Marks the annotated class as a data class. The compiler automatically generates
|
||||||
@@ -40,11 +40,11 @@ target(CLASSIFIER, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_S
|
|||||||
public annotation(mustBeDocumented = true) class deprecated(val value: String, val replaceWith: ReplaceWith = ReplaceWith(""))
|
public annotation(mustBeDocumented = true) class deprecated(val value: String, val replaceWith: ReplaceWith = ReplaceWith(""))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a code fragment that can be used to replace a deprecated function or property. Tools such
|
* Specifies a code fragment that can be used to replace a deprecated function, property or class. Tools such
|
||||||
* as IDEs can automatically apply the replacements specified through this annotation.
|
* as IDEs can automatically apply the replacements specified through this annotation.
|
||||||
*
|
*
|
||||||
* @property expression the replacement expression. The replacement expression is interpreted in the context
|
* @property expression the replacement expression. The replacement expression is interpreted in the context
|
||||||
* of the function or property being called, and can reference members of enclosing classes etc.
|
* of the symbol being used, and can reference members of enclosing classes etc.
|
||||||
* For function calls, the replacement expression may contain argument names of the deprecated function,
|
* For function calls, the replacement expression may contain argument names of the deprecated function,
|
||||||
* which will be substituted with actual parameters used in the call being updated. The imports used in the file
|
* which will be substituted with actual parameters used in the call being updated. The imports used in the file
|
||||||
* containing the deprecated function or property are NOT accessible; if the replacement expression refers
|
* containing the deprecated function or property are NOT accessible; if the replacement expression refers
|
||||||
|
|||||||
+16
-1
@@ -50,7 +50,22 @@ import org.jetbrains.kotlin.types.JetType
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun performCallReplacement(
|
class CallableUsageReplacementStrategy(
|
||||||
|
private val replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression
|
||||||
|
) : UsageReplacementStrategy {
|
||||||
|
|
||||||
|
override fun createReplacer(usage: JetSimpleNameExpression): (() -> JetElement)? {
|
||||||
|
val bindingContext = usage.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val resolvedCall = usage.getResolvedCall(bindingContext) ?: return null
|
||||||
|
if (!resolvedCall.status.isSuccess) return null
|
||||||
|
return {
|
||||||
|
// copy replacement expression because it is modified by performCallReplacement
|
||||||
|
performCallReplacement(usage, bindingContext, resolvedCall, replacement.copy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performCallReplacement(
|
||||||
element: JetSimpleNameExpression,
|
element: JetSimpleNameExpression,
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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.quickfix.replaceWith
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.JetElement
|
||||||
|
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetUserType
|
||||||
|
|
||||||
|
class ClassUsageReplacementStrategy(
|
||||||
|
private val replacement: JetUserType
|
||||||
|
) : UsageReplacementStrategy {
|
||||||
|
|
||||||
|
override fun createReplacer(usage: JetSimpleNameExpression): (() -> JetElement)? {
|
||||||
|
if (usage !is JetNameReferenceExpression) return null
|
||||||
|
|
||||||
|
val parent = usage.parent
|
||||||
|
when (parent) {
|
||||||
|
is JetUserType -> {
|
||||||
|
return {
|
||||||
|
val replaced = parent.replaced(replacement)
|
||||||
|
ShortenReferences.DEFAULT.process(replaced)
|
||||||
|
} //TODO: type arguments and type arguments of outer class are lost
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return null //TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-13
@@ -21,7 +21,6 @@ import com.intellij.codeInsight.intention.IntentionAction
|
|||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
@@ -29,9 +28,7 @@ import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
|||||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||||
import org.jetbrains.kotlin.idea.quickfix.moveCaret
|
import org.jetbrains.kotlin.idea.quickfix.moveCaret
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|
||||||
|
|
||||||
public class DeprecatedSymbolUsageFix(
|
public class DeprecatedSymbolUsageFix(
|
||||||
element: JetSimpleNameExpression/*TODO?*/,
|
element: JetSimpleNameExpression/*TODO?*/,
|
||||||
@@ -40,17 +37,10 @@ public class DeprecatedSymbolUsageFix(
|
|||||||
|
|
||||||
override fun getFamilyName() = "Replace deprecated symbol usage"
|
override fun getFamilyName() = "Replace deprecated symbol usage"
|
||||||
|
|
||||||
override fun getText() = "Replace with '${replaceWith.expression}'" //TODO: substitute?
|
override fun getText() = "Replace with '${replaceWith.pattern}'" //TODO: substitute?
|
||||||
|
|
||||||
override fun invoke(
|
|
||||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
|
||||||
bindingContext: BindingContext,
|
|
||||||
replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression,
|
|
||||||
project: Project,
|
|
||||||
editor: Editor?
|
|
||||||
) {
|
|
||||||
val result = performCallReplacement(element, bindingContext, resolvedCall, replacement)
|
|
||||||
|
|
||||||
|
override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) {
|
||||||
|
val result = replacementStrategy.createReplacer(element)!!.invoke()
|
||||||
val offset = (result.getCalleeExpressionIfAny() ?: result).textOffset
|
val offset = (result.getCalleeExpressionIfAny() ?: result).textOffset
|
||||||
editor?.moveCaret(offset)
|
editor?.moveCaret(offset)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-31
@@ -22,61 +22,36 @@ import com.intellij.psi.PsiFile
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
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.OptionalParametersHelper
|
||||||
import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction
|
import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
|
|
||||||
//TODO: replacement of class usages
|
|
||||||
//TODO: different replacements for property accessors
|
//TODO: different replacements for property accessors
|
||||||
|
|
||||||
public abstract class DeprecatedSymbolUsageFixBase(
|
public abstract class DeprecatedSymbolUsageFixBase(
|
||||||
element: JetSimpleNameExpression/*TODO?*/,
|
element: JetSimpleNameExpression,
|
||||||
val replaceWith: ReplaceWith
|
val replaceWith: ReplaceWith
|
||||||
) : JetIntentionAction<JetSimpleNameExpression>(element) {
|
) : JetIntentionAction<JetSimpleNameExpression>(element) {
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
if (!super.isAvailable(project, editor, file)) return false
|
if (!super.isAvailable(project, editor, file)) return false
|
||||||
|
val strategy = UsageReplacementStrategy.build(element, replaceWith)
|
||||||
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
|
return strategy != null && strategy.createReplacer(element) != null
|
||||||
if (!resolvedCall.status.isSuccess) return false
|
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
|
||||||
if (replaceWithPattern(descriptor, project) != replaceWith) return false
|
|
||||||
|
|
||||||
try {
|
|
||||||
JetPsiFactory(project).createExpression(replaceWith.expression)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
catch(e: Exception) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
final override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||||
val bindingContext = element.analyze()
|
val strategy = UsageReplacementStrategy.build(element, replaceWith)!!
|
||||||
val resolvedCall = element.getResolvedCall(bindingContext)!!
|
invoke(strategy, project, editor)
|
||||||
val descriptor = resolvedCall.resultingDescriptor
|
|
||||||
|
|
||||||
val replacement = ReplaceWithAnnotationAnalyzer.analyze(replaceWith, descriptor, element.getResolutionFacade())
|
|
||||||
|
|
||||||
invoke(resolvedCall, bindingContext, replacement, project, editor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun invoke(
|
protected abstract fun invoke(
|
||||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
replacementStrategy: UsageReplacementStrategy,
|
||||||
bindingContext: BindingContext,
|
|
||||||
replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression,
|
|
||||||
project: Project,
|
project: Project,
|
||||||
editor: Editor?)
|
editor: Editor?)
|
||||||
|
|
||||||
|
|||||||
+6
-21
@@ -27,10 +27,8 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|
||||||
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
import org.jetbrains.kotlin.idea.quickfix.JetSingleIntentionActionFactory
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
@@ -46,10 +44,6 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.renderer.NameShortness
|
import org.jetbrains.kotlin.renderer.NameShortness
|
||||||
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
|
|
||||||
public class DeprecatedSymbolUsageInWholeProjectFix(
|
public class DeprecatedSymbolUsageInWholeProjectFix(
|
||||||
element: JetSimpleNameExpression,
|
element: JetSimpleNameExpression,
|
||||||
@@ -68,16 +62,10 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
|||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
if (!super.isAvailable(project, editor, file)) return false
|
if (!super.isAvailable(project, editor, file)) return false
|
||||||
val targetPsiElement = element.mainReference.resolve()
|
val targetPsiElement = element.mainReference.resolve()
|
||||||
return targetPsiElement is JetNamedFunction || targetPsiElement is JetProperty
|
return targetPsiElement is JetNamedFunction || targetPsiElement is JetProperty //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invoke(
|
override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) {
|
||||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
|
||||||
bindingContext: BindingContext,
|
|
||||||
replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression,
|
|
||||||
project: Project,
|
|
||||||
editor: Editor?
|
|
||||||
) {
|
|
||||||
val psiElement = element.mainReference.resolve()!!
|
val psiElement = element.mainReference.resolve()!!
|
||||||
|
|
||||||
ProgressManager.getInstance().run(
|
ProgressManager.getInstance().run(
|
||||||
@@ -89,12 +77,12 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
|||||||
.filterIsInstance<JetSimpleNameReference>()
|
.filterIsInstance<JetSimpleNameReference>()
|
||||||
.map { ref -> ref.expression }
|
.map { ref -> ref.expression }
|
||||||
}
|
}
|
||||||
replaceUsages(project, usages, replacement)
|
replaceUsages(project, usages, replacementStrategy)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun replaceUsages(project: Project, usages: Collection<JetSimpleNameExpression>, replacement: ReplaceWithAnnotationAnalyzer.ReplacementExpression) {
|
private fun replaceUsages(project: Project, usages: Collection<JetSimpleNameExpression>, replacementStrategy: UsageReplacementStrategy) {
|
||||||
UIUtil.invokeLaterIfNeeded {
|
UIUtil.invokeLaterIfNeeded {
|
||||||
project.executeWriteCommand(text) {
|
project.executeWriteCommand(text) {
|
||||||
// we should delete imports later to not affect other usages
|
// we should delete imports later to not affect other usages
|
||||||
@@ -104,6 +92,7 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
|||||||
try {
|
try {
|
||||||
if (!usage.isValid) continue // TODO: nested calls
|
if (!usage.isValid) continue // TODO: nested calls
|
||||||
|
|
||||||
|
//TODO: keep the import if we don't know how to replace some of the usages
|
||||||
val importDirective = usage.getStrictParentOfType<JetImportDirective>()
|
val importDirective = usage.getStrictParentOfType<JetImportDirective>()
|
||||||
if (importDirective != null) {
|
if (importDirective != null) {
|
||||||
if (!importDirective.isAllUnder && importDirective.targetDescriptors().size() == 1) {
|
if (!importDirective.isAllUnder && importDirective.targetDescriptors().size() == 1) {
|
||||||
@@ -112,11 +101,7 @@ public class DeprecatedSymbolUsageInWholeProjectFix(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val bindingContext = usage.analyze(BodyResolveMode.PARTIAL)
|
replacementStrategy.createReplacer(usage)?.invoke()
|
||||||
val resolvedCall = usage.getResolvedCall(bindingContext) ?: continue
|
|
||||||
if (!resolvedCall.status.isSuccess) continue
|
|
||||||
// copy replacement expression because it is modified by performReplacement
|
|
||||||
performCallReplacement(usage, bindingContext, resolvedCall, replacement.copy())
|
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
|
|||||||
+87
-28
@@ -26,6 +26,8 @@ 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.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention
|
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention
|
||||||
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
@@ -36,6 +38,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
|||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
|
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
|
||||||
@@ -50,7 +53,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
|||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class ReplaceWith(val expression: String, vararg val imports: String)
|
data class ReplaceWith(val pattern: 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")
|
||||||
@@ -63,11 +66,11 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
fun copy() = ReplacementExpression(expression.copied(), fqNamesToImport)
|
fun copy() = ReplacementExpression(expression.copied(), fqNamesToImport)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun analyze(
|
public fun analyzeCallableReplacement(
|
||||||
annotation: ReplaceWith,
|
annotation: ReplaceWith,
|
||||||
symbolDescriptor: CallableDescriptor,
|
symbolDescriptor: CallableDescriptor,
|
||||||
resolutionFacade: ResolutionFacade
|
resolutionFacade: ResolutionFacade
|
||||||
): ReplacementExpression {
|
): ReplacementExpression? {
|
||||||
val originalDescriptor = (if (symbolDescriptor is CallableMemberDescriptor)
|
val originalDescriptor = (if (symbolDescriptor is CallableMemberDescriptor)
|
||||||
DescriptorUtils.unwrapFakeOverride(symbolDescriptor)
|
DescriptorUtils.unwrapFakeOverride(symbolDescriptor)
|
||||||
else
|
else
|
||||||
@@ -79,23 +82,22 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
annotation: ReplaceWith,
|
annotation: ReplaceWith,
|
||||||
symbolDescriptor: CallableDescriptor,
|
symbolDescriptor: CallableDescriptor,
|
||||||
resolutionFacade: ResolutionFacade
|
resolutionFacade: ResolutionFacade
|
||||||
): ReplacementExpression {
|
): ReplacementExpression? {
|
||||||
val psiFactory = JetPsiFactory(resolutionFacade.project)
|
val psiFactory = JetPsiFactory(resolutionFacade.project)
|
||||||
var expression = psiFactory.createExpression(annotation.expression)
|
var expression = try {
|
||||||
|
psiFactory.createExpression(annotation.pattern)
|
||||||
val importFqNames = annotation.imports
|
}
|
||||||
.filter { FqNameUnsafe.isValid(it) }
|
catch(e: Exception) {
|
||||||
.map { FqNameUnsafe(it) }
|
return null
|
||||||
.filter { it.isSafe }
|
}
|
||||||
.mapTo(LinkedHashSet<FqName>()) { it.toSafe() }
|
|
||||||
|
|
||||||
val explicitlyImportedSymbols = importFqNames.flatMap { resolutionFacade.resolveImportReference(symbolDescriptor.module, it) }
|
|
||||||
|
|
||||||
|
val module = symbolDescriptor.module
|
||||||
|
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
|
||||||
val additionalScopes = resolutionFacade.getFrontendService(FileScopeProvider.AdditionalScopes::class.java)
|
val additionalScopes = resolutionFacade.getFrontendService(FileScopeProvider.AdditionalScopes::class.java)
|
||||||
val scope = getResolutionScope(symbolDescriptor, symbolDescriptor,
|
val scope = getResolutionScope(symbolDescriptor, symbolDescriptor,
|
||||||
listOf(ExplicitImportsScope(explicitlyImportedSymbols)) + additionalScopes.scopes)
|
listOf(explicitImportsScope) + additionalScopes.scopes)
|
||||||
|
|
||||||
var bindingContext = analyzeInContext(expression, symbolDescriptor, scope, resolutionFacade)
|
var bindingContext = analyzeInContext(expression, module, scope, resolutionFacade)
|
||||||
|
|
||||||
val typeArgsToAdd = ArrayList<Pair<JetCallExpression, JetTypeArgumentList>>()
|
val typeArgsToAdd = ArrayList<Pair<JetCallExpression, JetTypeArgumentList>>()
|
||||||
expression.forEachDescendantOfType<JetCallExpression> {
|
expression.forEachDescendantOfType<JetCallExpression> {
|
||||||
@@ -110,10 +112,11 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reanalyze expression - new usages of type parameters may be added
|
// reanalyze expression - new usages of type parameters may be added
|
||||||
bindingContext = analyzeInContext(expression, symbolDescriptor, scope, resolutionFacade)
|
bindingContext = analyzeInContext(expression, module, scope, resolutionFacade)
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiversToAdd = ArrayList<Pair<JetExpression, JetExpression>>()
|
val receiversToAdd = ArrayList<Pair<JetExpression, JetExpression>>()
|
||||||
|
val importFqNames = importFqNames(annotation).toMutableSet()
|
||||||
|
|
||||||
expression.forEachDescendantOfType<JetSimpleNameExpression> { expression ->
|
expression.forEachDescendantOfType<JetSimpleNameExpression> { expression ->
|
||||||
val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType
|
val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType
|
||||||
@@ -158,14 +161,70 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
return ReplacementExpression(expression, importFqNames)
|
return ReplacementExpression(expression, importFqNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun analyzeClassReplacement(
|
||||||
|
annotation: ReplaceWith,
|
||||||
|
symbolDescriptor: ClassDescriptor,
|
||||||
|
resolutionFacade: ResolutionFacade
|
||||||
|
): JetUserType? {
|
||||||
|
val psiFactory = JetPsiFactory(resolutionFacade.project)
|
||||||
|
val typeReference = try {
|
||||||
|
psiFactory.createType(annotation.pattern)
|
||||||
|
}
|
||||||
|
catch(e: Exception) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (typeReference.typeElement !is JetUserType) return null
|
||||||
|
|
||||||
|
val module = symbolDescriptor.module
|
||||||
|
|
||||||
|
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
|
||||||
|
val scope = getResolutionScope(symbolDescriptor, symbolDescriptor, listOf(explicitImportsScope))
|
||||||
|
|
||||||
|
val dummyExpression = psiFactory.createExpressionByPattern("x as $0", typeReference) as JetBinaryExpressionWithTypeRHS
|
||||||
|
|
||||||
|
val bindingContext = analyzeInContext(dummyExpression, module, scope, resolutionFacade)
|
||||||
|
|
||||||
|
val typesToQualify = ArrayList<Pair<JetNameReferenceExpression, FqName>>()
|
||||||
|
|
||||||
|
dummyExpression.right!!.forEachDescendantOfType<JetNameReferenceExpression> { expression ->
|
||||||
|
val parentType = expression.parent as? JetUserType ?: return@forEachDescendantOfType
|
||||||
|
if (parentType.qualifier != null) return@forEachDescendantOfType
|
||||||
|
val targetClass = bindingContext[BindingContext.REFERENCE_TARGET, expression] as? ClassDescriptor ?: return@forEachDescendantOfType
|
||||||
|
val fqName = targetClass.fqNameUnsafe
|
||||||
|
if (fqName.isSafe) {
|
||||||
|
typesToQualify.add(expression to fqName.toSafe())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((nameExpression, fqName) in typesToQualify) {
|
||||||
|
nameExpression.mainReference.bindToFqName(fqName, JetSimpleNameReference.ShorteningMode.NO_SHORTENING)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dummyExpression.right!!.typeElement as JetUserType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildExplicitImportsScope(annotation: ReplaceWith, resolutionFacade: ResolutionFacade, module: ModuleDescriptor): ExplicitImportsScope {
|
||||||
|
val importedSymbols = importFqNames(annotation)
|
||||||
|
.flatMap { resolutionFacade.resolveImportReference(module, it) }
|
||||||
|
return ExplicitImportsScope(importedSymbols)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun importFqNames(annotation: ReplaceWith): List<FqName> {
|
||||||
|
return annotation.imports
|
||||||
|
.filter { FqNameUnsafe.isValid(it) }
|
||||||
|
.map { FqNameUnsafe(it) }
|
||||||
|
.filter { it.isSafe }
|
||||||
|
.map { it.toSafe() }
|
||||||
|
}
|
||||||
|
|
||||||
private fun analyzeInContext(
|
private fun analyzeInContext(
|
||||||
expression: JetExpression,
|
expression: JetExpression,
|
||||||
symbolDescriptor: CallableDescriptor,
|
module: ModuleDescriptor,
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
resolutionFacade: ResolutionFacade
|
resolutionFacade: ResolutionFacade
|
||||||
): BindingContext {
|
): BindingContext {
|
||||||
val traceContext = BindingTraceContext()
|
val traceContext = BindingTraceContext()
|
||||||
resolutionFacade.getFrontendService(symbolDescriptor.module, ExpressionTypingServices::class.java)
|
resolutionFacade.getFrontendService(module, ExpressionTypingServices::class.java)
|
||||||
.getTypeInfo(scope, expression, TypeUtils.NO_EXPECTED_TYPE, DataFlowInfo.EMPTY, traceContext, false)
|
.getTypeInfo(scope, expression, TypeUtils.NO_EXPECTED_TYPE, DataFlowInfo.EMPTY, traceContext, false)
|
||||||
return traceContext.bindingContext
|
return traceContext.bindingContext
|
||||||
}
|
}
|
||||||
@@ -180,22 +239,22 @@ object ReplaceWithAnnotationAnalyzer {
|
|||||||
is PackageViewDescriptor ->
|
is PackageViewDescriptor ->
|
||||||
ChainedScope(ownerDescriptor, "ReplaceWith resolution scope", descriptor.memberScope, *additionalScopes.toTypedArray()).asLexicalScope()
|
ChainedScope(ownerDescriptor, "ReplaceWith resolution scope", descriptor.memberScope, *additionalScopes.toTypedArray()).asLexicalScope()
|
||||||
|
|
||||||
is ClassDescriptorWithResolutionScopes ->
|
|
||||||
descriptor.scopeForMemberDeclarationResolution
|
|
||||||
|
|
||||||
is ClassDescriptor -> {
|
is ClassDescriptor -> {
|
||||||
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes)
|
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes)
|
||||||
ClassResolutionScopesSupport(descriptor, LockBasedStorageManager.NO_LOCKS, { outerScope }).scopeForMemberDeclarationResolution()
|
ClassResolutionScopesSupport(descriptor, LockBasedStorageManager.NO_LOCKS, { outerScope }).scopeForMemberDeclarationResolution()
|
||||||
}
|
}
|
||||||
|
|
||||||
is FunctionDescriptor ->
|
is FunctionDescriptor -> {
|
||||||
FunctionDescriptorUtil.getFunctionInnerScope(getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes),
|
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes)
|
||||||
descriptor, RedeclarationHandler.DO_NOTHING)
|
FunctionDescriptorUtil.getFunctionInnerScope(outerScope, descriptor, RedeclarationHandler.DO_NOTHING)
|
||||||
|
}
|
||||||
|
|
||||||
is PropertyDescriptor ->
|
is PropertyDescriptor -> {
|
||||||
JetScopeUtils.getPropertyDeclarationInnerScope(descriptor,
|
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes)
|
||||||
getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes),
|
JetScopeUtils.getPropertyDeclarationInnerScope(descriptor, outerScope, RedeclarationHandler.DO_NOTHING)
|
||||||
RedeclarationHandler.DO_NOTHING)
|
}
|
||||||
|
|
||||||
|
//TODO: it's not correct (it does not use additionalScopes!), drop this branch
|
||||||
is LocalVariableDescriptor -> {
|
is LocalVariableDescriptor -> {
|
||||||
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as JetDeclaration
|
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) as JetDeclaration
|
||||||
declaration.analyze()[BindingContext.RESOLUTION_SCOPE, declaration]!!.asLexicalScope()
|
declaration.analyze()[BindingContext.RESOLUTION_SCOPE, declaration]!!.asLexicalScope()
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.quickfix.replaceWith
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
|
import org.jetbrains.kotlin.psi.JetElement
|
||||||
|
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
|
interface UsageReplacementStrategy {
|
||||||
|
fun createReplacer(usage: JetSimpleNameExpression): (() -> JetElement)?
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun build(element: JetSimpleNameExpression, replaceWith: ReplaceWith): UsageReplacementStrategy? {
|
||||||
|
val resolutionFacade = element.getResolutionFacade()
|
||||||
|
val bindingContext = resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
|
||||||
|
val target = element.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return null
|
||||||
|
|
||||||
|
// check that ReplaceWith hasn't changed
|
||||||
|
if (DeprecatedSymbolUsageFixBase.replaceWithPattern(target, resolutionFacade.project) != replaceWith) return null
|
||||||
|
|
||||||
|
when (target) {
|
||||||
|
is CallableDescriptor -> {
|
||||||
|
val resolvedCall = element.getResolvedCall(bindingContext) ?: return null
|
||||||
|
if (!resolvedCall.status.isSuccess) return null
|
||||||
|
val replacement = ReplaceWithAnnotationAnalyzer.analyzeCallableReplacement(replaceWith, target, resolutionFacade) ?: return null
|
||||||
|
return CallableUsageReplacementStrategy(replacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ClassDescriptor -> {
|
||||||
|
val replacement = ReplaceWithAnnotationAnalyzer.analyzeClassReplacement(replaceWith, target, resolutionFacade) ?: return null
|
||||||
|
return ClassUsageReplacementStrategy(replacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
import dependency.NewClass
|
||||||
|
import dependency.OldClass
|
||||||
|
|
||||||
|
fun foo(): NewClass? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
import dependency.OldClass
|
||||||
|
|
||||||
|
fun foo(): <caret>OldClass? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Replace with 'File'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("File", "java.io.File"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
fun foo(): OldClass<caret>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import java.io.File
|
||||||
|
|
||||||
|
// "Replace with 'File'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("File", "java.io.File"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
fun foo(): File? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
class Outer {
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): Outer.OldClass<caret>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
class Outer {
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(): Outer.NewClass? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
|
||||||
|
fun foo(): ppp.OldClass<caret>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
|
||||||
|
fun foo(): NewClass? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
// "Replace with 'java.io.File'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("java.io.File"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
fun foo(): OldClass<caret>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import java.io.File
|
||||||
|
|
||||||
|
// "Replace with 'java.io.File'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("java.io.File"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
fun foo(): File? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
|
||||||
|
fun foo(): OldClass<caret>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// "Replace with 'NewClass'" "true"
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("NewClass"))
|
||||||
|
class OldClass
|
||||||
|
|
||||||
|
class NewClass
|
||||||
|
|
||||||
|
fun foo(): NewClass? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -906,6 +906,21 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
|||||||
doTestWithExtraFile(fileName);
|
doTestWithExtraFile(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ClassUsages extends AbstractQuickFixMultiFileTest {
|
||||||
|
@TestMetadata("addImportFromSamePackage.before.Main.kt")
|
||||||
|
public void testAddImportFromSamePackage() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/addImportFromSamePackage.before.Main.kt");
|
||||||
|
doTestWithExtraFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInClassUsages() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/classUsages"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/imports")
|
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/imports")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -3312,11 +3312,41 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/classUsages"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedSymbolUsage/classUsages"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("imports.kt")
|
||||||
|
public void testImports() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/imports.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nestedClassToNestedClass.kt")
|
||||||
|
public void testNestedClassToNestedClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/nestedClassToNestedClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noAnnotationConstructorUsage.kt")
|
@TestMetadata("noAnnotationConstructorUsage.kt")
|
||||||
public void testNoAnnotationConstructorUsage() throws Exception {
|
public void testNoAnnotationConstructorUsage() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/noAnnotationConstructorUsage.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/noAnnotationConstructorUsage.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("qualifiedClassName.kt")
|
||||||
|
public void testQualifiedClassName() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/qualifiedClassName.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("qualifiedClassNameInPattern.kt")
|
||||||
|
public void testQualifiedClassNameInPattern() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/qualifiedClassNameInPattern.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/classUsages/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/functionLiteralArguments")
|
@TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage/functionLiteralArguments")
|
||||||
|
|||||||
Reference in New Issue
Block a user