Convert to Kotlin: KotlinRefactoringUtil2 (prettify)

This commit is contained in:
Alexey Sedunov
2016-08-31 14:35:23 +03:00
parent fc9b28884d
commit 16b4c2c70d
@@ -24,14 +24,12 @@ import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.popup.JBPopupAdapter import com.intellij.openapi.ui.popup.JBPopupAdapter
import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.ui.popup.LightweightWindowEvent import com.intellij.openapi.ui.popup.LightweightWindowEvent
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.psi.search.searches.OverridingMethodsSearch import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.psi.util.PsiFormatUtil import com.intellij.psi.util.PsiFormatUtil
import com.intellij.psi.util.PsiFormatUtilBase import com.intellij.psi.util.PsiFormatUtilBase
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.ui.components.JBList import com.intellij.ui.components.JBList
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -41,16 +39,17 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
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.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.refactoring.introduce.findExpressionOrStringFragment import org.jetbrains.kotlin.idea.refactoring.introduce.findExpressionOrStringFragment
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -60,51 +59,44 @@ import java.util.*
import javax.swing.DefaultListCellRenderer import javax.swing.DefaultListCellRenderer
import javax.swing.DefaultListModel import javax.swing.DefaultListModel
import javax.swing.JList import javax.swing.JList
import javax.swing.event.ListSelectionListener
object KotlinRefactoringUtil2 { object KotlinRefactoringUtil2 {
fun wrapOrSkip(s: String, inCode: Boolean) = if (inCode) "<code>$s</code>" else s
fun wrapOrSkip(s: String, inCode: Boolean): String { fun formatClassDescriptor(classDescriptor: DeclarationDescriptor) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor)
return if (inCode) "<code>$s</code>" else s
}
fun formatClassDescriptor(classDescriptor: DeclarationDescriptor): String {
return IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(classDescriptor)
}
fun formatPsiClass( fun formatPsiClass(
psiClass: PsiClass, psiClass: PsiClass,
markAsJava: Boolean, markAsJava: Boolean,
inCode: Boolean): String { inCode: Boolean
): 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( fun checkSuperMethods(
declaration: KtDeclaration, declaration: KtDeclaration,
ignore: Collection<PsiElement>?, ignore: Collection<PsiElement>?,
actionStringKey: String): List<PsiElement> { actionStringKey: String
val bindingContext = declaration.analyze(BodyResolveMode.FULL) ): List<PsiElement> {
val declarationDescriptor = declaration.resolveToDescriptor() as CallableDescriptor
val declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) as CallableDescriptor? if (declarationDescriptor is LocalVariableDescriptor) return listOf(declaration)
if (declarationDescriptor == null || declarationDescriptor is LocalVariableDescriptor) {
return listOf(declaration)
}
val project = declaration.project val project = declaration.project
val overriddenElementsToDescriptor = HashMap<PsiElement, CallableDescriptor>() val overriddenElementsToDescriptor = HashMap<PsiElement, CallableDescriptor>()
for (overriddenDescriptor in DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) { for (overriddenDescriptor in DescriptorUtils.getAllOverriddenDescriptors(declarationDescriptor)) {
val overriddenDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, overriddenDescriptor) ?: continue val overriddenDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, overriddenDescriptor) ?: continue
if (PsiTreeUtil.instanceOf(overriddenDeclaration, KtNamedFunction::class.java, KtProperty::class.java, PsiMethod::class.java)) { if (overriddenDeclaration is KtNamedFunction || overriddenDeclaration is KtProperty || overriddenDeclaration is PsiMethod) {
overriddenElementsToDescriptor.put(overriddenDeclaration, overriddenDescriptor) overriddenElementsToDescriptor[overriddenDeclaration] = overriddenDescriptor
} }
} }
if (ignore != null) { if (ignore != null) {
@@ -113,30 +105,29 @@ object KotlinRefactoringUtil2 {
if (overriddenElementsToDescriptor.isEmpty()) return listOf(declaration) if (overriddenElementsToDescriptor.isEmpty()) return listOf(declaration)
val superClasses = getClassDescriptions(overriddenElementsToDescriptor) return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, actionStringKey)
return askUserForMethodsToSearch(declaration, declarationDescriptor, overriddenElementsToDescriptor, superClasses, actionStringKey)
} }
private fun askUserForMethodsToSearch( private fun askUserForMethodsToSearch(
declaration: KtDeclaration, declaration: KtDeclaration,
declarationDescriptor: CallableDescriptor, declarationDescriptor: CallableDescriptor,
overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>, overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>,
superClasses: List<String>, actionStringKey: String
actionStringKey: String): List<PsiElement> { ): List<PsiElement> {
if (ApplicationManager.getApplication().isUnitTestMode) { if (ApplicationManager.getApplication().isUnitTestMode) return overriddenElementsToDescriptor.keys.toList()
return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keys)
} val superClassDescriptions = getClassDescriptions(overriddenElementsToDescriptor)
val superClassesStr = "\n" + StringUtil.join(superClasses, "")
val message = KotlinBundle.message( val message = KotlinBundle.message(
"x.overrides.y.in.class.list", "x.overrides.y.in.class.list",
DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declarationDescriptor), DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declarationDescriptor),
superClassesStr, "\n${superClassDescriptions.joinToString(separator = "")}",
KotlinBundle.message(actionStringKey)) KotlinBundle.message(actionStringKey)
)
val exitCode = Messages.showYesNoCancelDialog(declaration.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon()) val exitCode = Messages.showYesNoCancelDialog(declaration.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
when (exitCode) { when (exitCode) {
Messages.YES -> return ContainerUtil.newArrayList(overriddenElementsToDescriptor.keys) Messages.YES -> return overriddenElementsToDescriptor.keys.toList()
Messages.NO -> return listOf(declaration) Messages.NO -> return listOf(declaration)
else -> return emptyList() else -> return emptyList()
} }
@@ -144,51 +135,46 @@ object KotlinRefactoringUtil2 {
private fun getClassDescriptions(overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>): List<String> { private fun getClassDescriptions(overriddenElementsToDescriptor: Map<PsiElement, CallableDescriptor>): List<String> {
return overriddenElementsToDescriptor.entries.map { entry -> return overriddenElementsToDescriptor.entries.map { entry ->
val description: String val (element, descriptor) = entry
val description = when (element) {
val element = entry.key is KtNamedFunction, is KtProperty -> formatClassDescriptor(descriptor.containingDeclaration)
val descriptor = entry.value is PsiMethod -> {
if (element is KtNamedFunction || element is KtProperty) { val psiClass = element.containingClass ?: error("Invalid element: ${element.getText()}")
description = formatClassDescriptor(descriptor.getContainingDeclaration()) formatPsiClass(psiClass, true, false)
}
else -> error("Unexpected element: ${element.getElementTextWithContext()}")
} }
else { " $description\n"
assert(element is PsiMethod) { "Invalid element: " + element.getText() }
val psiClass = (element as PsiMethod).containingClass ?: error("Invalid element: " + element.getText())
description = formatPsiClass(psiClass, true, false)
}
" " + description + "\n"
} }
} }
fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String { fun formatClass(classDescriptor: DeclarationDescriptor, inCode: Boolean): String {
val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) val element = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor)
if (element is PsiClass) { return if (element is PsiClass) {
return formatPsiClass((element as PsiClass?)!!, false, inCode) formatPsiClass(element, false, inCode)
}
else {
wrapOrSkip(formatClassDescriptor(classDescriptor), inCode)
} }
return wrapOrSkip(formatClassDescriptor(classDescriptor), inCode)
} }
fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean): String { fun formatFunction(functionDescriptor: DeclarationDescriptor, inCode: Boolean): String {
val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) val element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)
if (element is PsiMethod) { return if (element is PsiMethod) {
return formatPsiMethod((element as PsiMethod?)!!, false, inCode) formatPsiMethod(element, false, inCode)
}
else {
wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode)
} }
return wrapOrSkip(formatFunctionDescriptor(functionDescriptor), inCode)
} }
private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor): String { private fun formatFunctionDescriptor(functionDescriptor: DeclarationDescriptor) = DescriptorRenderer.COMPACT.render(functionDescriptor)
return DescriptorRenderer.COMPACT.render(functionDescriptor)
}
fun formatPsiMethod( fun formatPsiMethod(
psiMethod: PsiMethod, psiMethod: PsiMethod,
showContainingClass: Boolean, showContainingClass: Boolean,
inCode: Boolean): String { inCode: Boolean
): String {
var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE var options = PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or PsiFormatUtilBase.SHOW_TYPE
if (showContainingClass) { if (showContainingClass) {
//noinspection ConstantConditions //noinspection ConstantConditions
@@ -198,49 +184,30 @@ object KotlinRefactoringUtil2 {
var description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE) var description = PsiFormatUtil.formatMethod(psiMethod, PsiSubstitutor.EMPTY, options, PsiFormatUtilBase.SHOW_TYPE)
description = wrapOrSkip(description, inCode) description = wrapOrSkip(description, inCode)
return "[Java] " + description return "[Java] $description"
} }
fun formatJavaOrLightMethod(method: PsiMethod): String { fun formatJavaOrLightMethod(method: PsiMethod): String {
val originalDeclaration = method.unwrapped val originalDeclaration = method.unwrapped
if (originalDeclaration is KtDeclaration) { return if (originalDeclaration is KtDeclaration) {
val bindingContext = originalDeclaration.analyze(BodyResolveMode.FULL) formatFunctionDescriptor(originalDeclaration.resolveToDescriptor())
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, originalDeclaration) }
else {
if (descriptor != null) return formatFunctionDescriptor(descriptor) formatPsiMethod(method, false, false)
} }
return formatPsiMethod(method, false, false)
} }
fun formatClass(classOrObject: KtClassOrObject): String { fun formatClass(classOrObject: KtClassOrObject) = formatClassDescriptor(classOrObject.resolveToDescriptor() as ClassDescriptor)
val bindingContext = classOrObject.analyze(BodyResolveMode.FULL)
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject)
if (descriptor is ClassDescriptor) return formatClassDescriptor(descriptor)
return "class " + classOrObject.name!!
}
fun checkParametersInMethodHierarchy(parameter: PsiParameter): Collection<PsiElement>? { fun checkParametersInMethodHierarchy(parameter: PsiParameter): Collection<PsiElement>? {
val method = parameter.declarationScope as PsiMethod val method = parameter.declarationScope as PsiMethod
val parametersToDelete = collectParametersHierarchy(method, parameter) val parametersToDelete = collectParametersHierarchy(method, parameter)
if (parametersToDelete.size > 1) { if (parametersToDelete.size <= 1 || ApplicationManager.getApplication().isUnitTestMode) return parametersToDelete
if (ApplicationManager.getApplication().isUnitTestMode) {
return parametersToDelete
}
val message = KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method)) val message = KotlinBundle.message("delete.param.in.method.hierarchy", formatJavaOrLightMethod(method))
val exitCode = Messages.showOkCancelDialog( val exitCode = Messages.showOkCancelDialog(parameter.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon())
parameter.project, message, IdeBundle.message("title.warning"), Messages.getQuestionIcon()) return if (exitCode == Messages.OK) parametersToDelete else null
if (exitCode == Messages.OK) {
return parametersToDelete
}
else {
return null
}
}
return parametersToDelete
} }
// TODO: generalize breadth-first search // TODO: generalize breadth-first search
@@ -253,19 +220,15 @@ object KotlinRefactoringUtil2 {
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
val currentMethod = queue.poll() val currentMethod = queue.poll()
visited.add(currentMethod) visited += currentMethod
addParameter(currentMethod, parametersToDelete, parameter) addParameter(currentMethod, parametersToDelete, parameter)
for (superMethod in currentMethod.findSuperMethods(true)) { currentMethod.findSuperMethods(true)
if (!visited.contains(superMethod)) { .filter { it !in visited }
queue.offer(superMethod) .forEach { queue.offer(it) }
} OverridingMethodsSearch.search(currentMethod)
} .filter { it !in visited }
for (overrider in OverridingMethodsSearch.search(currentMethod)) { .forEach { queue.offer(it) }
if (!visited.contains(overrider)) {
queue.offer(overrider)
}
}
} }
return parametersToDelete return parametersToDelete
} }
@@ -289,9 +252,8 @@ object KotlinRefactoringUtil2 {
editor: Editor, editor: Editor,
file: KtFile, file: KtFile,
elementKinds: Collection<CodeInsightUtils.ElementKind>, elementKinds: Collection<CodeInsightUtils.ElementKind>,
callback: (PsiElement?) -> Unit) { callback: (PsiElement?) -> Unit
selectElement(editor, file, true, elementKinds, callback) ) = selectElement(editor, file, true, elementKinds, callback)
}
@Throws(IntroduceRefactoringException::class) @Throws(IntroduceRefactoringException::class)
fun selectElement(editor: Editor, fun selectElement(editor: Editor,
@@ -306,22 +268,18 @@ object KotlinRefactoringUtil2 {
var firstElement: PsiElement = file.findElementAt(selectionStart)!! var firstElement: PsiElement = file.findElementAt(selectionStart)!!
var lastElement: PsiElement = file.findElementAt(selectionEnd - 1)!! 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) { 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)!! firstElement = firstElement.getNextSiblingIgnoringWhitespaceAndComments(true)!!
lastElement = lastElement.getPrevSiblingIgnoringWhitespaceAndComments(true)!! lastElement = lastElement.getPrevSiblingIgnoringWhitespaceAndComments(true)!!
selectionStart = firstElement.textRange.startOffset selectionStart = firstElement.textRange.startOffset
selectionEnd = lastElement.textRange.endOffset selectionEnd = lastElement.textRange.endOffset
} }
for (elementKind in elementKinds) { val element = elementKinds.asSequence()
val element = findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, elementKind) .mapNotNull { findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, it) }
if (element != null) { .firstOrNull()
callback(element) callback(element)
return
}
}
callback(null)
} }
else { else {
val offset = editor.caretModel.offset val offset = editor.caretModel.offset
@@ -333,15 +291,13 @@ object KotlinRefactoringUtil2 {
fun getSmartSelectSuggestions( fun getSmartSelectSuggestions(
file: PsiFile, file: PsiFile,
offset: Int, offset: Int,
elementKind: CodeInsightUtils.ElementKind): List<KtElement> { elementKind: CodeInsightUtils.ElementKind
if (offset < 0) { ): List<KtElement> {
return ArrayList() if (offset < 0) return emptyList()
}
var element: PsiElement? = file.findElementAt(offset) ?: return ArrayList() var element: PsiElement? = file.findElementAt(offset) ?: return emptyList()
if (element is PsiWhiteSpace) {
return getSmartSelectSuggestions(file, offset - 1, elementKind) if (element is PsiWhiteSpace) return getSmartSelectSuggestions(file, offset - 1, elementKind)
}
val elements = ArrayList<KtElement>() val elements = ArrayList<KtElement>()
while (element != null && !(element is KtBlockExpression && element.parent !is KtFunctionLiteral) && while (element != null && !(element is KtBlockExpression && element.parent !is KtFunctionLiteral) &&
@@ -413,31 +369,28 @@ object KotlinRefactoringUtil2 {
offset: Int, offset: Int,
failOnEmptySuggestion: Boolean, failOnEmptySuggestion: Boolean,
elementKinds: Collection<CodeInsightUtils.ElementKind>, elementKinds: Collection<CodeInsightUtils.ElementKind>,
callback: (PsiElement?) -> Unit) { callback: (PsiElement?) -> Unit
val elements = elementKinds.flatMap { kind -> getSmartSelectSuggestions(file, offset, kind) } ) {
if (elements.size == 0) { val elements = elementKinds.flatMap { getSmartSelectSuggestions(file, offset, it) }
if (failOnEmptySuggestion) if (elements.isEmpty()) {
throw IntroduceRefactoringException( if (failOnEmptySuggestion) throw IntroduceRefactoringException(KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
KotlinRefactoringBundle.message("cannot.refactor.not.expression"))
callback(null) callback(null)
return return
} }
if (elements.size == 1 || ApplicationManager.getApplication().isUnitTestMode) { if (elements.size == 1 || ApplicationManager.getApplication().isUnitTestMode) {
callback(elements[0]) callback(elements.first())
return return
} }
val model = DefaultListModel<PsiElement>() val model = DefaultListModel<PsiElement>()
for (element in elements) { elements.forEach { model.addElement(it) }
model.addElement(element)
}
val highlighter = ScopeHighlighter(editor) val highlighter = ScopeHighlighter(editor)
val list = JBList(model) val list = JBList(model)
list.setCellRenderer(object : DefaultListCellRenderer() { list.cellRenderer = object : DefaultListCellRenderer() {
override fun getListCellRendererComponent(list: JList<*>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component { override fun getListCellRendererComponent(list: JList<*>, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
val rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus) val rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
val element = value as KtElement? val element = value as KtElement?
@@ -446,16 +399,16 @@ object KotlinRefactoringUtil2 {
} }
return rendererComponent return rendererComponent
} }
}) }
list.addListSelectionListener(ListSelectionListener { list.addListSelectionListener {
highlighter.dropHighlight() highlighter.dropHighlight()
val selectedIndex = list.getSelectedIndex() val selectedIndex = list.selectedIndex
if (selectedIndex < 0) return@ListSelectionListener if (selectedIndex < 0) return@addListSelectionListener
val toExtract = ArrayList<PsiElement>() val toExtract = ArrayList<PsiElement>()
toExtract.add(model.get(selectedIndex)) toExtract.add(model.get(selectedIndex))
highlighter.highlight(model.get(selectedIndex), toExtract) highlighter.highlight(model.get(selectedIndex), toExtract)
}) }
var title = "Elements" var title = "Elements"
if (elementKinds.size == 1) { if (elementKinds.size == 1) {
@@ -465,11 +418,22 @@ object KotlinRefactoringUtil2 {
} }
} }
JBPopupFactory.getInstance().createListPopupBuilder(list).setTitle(title).setMovable(false).setResizable(false).setRequestFocus(true).setItemChoosenCallback { callback(list.getSelectedValue() as KtElement) }.addListener(object : JBPopupAdapter() { JBPopupFactory.getInstance()
override fun onClosed(event: LightweightWindowEvent?) { .createListPopupBuilder(list)
highlighter.dropHighlight() .setTitle(title)
} .setMovable(false)
}).createPopup().showInBestPositionFor(editor) .setResizable(false)
.setRequestFocus(true)
.setItemChoosenCallback { callback(list.selectedValue as KtElement) }
.addListener(
object : JBPopupAdapter() {
override fun onClosed(event: LightweightWindowEvent?) {
highlighter.dropHighlight()
}
}
)
.createPopup()
.showInBestPositionFor(editor)
} }
@@ -487,7 +451,8 @@ object KotlinRefactoringUtil2 {
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
failOnNoExpression: Boolean, failOnNoExpression: Boolean,
elementKind: CodeInsightUtils.ElementKind): PsiElement? { elementKind: CodeInsightUtils.ElementKind
): PsiElement? {
var element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind) var element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind)
if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) { if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) {
element = findExpressionOrStringFragment(file, startOffset, endOffset) element = findExpressionOrStringFragment(file, startOffset, endOffset)
@@ -503,8 +468,5 @@ object KotlinRefactoringUtil2 {
return element return element
} }
class IntroduceRefactoringException(private val myMessage: String) : RuntimeException() { class IntroduceRefactoringException(message: String) : RuntimeException(message)
override val message: String?
get() = myMessage
}
} }