Inline Variable: Warn about non-Kotlin usages

#KT-8885 Fixed
This commit is contained in:
Alexey Sedunov
2015-12-04 18:18:33 +03:00
parent ffb382e3bc
commit b5fad71b18
@@ -33,10 +33,12 @@ import com.intellij.refactoring.HelpID
import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.refactoring.util.RefactoringMessageDialog import com.intellij.refactoring.util.RefactoringMessageDialog
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.refactoring.checkConflictsInteractively
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
@@ -52,7 +54,9 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
import java.util.*
class KotlinInlineValHandler : InlineActionHandler() { class KotlinInlineValHandler : InlineActionHandler() {
override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE
@@ -67,8 +71,16 @@ class KotlinInlineValHandler : InlineActionHandler() {
val file = declaration.getContainingKtFile() val file = declaration.getContainingKtFile()
val name = declaration.name ?: return val name = declaration.name ?: return
val referenceExpressions = ReferencesSearch.search(declaration).mapNotNull() { val references = ReferencesSearch.search(declaration)
(it.element as? KtExpression)?.getQualifiedExpressionForSelectorOrThis() val referenceExpressions = ArrayList<KtExpression>()
val foreignUsages = ArrayList<PsiElement>()
for (ref in references) {
val refElement = ref.element ?: continue
if (refElement !is KtElement) {
foreignUsages.add(refElement)
continue
}
referenceExpressions.addIfNotNull((refElement as? KtExpression)?.getQualifiedExpressionForSelectorOrThis())
} }
if (referenceExpressions.isEmpty()) { if (referenceExpressions.isEmpty()) {
@@ -108,32 +120,45 @@ class KotlinInlineValHandler : InlineActionHandler() {
highlightExpressions(project, editor, referenceExpressions) highlightExpressions(project, editor, referenceExpressions)
} }
if (!showDialog(project, name, declaration, referenceExpressions)) { fun performRefactoring() {
if (canHighlight) { if (!showDialog(project, name, declaration, referenceExpressions)) {
val statusBar = WindowManager.getInstance().getStatusBar(project) if (canHighlight) {
statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting") val statusBar = WindowManager.getInstance().getStatusBar(project)
statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting")
}
return
}
project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) {
val inlinedExpressions = referenceExpressions.mapNotNull { referenceExpression ->
if (assignments.contains(referenceExpression.parent)) return@mapNotNull null
referenceExpression.replaced(initializer)
}
assignments.forEach { it.delete() }
declaration.delete()
if (inlinedExpressions.isEmpty()) return@executeWriteCommand
typeArgumentsForCall?.let { addTypeArguments(it, inlinedExpressions) }
parametersForFunctionLiteral?.let { addFunctionLiteralParameterTypes(it, inlinedExpressions) }
if (canHighlight) {
highlightExpressions(project, editor, inlinedExpressions)
}
} }
return
} }
project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) { if (foreignUsages.isNotEmpty()) {
val inlinedExpressions = referenceExpressions.mapNotNull { referenceExpression -> val conflicts = MultiMap<PsiElement, String>().apply {
if (assignments.contains(referenceExpression.parent)) return@mapNotNull null putValue(null, "Property '$name' has non-Kotlin usages. They won't be processed by the Inline refactoring.")
referenceExpression.replaced(initializer) foreignUsages.forEach { putValue(it, it.text) }
}
assignments.forEach { it.delete() }
declaration.delete()
if (inlinedExpressions.isEmpty()) return@executeWriteCommand
typeArgumentsForCall?.let { addTypeArguments(it, inlinedExpressions) }
parametersForFunctionLiteral?.let { addFunctionLiteralParameterTypes(it, inlinedExpressions) }
if (canHighlight) {
highlightExpressions(project, editor, inlinedExpressions)
} }
project.checkConflictsInteractively(conflicts) { performRefactoring() }
}
else {
performRefactoring()
} }
} }