Move: Implement Kotlin-specific editor for class name
#KT-13192 Fixed
This commit is contained in:
@@ -142,7 +142,7 @@ abstract class CompletionSession(
|
||||
|
||||
// LookupElementsCollector instantiation is deferred because virtual call to createSorter uses data from derived classes
|
||||
protected val collector: LookupElementsCollector by lazy(LazyThreadSafetyMode.NONE) {
|
||||
LookupElementsCollector(prefixMatcher, parameters, resultSet, createSorter())
|
||||
LookupElementsCollector(prefixMatcher, parameters, resultSet, createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter)
|
||||
}
|
||||
|
||||
protected val searchScope: GlobalSearchScope = getResolveScope(parameters.originalFile as KtFile)
|
||||
|
||||
@@ -418,4 +418,6 @@ fun OffsetMap.tryGetOffset(key: OffsetKey): Int? {
|
||||
catch(e: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var KtCodeFragment.extraCompletionFilter: ((LookupElement) -> Boolean)? by CopyableUserDataProperty(Key.create("EXTRA_COMPLETION_FILTER"))
|
||||
@@ -159,6 +159,7 @@ object KeywordCompletion {
|
||||
CommentFilter(),
|
||||
ParentFilter(ClassFilter(KtLiteralStringTemplateEntry::class.java)),
|
||||
ParentFilter(ClassFilter(KtConstantExpression::class.java)),
|
||||
FileFilter(ClassFilter(KtTypeCodeFragment::class.java)),
|
||||
LeftNeighbour(TextFilter(".")),
|
||||
LeftNeighbour(TextFilter("?."))
|
||||
))
|
||||
@@ -182,6 +183,17 @@ object KeywordCompletion {
|
||||
}
|
||||
}
|
||||
|
||||
private class FileFilter(filter : ElementFilter) : PositionElementFilter() {
|
||||
init {
|
||||
setFilter(filter)
|
||||
}
|
||||
|
||||
override fun isAcceptable(element : Any?, context : PsiElement?) : Boolean {
|
||||
val file = (element as? PsiElement)?.containingFile
|
||||
return file != null && (filter?.isAcceptable(file, context) ?: true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildFilter(position: PsiElement): (KtKeywordToken) -> Boolean {
|
||||
var parent = position.parent
|
||||
var prevParent = position
|
||||
|
||||
+5
-2
@@ -32,7 +32,8 @@ class LookupElementsCollector(
|
||||
private val prefixMatcher: PrefixMatcher,
|
||||
private val completionParameters: CompletionParameters,
|
||||
resultSet: CompletionResultSet,
|
||||
sorter: CompletionSorter
|
||||
sorter: CompletionSorter,
|
||||
private val filter: ((LookupElement) -> Boolean)?
|
||||
) {
|
||||
|
||||
var bestMatchingDegree = Int.MIN_VALUE
|
||||
@@ -132,7 +133,9 @@ class LookupElementsCollector(
|
||||
}
|
||||
}
|
||||
|
||||
elements.add(result)
|
||||
if (filter?.invoke(result) ?: true) {
|
||||
elements.add(result)
|
||||
}
|
||||
|
||||
val matchingDegree = RealPrefixMatchingWeigher.getBestMatchingDegree(result, prefixMatcher)
|
||||
bestMatchingDegree = Math.max(bestMatchingDegree, matchingDegree)
|
||||
|
||||
+25
-7
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.ide.util.ClassFilter;
|
||||
import com.intellij.ide.util.TreeClassChooser;
|
||||
import com.intellij.ide.util.TreeJavaClassChooserDialog;
|
||||
@@ -23,9 +24,9 @@ import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaCodeFragment;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
@@ -34,18 +35,21 @@ import com.intellij.refactoring.classMembers.MemberInfoChange;
|
||||
import com.intellij.refactoring.move.MoveCallback;
|
||||
import com.intellij.refactoring.move.MoveHandler;
|
||||
import com.intellij.refactoring.ui.RefactoringDialog;
|
||||
import com.intellij.ui.ReferenceEditorComboWithBrowseButton;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration;
|
||||
import org.jetbrains.kotlin.idea.completion.CompletionUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject;
|
||||
import org.jetbrains.kotlin.idea.projectView.KtClassOrObjectTreeNode;
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtilKt;
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo;
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel;
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTable;
|
||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*;
|
||||
import org.jetbrains.kotlin.idea.refactoring.ui.KotlinTypeReferenceEditorComboWithBrowseButton;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -62,7 +66,7 @@ public class MoveKotlinNestedClassesDialog extends RefactoringDialog {
|
||||
private JPanel mainPanel;
|
||||
private JTextField originalClassField;
|
||||
private JPanel membersInfoPanel;
|
||||
private ReferenceEditorComboWithBrowseButton targetClassChooser;
|
||||
private KotlinTypeReferenceEditorComboWithBrowseButton targetClassChooser;
|
||||
private JCheckBox openInEditorCheckBox;
|
||||
private JPanel targetClassChooserPanel;
|
||||
private KotlinMemberSelectionTable memberTable;
|
||||
@@ -96,7 +100,7 @@ public class MoveKotlinNestedClassesDialog extends RefactoringDialog {
|
||||
originalClassField.setText(originalClass.getFqName().asString());
|
||||
|
||||
//noinspection ConstantConditions
|
||||
targetClassChooser = new ReferenceEditorComboWithBrowseButton(
|
||||
targetClassChooser = new KotlinTypeReferenceEditorComboWithBrowseButton(
|
||||
new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -148,10 +152,24 @@ public class MoveKotlinNestedClassesDialog extends RefactoringDialog {
|
||||
}
|
||||
},
|
||||
initialTargetClass.getFqName().asString(),
|
||||
myProject,
|
||||
true,
|
||||
JavaCodeFragment.VisibilityChecker.PROJECT_SCOPE_VISIBLE,
|
||||
originalClass,
|
||||
RECENTS_KEY);
|
||||
KtTypeCodeFragment codeFragment = targetClassChooser.getCodeFragment();
|
||||
if (codeFragment != null) {
|
||||
CompletionUtilsKt.setExtraCompletionFilter(
|
||||
codeFragment,
|
||||
new Function1<LookupElement, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(LookupElement lookupElement) {
|
||||
Object lookupObject = lookupElement.getObject();
|
||||
if (!(lookupObject instanceof DeclarationLookupObject)) return false;
|
||||
PsiElement psiElement = ((DeclarationLookupObject) lookupObject).getPsiElement();
|
||||
if (!(psiElement instanceof KtClassOrObject)) return false;
|
||||
return KotlinRefactoringUtilKt.canRefactor(psiElement);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
targetClassChooser.getChildComponent().getDocument().addDocumentListener(
|
||||
new DocumentAdapter() {
|
||||
@Override
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.refactoring.ui
|
||||
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.ui.ComponentWithBrowseButton
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.ui.EditorComboBox
|
||||
import com.intellij.ui.RecentsManager
|
||||
import com.intellij.ui.TextAccessor
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtTypeCodeFragment
|
||||
import java.awt.event.ActionListener
|
||||
|
||||
class KotlinTypeReferenceEditorComboWithBrowseButton(
|
||||
browseActionListener: ActionListener,
|
||||
text: String?,
|
||||
contextElement: PsiElement,
|
||||
recentsKey: String
|
||||
) : ComponentWithBrowseButton<EditorComboBox>(
|
||||
EditorComboBox(createDocument(text, contextElement), contextElement.project, KotlinFileType.INSTANCE),
|
||||
browseActionListener
|
||||
), TextAccessor {
|
||||
companion object {
|
||||
private fun createDocument(text: String?, contextElement: PsiElement): Document? {
|
||||
val codeFragment = KtPsiFactory(contextElement).createTypeCodeFragment(text ?: "", contextElement)
|
||||
return PsiDocumentManager.getInstance(contextElement.project).getDocument(codeFragment)
|
||||
}
|
||||
}
|
||||
|
||||
private val project = contextElement.project
|
||||
|
||||
init {
|
||||
RecentsManager.getInstance(contextElement.project).getRecentEntries(recentsKey)?.let {
|
||||
childComponent.setHistory(ArrayUtil.toStringArray(it))
|
||||
}
|
||||
|
||||
if (text != null) {
|
||||
if (text.isNotEmpty()) {
|
||||
childComponent.prependItem(text)
|
||||
}
|
||||
else {
|
||||
childComponent.selectedItem = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getText() = childComponent.text.trim { it <= ' ' }
|
||||
|
||||
override fun setText(text: String) {
|
||||
childComponent.text = text
|
||||
}
|
||||
|
||||
val codeFragment: KtTypeCodeFragment?
|
||||
get() = PsiDocumentManager.getInstance(project).getPsiFile(childComponent.document) as? KtTypeCodeFragment
|
||||
}
|
||||
Reference in New Issue
Block a user