Convert to Kotlin: KotlinRefactoringUtil2 (replace object with top-level declarations)
This commit is contained in:
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiWhiteSpace;
|
|||||||
import com.intellij.util.IncorrectOperationException;
|
import com.intellij.util.IncorrectOperationException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression;
|
import org.jetbrains.kotlin.psi.KtBlockExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
@@ -44,7 +44,7 @@ public abstract class KotlinUnwrapRemoveBase extends AbstractUnwrapper<KotlinUnw
|
|||||||
@Override
|
@Override
|
||||||
public String getDescription(PsiElement e) {
|
public String getDescription(PsiElement e) {
|
||||||
assert e instanceof KtElement;
|
assert e instanceof KtElement;
|
||||||
return KotlinBundle.message(key, KotlinRefactoringUtil2.INSTANCE.getExpressionShortText((KtElement) e));
|
return KotlinBundle.message(key, KotlinRefactoringUtil2Kt.getExpressionShortText((KtElement) e));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canExtractExpression(@NotNull KtExpression expression, @NotNull KtElement parent) {
|
protected boolean canExtractExpression(@NotNull KtExpression expression, @NotNull KtElement parent) {
|
||||||
|
|||||||
@@ -33,11 +33,12 @@ import org.jetbrains.kotlin.idea.findUsages.handlers.DelegatingFindMemberUsagesH
|
|||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindMemberUsagesHandler
|
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindMemberUsagesHandler
|
||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinTypeParameterFindUsagesHandler
|
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinTypeParameterFindUsagesHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2
|
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods
|
||||||
import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator
|
import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isOverridable
|
import org.jetbrains.kotlin.psi.psiUtil.isOverridable
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
|
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactory() {
|
class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactory() {
|
||||||
val javaHandlerFactory = JavaFindUsagesHandlerFactory(project)
|
val javaHandlerFactory = JavaFindUsagesHandlerFactory(project)
|
||||||
@@ -107,7 +108,7 @@ class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactor
|
|||||||
return KotlinFindMemberUsagesHandler.getInstance(declaration, factory = this)
|
return KotlinFindMemberUsagesHandler.getInstance(declaration, factory = this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val declarationsToSearch = KotlinRefactoringUtil2.checkSuperMethods(declaration, null, "super.methods.action.key.find.usages")
|
val declarationsToSearch = checkSuperMethods(declaration, null, "super.methods.action.key.find.usages")
|
||||||
return handlerForMultiple(declaration, declarationsToSearch)
|
return handlerForMultiple(declaration, declarationsToSearch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -33,7 +33,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinClassFindUsagesOptions;
|
import org.jetbrains.kotlin.idea.findUsages.KotlinClassFindUsagesOptions;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
import org.jetbrains.kotlin.psi.KtClass;
|
import org.jetbrains.kotlin.psi.KtClass;
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||||
@@ -154,7 +154,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
|||||||
: klass.getUserData(ORIGINAL_CLASS);
|
: klass.getUserData(ORIGINAL_CLASS);
|
||||||
|
|
||||||
if (originalClass != null) {
|
if (originalClass != null) {
|
||||||
coloredComponent.append(KotlinRefactoringUtil2.INSTANCE.formatClass(originalClass));
|
coloredComponent.append(KotlinRefactoringUtil2Kt.formatClass(originalClass));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -26,7 +26,7 @@ import com.intellij.ui.SimpleColoredComponent;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions;
|
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class KotlinFindFunctionUsagesDialog extends FindMethodUsagesDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) {
|
public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) {
|
||||||
coloredComponent.append(KotlinRefactoringUtil2.INSTANCE.formatJavaOrLightMethod((PsiMethod) myPsiElement));
|
coloredComponent.append(KotlinRefactoringUtil2Kt.formatJavaOrLightMethod((PsiMethod) myPsiElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -60,413 +60,410 @@ import javax.swing.DefaultListCellRenderer
|
|||||||
import javax.swing.DefaultListModel
|
import javax.swing.DefaultListModel
|
||||||
import javax.swing.JList
|
import javax.swing.JList
|
||||||
|
|
||||||
object KotlinRefactoringUtil2 {
|
fun wrapOrSkip(s: String, inCode: Boolean) = if (inCode) "<code>$s</code>" else s
|
||||||
fun wrapOrSkip(s: String, inCode: Boolean) = if (inCode) "<code>$s</code>" else s
|
|
||||||
|
|
||||||
fun formatClassDescriptor(classDescriptor: DeclarationDescriptor) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor)
|
fun formatClassDescriptor(classDescriptor: DeclarationDescriptor) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor)
|
||||||
|
|
||||||
fun formatPsiClass(
|
fun formatPsiClass(
|
||||||
psiClass: PsiClass,
|
psiClass: PsiClass,
|
||||||
markAsJava: Boolean,
|
markAsJava: Boolean,
|
||||||
inCode: Boolean
|
inCode: Boolean
|
||||||
): String {
|
): String {
|
||||||
var description: String
|
var description: String
|
||||||
|
|
||||||
val kind = if (psiClass.isInterface) "interface " else "class "
|
val kind = if (psiClass.isInterface) "interface " else "class "
|
||||||
description = kind + PsiFormatUtil.formatClass(
|
description = kind + PsiFormatUtil.formatClass(
|
||||||
psiClass,
|
psiClass,
|
||||||
PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
|
PsiFormatUtilBase.SHOW_CONTAINING_CLASS or PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
|
||||||
)
|
)
|
||||||
description = wrapOrSkip(description, inCode)
|
description = wrapOrSkip(description, inCode)
|
||||||
|
|
||||||
return if (markAsJava) "[Java] $description" else description
|
return if (markAsJava) "[Java] $description" else description
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkSuperMethods(
|
||||||
|
declaration: KtDeclaration,
|
||||||
|
ignore: Collection<PsiElement>?,
|
||||||
|
actionStringKey: String
|
||||||
|
): List<PsiElement> {
|
||||||
|
val declarationDescriptor = declaration.resolveToDescriptor() as CallableDescriptor
|
||||||
|
|
||||||
|
if (declarationDescriptor is LocalVariableDescriptor) return listOf(declaration)
|
||||||
|
|
||||||
|
val project = declaration.project
|
||||||
|
val overriddenElementsToDescriptor = HashMap<PsiElement, CallableDescriptor>()
|
||||||
|
for (overriddenDescriptor in DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) {
|
||||||
|
val overriddenDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, overriddenDescriptor) ?: continue
|
||||||
|
if (overriddenDeclaration is KtNamedFunction || overriddenDeclaration is KtProperty || overriddenDeclaration is PsiMethod) {
|
||||||
|
overriddenElementsToDescriptor[overriddenDeclaration] = overriddenDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ignore != null) {
|
||||||
|
overriddenElementsToDescriptor.keys.removeAll(ignore)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkSuperMethods(
|
if (overriddenElementsToDescriptor.isEmpty()) return listOf(declaration)
|
||||||
declaration: KtDeclaration,
|
|
||||||
ignore: Collection<PsiElement>?,
|
|
||||||
actionStringKey: String
|
|
||||||
): List<PsiElement> {
|
|
||||||
val declarationDescriptor = declaration.resolveToDescriptor() as CallableDescriptor
|
|
||||||
|
|
||||||
if (declarationDescriptor is LocalVariableDescriptor) return listOf(declaration)
|
return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, actionStringKey)
|
||||||
|
}
|
||||||
|
|
||||||
val project = declaration.project
|
private fun askUserForMethodsToSearch(
|
||||||
val overriddenElementsToDescriptor = HashMap<PsiElement, CallableDescriptor>()
|
declaration: KtDeclaration,
|
||||||
for (overriddenDescriptor in DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) {
|
declarationDescriptor: CallableDescriptor,
|
||||||
val overriddenDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, overriddenDescriptor) ?: continue
|
overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>,
|
||||||
if (overriddenDeclaration is KtNamedFunction || overriddenDeclaration is KtProperty || overriddenDeclaration is PsiMethod) {
|
actionStringKey: String
|
||||||
overriddenElementsToDescriptor[overriddenDeclaration] = overriddenDescriptor
|
): List<PsiElement> {
|
||||||
|
if (ApplicationManager.getApplication().isUnitTestMode) return overriddenElementsToDescriptor.keys.toList()
|
||||||
|
|
||||||
|
val superClassDescriptions = getClassDescriptions(overriddenElementsToDescriptor)
|
||||||
|
|
||||||
|
val message = KotlinBundle.message(
|
||||||
|
"x.overrides.y.in.class.list",
|
||||||
|
DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declarationDescriptor),
|
||||||
|
"\n${superClassDescriptions.joinToString(separator = "")}",
|
||||||
|
KotlinBundle.message(actionStringKey)
|
||||||
|
)
|
||||||
|
|
||||||
|
val exitCode = Messages.showYesNoCancelDialog(declaration.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
|
||||||
|
when (exitCode) {
|
||||||
|
Messages.YES -> return overriddenElementsToDescriptor.keys.toList()
|
||||||
|
Messages.NO -> return listOf(declaration)
|
||||||
|
else -> return emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClassDescriptions(overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>): List<String> {
|
||||||
|
return overriddenElementsToDescriptor.entries.map { entry ->
|
||||||
|
val (element, descriptor) = entry
|
||||||
|
val description = when (element) {
|
||||||
|
is KtNamedFunction, is KtProperty -> formatClassDescriptor(descriptor.containingDeclaration)
|
||||||
|
is PsiMethod -> {
|
||||||
|
val psiClass = element.containingClass ?: error("Invalid element: ${element.getText()}")
|
||||||
|
formatPsiClass(psiClass, true, false)
|
||||||
|
}
|
||||||
|
else -> error("Unexpected element: ${element.getElementTextWithContext()}")
|
||||||
|
}
|
||||||
|
" $description\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String {
|
||||||
|
val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor)
|
||||||
|
return if (element is PsiClass) {
|
||||||
|
formatPsiClass(element, false, inCode)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wrapOrSkip(formatClassDescriptor(classDescriptor), inCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean): String {
|
||||||
|
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
|
||||||
|
return if (element is PsiMethod) {
|
||||||
|
formatPsiMethod(element, false, inCode)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor) = DescriptorRenderer.COMPACT.render(functionDescriptor)
|
||||||
|
|
||||||
|
fun formatPsiMethod(
|
||||||
|
psiMethod: PsiMethod,
|
||||||
|
showContainingClass: Boolean,
|
||||||
|
inCode: Boolean
|
||||||
|
): String {
|
||||||
|
var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
|
||||||
|
if (showContainingClass) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
options = options or PsiFormatUtilBase.SHOW_CONTAINING_CLASS
|
||||||
|
}
|
||||||
|
|
||||||
|
var description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE)
|
||||||
|
description = wrapOrSkip(description, inCode)
|
||||||
|
|
||||||
|
return "[Java] $description"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatJavaOrLightMethod(method: PsiMethod): String {
|
||||||
|
val originalDeclaration = method.unwrapped
|
||||||
|
return if (originalDeclaration is KtDeclaration) {
|
||||||
|
formatFunctionDescriptor(originalDeclaration.resolveToDescriptor())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
formatPsiMethod(method, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatClass(classOrObject: KtClassOrObject) = formatClassDescriptor(classOrObject.resolveToDescriptor() as ClassDescriptor)
|
||||||
|
|
||||||
|
fun checkParametersInMethodHierarchy(parameter: PsiParameter): Collection<PsiElement>? {
|
||||||
|
val method = parameter.declarationScope as PsiMethod
|
||||||
|
|
||||||
|
val parametersToDelete = collectParametersHierarchy(method, parameter)
|
||||||
|
if (parametersToDelete.size <= 1 || ApplicationManager.getApplication().isUnitTestMode) return parametersToDelete
|
||||||
|
|
||||||
|
val message = KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method))
|
||||||
|
val exitCode = Messages.showOkCancelDialog(parameter.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
|
||||||
|
return if (exitCode == Messages.OK) parametersToDelete else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: generalize breadth-first search
|
||||||
|
private fun collectParametersHierarchy(method: PsiMethod, parameter: PsiParameter): Set<PsiElement> {
|
||||||
|
val queue = ArrayDeque<PsiMethod>()
|
||||||
|
val visited = HashSet<PsiMethod>()
|
||||||
|
val parametersToDelete = HashSet<PsiElement>()
|
||||||
|
|
||||||
|
queue.add(method)
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
val currentMethod = queue.poll()
|
||||||
|
|
||||||
|
visited += currentMethod
|
||||||
|
addParameter(currentMethod, parametersToDelete, parameter)
|
||||||
|
|
||||||
|
currentMethod.findSuperMethods(true)
|
||||||
|
.filter { it !in visited }
|
||||||
|
.forEach { queue.offer(it) }
|
||||||
|
OverridingMethodsSearch.search(currentMethod)
|
||||||
|
.filter { it !in visited }
|
||||||
|
.forEach { queue.offer(it) }
|
||||||
|
}
|
||||||
|
return parametersToDelete
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addParameter(method: PsiMethod, result: MutableSet<PsiElement>, parameter: PsiParameter) {
|
||||||
|
val parameterIndex = parameter.unwrapped!!.parameterIndex()
|
||||||
|
|
||||||
|
if (method is KtLightMethod) {
|
||||||
|
val declaration = method.kotlinOrigin
|
||||||
|
if (declaration is KtFunction) {
|
||||||
|
result.add(declaration.valueParameters[parameterIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.add(method.parameterList.parameters[parameterIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IntroduceRefactoringException::class)
|
||||||
|
fun selectElement(
|
||||||
|
editor: Editor,
|
||||||
|
file: KtFile,
|
||||||
|
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||||
|
callback: (PsiElement?) -> Unit
|
||||||
|
) = selectElement(editor, file, true, elementKinds, callback)
|
||||||
|
|
||||||
|
@Throws(IntroduceRefactoringException::class)
|
||||||
|
fun selectElement(editor: Editor,
|
||||||
|
file: KtFile,
|
||||||
|
failOnEmptySuggestion: Boolean,
|
||||||
|
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||||
|
callback: (PsiElement?) -> Unit) {
|
||||||
|
if (editor.selectionModel.hasSelection()) {
|
||||||
|
var selectionStart = editor.selectionModel.selectionStart
|
||||||
|
var selectionEnd = editor.selectionModel.selectionEnd
|
||||||
|
|
||||||
|
var firstElement: PsiElement = file.findElementAt(selectionStart)!!
|
||||||
|
var lastElement: PsiElement = file.findElementAt(selectionEnd - 1)!!
|
||||||
|
|
||||||
|
if (PsiTreeUtil.getParentOfType(firstElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null
|
||||||
|
&& PsiTreeUtil.getParentOfType(lastElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null) {
|
||||||
|
firstElement = firstElement.getNextSiblingIgnoringWhitespaceAndComments(true)!!
|
||||||
|
lastElement = lastElement.getPrevSiblingIgnoringWhitespaceAndComments(true)!!
|
||||||
|
selectionStart = firstElement.textRange.startOffset
|
||||||
|
selectionEnd = lastElement.textRange.endOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
val element = elementKinds.asSequence()
|
||||||
|
.mapNotNull { findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, it) }
|
||||||
|
.firstOrNull()
|
||||||
|
callback(element)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val offset = editor.caretModel.offset
|
||||||
|
smartSelectElement(editor, file, offset, failOnEmptySuggestion, elementKinds, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IntroduceRefactoringException::class)
|
||||||
|
fun getSmartSelectSuggestions(
|
||||||
|
file: PsiFile,
|
||||||
|
offset: Int,
|
||||||
|
elementKind: CodeInsightUtils.ElementKind
|
||||||
|
): List<KtElement> {
|
||||||
|
if (offset < 0) return emptyList()
|
||||||
|
|
||||||
|
var element: PsiElement? = file.findElementAt(offset) ?: return emptyList()
|
||||||
|
|
||||||
|
if (element is PsiWhiteSpace) return getSmartSelectSuggestions(file, offset - 1, elementKind)
|
||||||
|
|
||||||
|
val elements = ArrayList<KtElement>()
|
||||||
|
while (element != null && !(element is KtBlockExpression && element.parent !is KtFunctionLiteral) &&
|
||||||
|
element !is KtNamedFunction
|
||||||
|
&& element !is KtClassBody) {
|
||||||
|
var addElement = false
|
||||||
|
var keepPrevious = true
|
||||||
|
|
||||||
|
if (element is KtTypeElement) {
|
||||||
|
addElement = elementKind == CodeInsightUtils.ElementKind.TYPE_ELEMENT
|
||||||
|
if (!addElement) {
|
||||||
|
keepPrevious = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ignore != null) {
|
else if (element is KtExpression && element !is KtStatementExpression) {
|
||||||
overriddenElementsToDescriptor.keys.removeAll(ignore)
|
addElement = elementKind == CodeInsightUtils.ElementKind.EXPRESSION
|
||||||
}
|
|
||||||
|
|
||||||
if (overriddenElementsToDescriptor.isEmpty()) return listOf(declaration)
|
|
||||||
|
|
||||||
return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, actionStringKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun askUserForMethodsToSearch(
|
|
||||||
declaration: KtDeclaration,
|
|
||||||
declarationDescriptor: CallableDescriptor,
|
|
||||||
overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>,
|
|
||||||
actionStringKey: String
|
|
||||||
): List<PsiElement> {
|
|
||||||
if (ApplicationManager.getApplication().isUnitTestMode) return overriddenElementsToDescriptor.keys.toList()
|
|
||||||
|
|
||||||
val superClassDescriptions = getClassDescriptions(overriddenElementsToDescriptor)
|
|
||||||
|
|
||||||
val message = KotlinBundle.message(
|
|
||||||
"x.overrides.y.in.class.list",
|
|
||||||
DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declarationDescriptor),
|
|
||||||
"\n${superClassDescriptions.joinToString(separator = "")}",
|
|
||||||
KotlinBundle.message(actionStringKey)
|
|
||||||
)
|
|
||||||
|
|
||||||
val exitCode = Messages.showYesNoCancelDialog(declaration.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
|
|
||||||
when (exitCode) {
|
|
||||||
Messages.YES -> return overriddenElementsToDescriptor.keys.toList()
|
|
||||||
Messages.NO -> return listOf(declaration)
|
|
||||||
else -> return emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClassDescriptions(overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>): List<String> {
|
|
||||||
return overriddenElementsToDescriptor.entries.map { entry ->
|
|
||||||
val (element, descriptor) = entry
|
|
||||||
val description = when (element) {
|
|
||||||
is KtNamedFunction, is KtProperty -> formatClassDescriptor(descriptor.containingDeclaration)
|
|
||||||
is PsiMethod -> {
|
|
||||||
val psiClass = element.containingClass ?: error("Invalid element: ${element.getText()}")
|
|
||||||
formatPsiClass(psiClass, true, false)
|
|
||||||
}
|
|
||||||
else -> error("Unexpected element: ${element.getElementTextWithContext()}")
|
|
||||||
}
|
|
||||||
" $description\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String {
|
|
||||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor)
|
|
||||||
return if (element is PsiClass) {
|
|
||||||
formatPsiClass(element, false, inCode)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wrapOrSkip(formatClassDescriptor(classDescriptor), inCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean): String {
|
|
||||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
|
|
||||||
return if (element is PsiMethod) {
|
|
||||||
formatPsiMethod(element, false, inCode)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor) = DescriptorRenderer.COMPACT.render(functionDescriptor)
|
|
||||||
|
|
||||||
fun formatPsiMethod(
|
|
||||||
psiMethod: PsiMethod,
|
|
||||||
showContainingClass: Boolean,
|
|
||||||
inCode: Boolean
|
|
||||||
): String {
|
|
||||||
var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
|
|
||||||
if (showContainingClass) {
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
options = options or PsiFormatUtilBase.SHOW_CONTAINING_CLASS
|
|
||||||
}
|
|
||||||
|
|
||||||
var description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE)
|
|
||||||
description = wrapOrSkip(description, inCode)
|
|
||||||
|
|
||||||
return "[Java] $description"
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatJavaOrLightMethod(method: PsiMethod): String {
|
|
||||||
val originalDeclaration = method.unwrapped
|
|
||||||
return if (originalDeclaration is KtDeclaration) {
|
|
||||||
formatFunctionDescriptor(originalDeclaration.resolveToDescriptor())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
formatPsiMethod(method, false, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatClass(classOrObject: KtClassOrObject) = formatClassDescriptor(classOrObject.resolveToDescriptor() as ClassDescriptor)
|
|
||||||
|
|
||||||
fun checkParametersInMethodHierarchy(parameter: PsiParameter): Collection<PsiElement>? {
|
|
||||||
val method = parameter.declarationScope as PsiMethod
|
|
||||||
|
|
||||||
val parametersToDelete = collectParametersHierarchy(method, parameter)
|
|
||||||
if (parametersToDelete.size <= 1 || ApplicationManager.getApplication().isUnitTestMode) return parametersToDelete
|
|
||||||
|
|
||||||
val message = KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method))
|
|
||||||
val exitCode = Messages.showOkCancelDialog(parameter.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
|
|
||||||
return if (exitCode == Messages.OK) parametersToDelete else null
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: generalize breadth-first search
|
|
||||||
private fun collectParametersHierarchy(method: PsiMethod, parameter: PsiParameter): Set<PsiElement> {
|
|
||||||
val queue = ArrayDeque<PsiMethod>()
|
|
||||||
val visited = HashSet<PsiMethod>()
|
|
||||||
val parametersToDelete = HashSet<PsiElement>()
|
|
||||||
|
|
||||||
queue.add(method)
|
|
||||||
while (!queue.isEmpty()) {
|
|
||||||
val currentMethod = queue.poll()
|
|
||||||
|
|
||||||
visited += currentMethod
|
|
||||||
addParameter(currentMethod, parametersToDelete, parameter)
|
|
||||||
|
|
||||||
currentMethod.findSuperMethods(true)
|
|
||||||
.filter { it !in visited }
|
|
||||||
.forEach { queue.offer(it) }
|
|
||||||
OverridingMethodsSearch.search(currentMethod)
|
|
||||||
.filter { it !in visited }
|
|
||||||
.forEach { queue.offer(it) }
|
|
||||||
}
|
|
||||||
return parametersToDelete
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addParameter(method: PsiMethod, result: MutableSet<PsiElement>, parameter: PsiParameter) {
|
|
||||||
val parameterIndex = parameter.unwrapped!!.parameterIndex()
|
|
||||||
|
|
||||||
if (method is KtLightMethod) {
|
|
||||||
val declaration = method.kotlinOrigin
|
|
||||||
if (declaration is KtFunction) {
|
|
||||||
result.add(declaration.valueParameters[parameterIndex])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.add(method.parameterList.parameters[parameterIndex])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IntroduceRefactoringException::class)
|
|
||||||
fun selectElement(
|
|
||||||
editor: Editor,
|
|
||||||
file: KtFile,
|
|
||||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
|
||||||
callback: (PsiElement?) -> Unit
|
|
||||||
) = selectElement(editor, file, true, elementKinds, callback)
|
|
||||||
|
|
||||||
@Throws(IntroduceRefactoringException::class)
|
|
||||||
fun selectElement(editor: Editor,
|
|
||||||
file: KtFile,
|
|
||||||
failOnEmptySuggestion: Boolean,
|
|
||||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
|
||||||
callback: (PsiElement?) -> Unit) {
|
|
||||||
if (editor.selectionModel.hasSelection()) {
|
|
||||||
var selectionStart = editor.selectionModel.selectionStart
|
|
||||||
var selectionEnd = editor.selectionModel.selectionEnd
|
|
||||||
|
|
||||||
var firstElement: PsiElement = file.findElementAt(selectionStart)!!
|
|
||||||
var lastElement: PsiElement = file.findElementAt(selectionEnd - 1)!!
|
|
||||||
|
|
||||||
if (PsiTreeUtil.getParentOfType(firstElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null
|
|
||||||
&& PsiTreeUtil.getParentOfType(lastElement, KtLiteralStringTemplateEntry::class.java, KtEscapeStringTemplateEntry::class.java) == null) {
|
|
||||||
firstElement = firstElement.getNextSiblingIgnoringWhitespaceAndComments(true)!!
|
|
||||||
lastElement = lastElement.getPrevSiblingIgnoringWhitespaceAndComments(true)!!
|
|
||||||
selectionStart = firstElement.textRange.startOffset
|
|
||||||
selectionEnd = lastElement.textRange.endOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
val element = elementKinds.asSequence()
|
|
||||||
.mapNotNull { findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, it) }
|
|
||||||
.firstOrNull()
|
|
||||||
callback(element)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val offset = editor.caretModel.offset
|
|
||||||
smartSelectElement(editor, file, offset, failOnEmptySuggestion, elementKinds, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IntroduceRefactoringException::class)
|
|
||||||
fun getSmartSelectSuggestions(
|
|
||||||
file: PsiFile,
|
|
||||||
offset: Int,
|
|
||||||
elementKind: CodeInsightUtils.ElementKind
|
|
||||||
): List<KtElement> {
|
|
||||||
if (offset < 0) return emptyList()
|
|
||||||
|
|
||||||
var element: PsiElement? = file.findElementAt(offset) ?: return emptyList()
|
|
||||||
|
|
||||||
if (element is PsiWhiteSpace) return getSmartSelectSuggestions(file, offset - 1, elementKind)
|
|
||||||
|
|
||||||
val elements = ArrayList<KtElement>()
|
|
||||||
while (element != null && !(element is KtBlockExpression && element.parent !is KtFunctionLiteral) &&
|
|
||||||
element !is KtNamedFunction
|
|
||||||
&& element !is KtClassBody) {
|
|
||||||
var addElement = false
|
|
||||||
var keepPrevious = true
|
|
||||||
|
|
||||||
if (element is KtTypeElement) {
|
|
||||||
addElement = elementKind == CodeInsightUtils.ElementKind.TYPE_ELEMENT
|
|
||||||
if (!addElement) {
|
|
||||||
keepPrevious = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (element is KtExpression && element !is KtStatementExpression) {
|
|
||||||
addElement = elementKind == CodeInsightUtils.ElementKind.EXPRESSION
|
|
||||||
|
|
||||||
if (addElement) {
|
|
||||||
if (element is KtParenthesizedExpression) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
else if (KtPsiUtil.isLabelIdentifierExpression(element)) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
else if (element.parent is KtQualifiedExpression) {
|
|
||||||
val qualifiedExpression = element.parent as KtQualifiedExpression
|
|
||||||
if (qualifiedExpression.receiverExpression !== element) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (element.parent is KtCallElement
|
|
||||||
|| element.parent is KtThisExpression
|
|
||||||
|| PsiTreeUtil.getParentOfType(element, KtSuperExpression::class.java) != null) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
else if (element.parent is KtOperationExpression) {
|
|
||||||
val operationExpression = element.parent as KtOperationExpression
|
|
||||||
if (operationExpression.operationReference === element) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (addElement) {
|
|
||||||
val bindingContext = element.analyze(BodyResolveMode.FULL)
|
|
||||||
val expressionType = bindingContext.getType(element)
|
|
||||||
if (expressionType == null || KotlinBuiltIns.isUnit(expressionType)) {
|
|
||||||
addElement = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addElement) {
|
if (addElement) {
|
||||||
elements.add(element as KtElement)
|
if (element is KtParenthesizedExpression) {
|
||||||
}
|
addElement = false
|
||||||
|
}
|
||||||
if (!keepPrevious) {
|
else if (KtPsiUtil.isLabelIdentifierExpression(element)) {
|
||||||
elements.clear()
|
addElement = false
|
||||||
}
|
}
|
||||||
|
else if (element.parent is KtQualifiedExpression) {
|
||||||
element = element.parent
|
val qualifiedExpression = element.parent as KtQualifiedExpression
|
||||||
}
|
if (qualifiedExpression.receiverExpression !== element) {
|
||||||
return elements
|
addElement = false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Throws(IntroduceRefactoringException::class)
|
else if (element.parent is KtCallElement
|
||||||
private fun smartSelectElement(
|
|| element.parent is KtThisExpression
|
||||||
editor: Editor,
|
|| PsiTreeUtil.getParentOfType(element, KtSuperExpression::class.java) != null) {
|
||||||
file: PsiFile,
|
addElement = false
|
||||||
offset: Int,
|
}
|
||||||
failOnEmptySuggestion: Boolean,
|
else if (element.parent is KtOperationExpression) {
|
||||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
val operationExpression = element.parent as KtOperationExpression
|
||||||
callback: (PsiElement?) -> Unit
|
if (operationExpression.operationReference === element) {
|
||||||
) {
|
addElement = false
|
||||||
val elements = elementKinds.flatMap { getSmartSelectSuggestions(file, offset, it) }
|
}
|
||||||
if (elements.isEmpty()) {
|
}
|
||||||
if (failOnEmptySuggestion) throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
|
if (addElement) {
|
||||||
callback(null)
|
val bindingContext = element.analyze(BodyResolveMode.FULL)
|
||||||
return
|
val expressionType = bindingContext.getType(element)
|
||||||
}
|
if (expressionType == null || KotlinBuiltIns.isUnit(expressionType)) {
|
||||||
|
addElement = false
|
||||||
if (elements.size == 1 || ApplicationManager.getApplication().isUnitTestMode) {
|
}
|
||||||
callback(elements.first())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val model = DefaultListModel<PsiElement>()
|
|
||||||
elements.forEach { model.addElement(it) }
|
|
||||||
|
|
||||||
val highlighter = ScopeHighlighter(editor)
|
|
||||||
|
|
||||||
val list = JBList(model)
|
|
||||||
|
|
||||||
list.cellRenderer = object : DefaultListCellRenderer() {
|
|
||||||
override fun getListCellRendererComponent(list: JList<*>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
|
|
||||||
val rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
|
|
||||||
val element = value as KtElement?
|
|
||||||
if (element!!.isValid) {
|
|
||||||
text = getExpressionShortText(element)
|
|
||||||
}
|
}
|
||||||
return rendererComponent
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.addListSelectionListener {
|
if (addElement) {
|
||||||
highlighter.dropHighlight()
|
elements.add(element as KtElement)
|
||||||
val selectedIndex = list.selectedIndex
|
|
||||||
if (selectedIndex < 0) return@addListSelectionListener
|
|
||||||
val toExtract = ArrayList<PsiElement>()
|
|
||||||
toExtract.add(model.get(selectedIndex))
|
|
||||||
highlighter.highlight(model.get(selectedIndex), toExtract)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var title = "Elements"
|
if (!keepPrevious) {
|
||||||
if (elementKinds.size == 1) {
|
elements.clear()
|
||||||
when (elementKinds.iterator().next()) {
|
|
||||||
CodeInsightUtils.ElementKind.EXPRESSION -> title = "Expressions"
|
|
||||||
CodeInsightUtils.ElementKind.TYPE_ELEMENT, CodeInsightUtils.ElementKind.TYPE_CONSTRUCTOR -> title = "Types"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JBPopupFactory.getInstance()
|
element = element.parent
|
||||||
.createListPopupBuilder(list)
|
|
||||||
.setTitle(title)
|
|
||||||
.setMovable(false)
|
|
||||||
.setResizable(false)
|
|
||||||
.setRequestFocus(true)
|
|
||||||
.setItemChoosenCallback { callback(list.selectedValue as KtElement) }
|
|
||||||
.addListener(
|
|
||||||
object : JBPopupAdapter() {
|
|
||||||
override fun onClosed(event: LightweightWindowEvent?) {
|
|
||||||
highlighter.dropHighlight()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.createPopup()
|
|
||||||
.showInBestPositionFor(editor)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return elements
|
||||||
fun getExpressionShortText(element: KtElement): String {
|
|
||||||
val text = element.renderTrimmed()
|
|
||||||
val firstNewLinePos = text.indexOf('\n')
|
|
||||||
var trimmedText = text.substring(0, if (firstNewLinePos != -1) firstNewLinePos else Math.min(100, text.length))
|
|
||||||
if (trimmedText.length != text.length) trimmedText += " ..."
|
|
||||||
return trimmedText
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IntroduceRefactoringException::class)
|
|
||||||
private fun findElement(
|
|
||||||
file: KtFile,
|
|
||||||
startOffset: Int,
|
|
||||||
endOffset: Int,
|
|
||||||
failOnNoExpression: Boolean,
|
|
||||||
elementKind: CodeInsightUtils.ElementKind
|
|
||||||
): PsiElement? {
|
|
||||||
var element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind)
|
|
||||||
if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) {
|
|
||||||
element = findExpressionOrStringFragment(file, startOffset, endOffset)
|
|
||||||
}
|
|
||||||
if (element == null) {
|
|
||||||
//todo: if it's infix expression => add (), then commit document then return new created expression
|
|
||||||
|
|
||||||
if (failOnNoExpression) {
|
|
||||||
throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
class IntroduceRefactoringException(message: String) : RuntimeException(message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(IntroduceRefactoringException::class)
|
||||||
|
private fun smartSelectElement(
|
||||||
|
editor: Editor,
|
||||||
|
file: PsiFile,
|
||||||
|
offset: Int,
|
||||||
|
failOnEmptySuggestion: Boolean,
|
||||||
|
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||||
|
callback: (PsiElement?) -> Unit
|
||||||
|
) {
|
||||||
|
val elements = elementKinds.flatMap { getSmartSelectSuggestions(file, offset, it) }
|
||||||
|
if (elements.isEmpty()) {
|
||||||
|
if (failOnEmptySuggestion) throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
|
||||||
|
callback(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elements.size == 1 || ApplicationManager.getApplication().isUnitTestMode) {
|
||||||
|
callback(elements.first())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val model = DefaultListModel<PsiElement>()
|
||||||
|
elements.forEach { model.addElement(it) }
|
||||||
|
|
||||||
|
val highlighter = ScopeHighlighter(editor)
|
||||||
|
|
||||||
|
val list = JBList(model)
|
||||||
|
|
||||||
|
list.cellRenderer = object : DefaultListCellRenderer() {
|
||||||
|
override fun getListCellRendererComponent(list: JList<*>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
|
||||||
|
val rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
|
||||||
|
val element = value as KtElement?
|
||||||
|
if (element!!.isValid) {
|
||||||
|
text = getExpressionShortText(element)
|
||||||
|
}
|
||||||
|
return rendererComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.addListSelectionListener {
|
||||||
|
highlighter.dropHighlight()
|
||||||
|
val selectedIndex = list.selectedIndex
|
||||||
|
if (selectedIndex < 0) return@addListSelectionListener
|
||||||
|
val toExtract = ArrayList<PsiElement>()
|
||||||
|
toExtract.add(model.get(selectedIndex))
|
||||||
|
highlighter.highlight(model.get(selectedIndex), toExtract)
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = "Elements"
|
||||||
|
if (elementKinds.size == 1) {
|
||||||
|
when (elementKinds.iterator().next()) {
|
||||||
|
CodeInsightUtils.ElementKind.EXPRESSION -> title = "Expressions"
|
||||||
|
CodeInsightUtils.ElementKind.TYPE_ELEMENT, CodeInsightUtils.ElementKind.TYPE_CONSTRUCTOR -> title = "Types"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JBPopupFactory.getInstance()
|
||||||
|
.createListPopupBuilder(list)
|
||||||
|
.setTitle(title)
|
||||||
|
.setMovable(false)
|
||||||
|
.setResizable(false)
|
||||||
|
.setRequestFocus(true)
|
||||||
|
.setItemChoosenCallback { callback(list.selectedValue as KtElement) }
|
||||||
|
.addListener(
|
||||||
|
object : JBPopupAdapter() {
|
||||||
|
override fun onClosed(event: LightweightWindowEvent?) {
|
||||||
|
highlighter.dropHighlight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.createPopup()
|
||||||
|
.showInBestPositionFor(editor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getExpressionShortText(element: KtElement): String {
|
||||||
|
val text = element.renderTrimmed()
|
||||||
|
val firstNewLinePos = text.indexOf('\n')
|
||||||
|
var trimmedText = text.substring(0, if (firstNewLinePos != -1) firstNewLinePos else Math.min(100, text.length))
|
||||||
|
if (trimmedText.length != text.length) trimmedText += " ..."
|
||||||
|
return trimmedText
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IntroduceRefactoringException::class)
|
||||||
|
private fun findElement(
|
||||||
|
file: KtFile,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
failOnNoExpression: Boolean,
|
||||||
|
elementKind: CodeInsightUtils.ElementKind
|
||||||
|
): PsiElement? {
|
||||||
|
var element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind)
|
||||||
|
if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) {
|
||||||
|
element = findExpressionOrStringFragment(file, startOffset, endOffset)
|
||||||
|
}
|
||||||
|
if (element == null) {
|
||||||
|
//todo: if it's infix expression => add (), then commit document then return new created expression
|
||||||
|
|
||||||
|
if (failOnNoExpression) {
|
||||||
|
throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
class IntroduceRefactoringException(message: String) : RuntimeException(message)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import com.intellij.psi.util.PsiTreeUtil
|
|||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
|
import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringBundle
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringBundle
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2
|
import org.jetbrains.kotlin.idea.refactoring.selectElement
|
||||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
@@ -122,7 +122,7 @@ fun selectElementsWithTargetParent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun selectSingleElement() {
|
fun selectSingleElement() {
|
||||||
KotlinRefactoringUtil2.selectElement(editor, file, false, elementKinds) { expr ->
|
selectElement(editor, file, false, elementKinds) { expr ->
|
||||||
if (expr != null) {
|
if (expr != null) {
|
||||||
selectTargetContainer(listOf(expr))
|
selectTargetContainer(listOf(expr))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -719,11 +719,11 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
|
|||||||
if (file !is KtFile) return
|
if (file !is KtFile) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KotlinRefactoringUtil2.selectElement(editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) {
|
selectElement(editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) {
|
||||||
doRefactoring(project, editor, it as KtExpression?, null, null)
|
doRefactoring(project, editor, it as KtExpression?, null, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e: KotlinRefactoringUtil2.IntroduceRefactoringException) {
|
catch (e: IntroduceRefactoringException) {
|
||||||
showErrorHint(project, editor, e.message!!)
|
showErrorHint(project, editor, e.message!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -37,7 +37,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction;
|
import org.jetbrains.kotlin.psi.KtNamedFunction;
|
||||||
@@ -110,7 +110,7 @@ class KotlinOverridingDialog extends DialogWrapper {
|
|||||||
|
|
||||||
assert element instanceof PsiMethod
|
assert element instanceof PsiMethod
|
||||||
: "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found";
|
: "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found";
|
||||||
return KotlinRefactoringUtil2.INSTANCE.formatPsiMethod((PsiMethod) element, true, false);
|
return KotlinRefactoringUtil2Kt.formatPsiMethod((PsiMethod) element, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+11
-8
@@ -39,7 +39,10 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent
|
import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2
|
import org.jetbrains.kotlin.idea.refactoring.checkParametersInMethodHierarchy
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.formatClass
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.formatFunction
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
|
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -260,10 +263,10 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
|||||||
.mapTo(ArrayList<String>()) { overridenDescriptor ->
|
.mapTo(ArrayList<String>()) { overridenDescriptor ->
|
||||||
KotlinBundle.message(
|
KotlinBundle.message(
|
||||||
"x.implements.y",
|
"x.implements.y",
|
||||||
KotlinRefactoringUtil2.formatFunction(declarationDescriptor, true),
|
formatFunction(declarationDescriptor, true),
|
||||||
KotlinRefactoringUtil2.formatClass(declarationDescriptor.containingDeclaration, true),
|
formatClass(declarationDescriptor.containingDeclaration, true),
|
||||||
KotlinRefactoringUtil2.formatFunction(overridenDescriptor, true),
|
formatFunction(overridenDescriptor, true),
|
||||||
KotlinRefactoringUtil2.formatClass(overridenDescriptor.containingDeclaration, true)
|
formatClass(overridenDescriptor.containingDeclaration, true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,18 +335,18 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
|||||||
when (element) {
|
when (element) {
|
||||||
is KtParameter ->
|
is KtParameter ->
|
||||||
return element.toPsiParameters().flatMap { psiParameter ->
|
return element.toPsiParameters().flatMap { psiParameter ->
|
||||||
KotlinRefactoringUtil2.checkParametersInMethodHierarchy(psiParameter) ?: emptyList()
|
checkParametersInMethodHierarchy(psiParameter) ?: emptyList()
|
||||||
}.ifEmpty { listOf(element) }
|
}.ifEmpty { listOf(element) }
|
||||||
|
|
||||||
is PsiParameter ->
|
is PsiParameter ->
|
||||||
return KotlinRefactoringUtil2.checkParametersInMethodHierarchy(element)
|
return checkParametersInMethodHierarchy(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ApplicationManager.getApplication()!!.isUnitTestMode) return Collections.singletonList(element)
|
if (ApplicationManager.getApplication()!!.isUnitTestMode) return Collections.singletonList(element)
|
||||||
|
|
||||||
return when (element) {
|
return when (element) {
|
||||||
is KtNamedFunction, is KtProperty ->
|
is KtNamedFunction, is KtProperty ->
|
||||||
KotlinRefactoringUtil2.checkSuperMethods(
|
checkSuperMethods(
|
||||||
element as KtDeclaration, allElementsToDelete, "super.methods.delete.with.usage.search"
|
element as KtDeclaration, allElementsToDelete, "super.methods.delete.with.usage.search"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ import kotlin.Unit;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.IntroduceRefactoringException;
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ public abstract class AbstractExpressionSelectionTest extends LightCodeInsightTe
|
|||||||
final String expectedExpression = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
final String expectedExpression = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KotlinRefactoringUtil2.INSTANCE.selectElement(
|
KotlinRefactoringUtil2Kt.selectElement(
|
||||||
getEditor(),
|
getEditor(),
|
||||||
(KtFile) getFile(),
|
(KtFile) getFile(),
|
||||||
Collections.singletonList(CodeInsightUtils.ElementKind.EXPRESSION),
|
Collections.singletonList(CodeInsightUtils.ElementKind.EXPRESSION),
|
||||||
@@ -49,7 +50,7 @@ public abstract class AbstractExpressionSelectionTest extends LightCodeInsightTe
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (KotlinRefactoringUtil2.IntroduceRefactoringException e) {
|
catch (IntroduceRefactoringException e) {
|
||||||
assertEquals(expectedExpression, "");
|
assertEquals(expectedExpression, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
|||||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2;
|
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2Kt;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
@@ -34,12 +34,12 @@ public abstract class AbstractSmartSelectionTest extends LightCodeInsightTestCas
|
|||||||
configureByFile(path);
|
configureByFile(path);
|
||||||
String expectedResultText = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
String expectedResultText = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
||||||
|
|
||||||
List<KtElement> elements = KotlinRefactoringUtil2.INSTANCE.getSmartSelectSuggestions(
|
List<KtElement> elements = KotlinRefactoringUtil2Kt.getSmartSelectSuggestions(
|
||||||
getFile(), getEditor().getCaretModel().getOffset(), CodeInsightUtils.ElementKind.EXPRESSION);
|
getFile(), getEditor().getCaretModel().getOffset(), CodeInsightUtils.ElementKind.EXPRESSION);
|
||||||
|
|
||||||
List<String> textualExpressions = new ArrayList<String>();
|
List<String> textualExpressions = new ArrayList<String>();
|
||||||
for (KtElement element : elements) {
|
for (KtElement element : elements) {
|
||||||
textualExpressions.add(KotlinRefactoringUtil2.INSTANCE.getExpressionShortText(element));
|
textualExpressions.add(KotlinRefactoringUtil2Kt.getExpressionShortText(element));
|
||||||
}
|
}
|
||||||
assertEquals(expectedResultText, StringUtil.join(textualExpressions, "\n"));
|
assertEquals(expectedResultText, StringUtil.join(textualExpressions, "\n"));
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -37,7 +37,6 @@ import com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager
|
|||||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.EXTRACT_FUNCTION
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.EXTRACT_FUNCTION
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||||
@@ -47,6 +46,7 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.introduceProperty.KotlinI
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.KotlinIntroduceTypeAliasHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeAlias.KotlinIntroduceTypeAliasHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeParameter.KotlinIntroduceTypeParameterHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceTypeParameter.KotlinIntroduceTypeParameterHandler
|
||||||
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.selectElement
|
||||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
@@ -115,7 +115,7 @@ abstract class AbstractExtractionTest() : KotlinLightCodeInsightFixtureTestCase(
|
|||||||
with (handler) {
|
with (handler) {
|
||||||
val target = (file as KtFile).findElementByCommentPrefix("// TARGET:") as? KtNamedDeclaration
|
val target = (file as KtFile).findElementByCommentPrefix("// TARGET:") as? KtNamedDeclaration
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
KotlinRefactoringUtil2.selectElement(fixture.getEditor(), file, true, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) { element ->
|
selectElement(fixture.getEditor(), file, true, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) { element ->
|
||||||
invoke(fixture.getProject(), fixture.getEditor(), element as KtExpression, target)
|
invoke(fixture.getProject(), fixture.getEditor(), element as KtExpression, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -21,7 +21,8 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil2
|
import org.jetbrains.kotlin.idea.refactoring.IntroduceRefactoringException
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.selectElement
|
||||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
@@ -90,7 +91,7 @@ class KotlinNameSuggesterTest : LightCodeInsightFixtureTestCase() {
|
|||||||
if (withRuntime) {
|
if (withRuntime) {
|
||||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())
|
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())
|
||||||
}
|
}
|
||||||
KotlinRefactoringUtil2.selectElement(myFixture.editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) {
|
selectElement(myFixture.editor, file, listOf(CodeInsightUtils.ElementKind.EXPRESSION)) {
|
||||||
val names = KotlinNameSuggester
|
val names = KotlinNameSuggester
|
||||||
.suggestNamesByExpressionAndType(it as KtExpression,
|
.suggestNamesByExpressionAndType(it as KtExpression,
|
||||||
null,
|
null,
|
||||||
@@ -102,7 +103,7 @@ class KotlinNameSuggesterTest : LightCodeInsightFixtureTestCase() {
|
|||||||
assertEquals(expectedResultText, result)
|
assertEquals(expectedResultText, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e: KotlinRefactoringUtil2.IntroduceRefactoringException) {
|
catch (e: IntroduceRefactoringException) {
|
||||||
throw AssertionError("Failed to find expression: " + e.message)
|
throw AssertionError("Failed to find expression: " + e.message)
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user