Refactoring: Extend expression selection utilities to support KtTypeElement
This commit is contained in:
@@ -27,9 +27,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -47,8 +45,23 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
|
||||
public class CodeInsightUtils {
|
||||
|
||||
@Nullable
|
||||
public static KtExpression findExpression(@NotNull PsiFile file, int startOffset, int endOffset) {
|
||||
KtExpression element = findElementOfClassAtRange(file, startOffset, endOffset, KtExpression.class);
|
||||
public static PsiElement findElement(
|
||||
@NotNull PsiFile file,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind
|
||||
) {
|
||||
Class<? extends KtElement> elementClass;
|
||||
switch (elementKind) {
|
||||
case EXPRESSION: elementClass = KtExpression.class;
|
||||
break;
|
||||
case TYPE_ELEMENT: elementClass = KtTypeElement.class;
|
||||
break;
|
||||
default: throw new IllegalArgumentException(elementKind.name());
|
||||
}
|
||||
PsiElement element = findElementOfClassAtRange(file, startOffset, endOffset, elementClass);
|
||||
|
||||
if (elementKind == ElementKind.TYPE_ELEMENT) return element;
|
||||
|
||||
if (element instanceof KtScriptInitializer) {
|
||||
element = ((KtScriptInitializer) element).getBody();
|
||||
@@ -78,24 +91,26 @@ public class CodeInsightUtils {
|
||||
}
|
||||
}
|
||||
|
||||
KtExpression expression = element;
|
||||
KtExpression expression = (KtExpression) element;
|
||||
|
||||
BindingContext context = ResolutionUtils.analyze(expression);
|
||||
|
||||
Qualifier qualifier = context.get(BindingContext.QUALIFIER, expression);
|
||||
if (qualifier != null) {
|
||||
if (!(qualifier instanceof ClassQualifier)) return null;
|
||||
ClassifierDescriptor classifier = ((ClassQualifier) qualifier).getDescriptor();
|
||||
if (!(classifier instanceof ClassDescriptor) || ((ClassDescriptor) classifier).getKind() != ClassKind.OBJECT) {
|
||||
return null;
|
||||
}
|
||||
if (((ClassQualifier) qualifier).getDescriptor().getKind() != ClassKind.OBJECT) return null;
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
public enum ElementKind {
|
||||
EXPRESSION,
|
||||
TYPE_ELEMENT
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiElement[] findStatements(@NotNull PsiFile file, int startOffset, int endOffset) {
|
||||
public static PsiElement[] findElements(@NotNull PsiFile file, int startOffset, int endOffset, @NotNull ElementKind kind) {
|
||||
PsiElement element1 = getElementAtOffsetIgnoreWhitespaceBefore(file, startOffset);
|
||||
PsiElement element2 = getElementAtOffsetIgnoreWhitespaceAfter(file, endOffset);
|
||||
|
||||
@@ -129,7 +144,9 @@ public class CodeInsightUtils {
|
||||
}
|
||||
|
||||
for (PsiElement element : array) {
|
||||
if (!(element instanceof KtExpression
|
||||
boolean correctType = kind == ElementKind.EXPRESSION && element instanceof KtExpression
|
||||
|| kind == ElementKind.TYPE_ELEMENT && element instanceof KtTypeElement;
|
||||
if (!(correctType
|
||||
|| element.getNode().getElementType() == KtTokens.SEMICOLON
|
||||
|| element instanceof PsiWhiteSpace
|
||||
|| element instanceof PsiComment)) {
|
||||
|
||||
+4
-1
@@ -37,7 +37,10 @@ public class KotlinExpressionSurroundDescriptor implements SurroundDescriptor {
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
|
||||
KtExpression expression = CodeInsightUtils.findExpression(file, startOffset, endOffset);
|
||||
KtExpression expression = (KtExpression) CodeInsightUtils.findElement(file,
|
||||
startOffset,
|
||||
endOffset,
|
||||
CodeInsightUtils.ElementKind.EXPRESSION);
|
||||
if (expression == null) {
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class KotlinStatementSurroundDescriptor implements SurroundDescriptor {
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) {
|
||||
return CodeInsightUtils.findStatements(file, startOffset, endOffset);
|
||||
return CodeInsightUtils.findElements(file, startOffset, endOffset, CodeInsightUtils.ElementKind.EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.IntroduceUtilKt;
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
||||
@@ -325,118 +326,144 @@ public class KotlinRefactoringUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public interface SelectExpressionCallback {
|
||||
void run(@Nullable KtExpression expression);
|
||||
public interface SelectElementCallback {
|
||||
void run(@Nullable PsiElement element);
|
||||
}
|
||||
|
||||
public static void selectExpression(
|
||||
public static void selectElement(
|
||||
@NotNull Editor editor,
|
||||
@NotNull KtFile file,
|
||||
@NotNull SelectExpressionCallback callback) throws IntroduceRefactoringException {
|
||||
selectExpression(editor, file, true, callback);
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind,
|
||||
@NotNull SelectElementCallback callback
|
||||
) throws IntroduceRefactoringException {
|
||||
selectElement(editor, file, true, elementKind, callback);
|
||||
}
|
||||
|
||||
public static void selectExpression(@NotNull Editor editor,
|
||||
public static void selectElement(@NotNull Editor editor,
|
||||
@NotNull KtFile file,
|
||||
boolean failOnEmptySuggestion,
|
||||
@NotNull SelectExpressionCallback callback) throws IntroduceRefactoringException {
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind,
|
||||
@NotNull SelectElementCallback callback
|
||||
) throws IntroduceRefactoringException {
|
||||
if (editor.getSelectionModel().hasSelection()) {
|
||||
int selectionStart = editor.getSelectionModel().getSelectionStart();
|
||||
int selectionEnd = editor.getSelectionModel().getSelectionEnd();
|
||||
String text = file.getText();
|
||||
while (selectionStart < selectionEnd && Character.isSpaceChar(text.charAt(selectionStart))) ++selectionStart;
|
||||
while (selectionStart < selectionEnd && Character.isSpaceChar(text.charAt(selectionEnd - 1))) --selectionEnd;
|
||||
callback.run(findExpression(file, selectionStart, selectionEnd, failOnEmptySuggestion));
|
||||
callback.run(findElement(file, selectionStart, selectionEnd, failOnEmptySuggestion, elementKind));
|
||||
}
|
||||
else {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
smartSelectExpression(editor, file, offset, failOnEmptySuggestion, callback);
|
||||
smartSelectElement(editor, file, offset, failOnEmptySuggestion, elementKind, callback);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<KtExpression> getSmartSelectSuggestions(
|
||||
public static List<KtElement> getSmartSelectSuggestions(
|
||||
@NotNull PsiFile file,
|
||||
int offset
|
||||
int offset,
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind
|
||||
) throws IntroduceRefactoringException {
|
||||
if (offset < 0) {
|
||||
return new ArrayList<KtExpression>();
|
||||
return new ArrayList<KtElement>();
|
||||
}
|
||||
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
if (element == null) {
|
||||
return new ArrayList<KtExpression>();
|
||||
return new ArrayList<KtElement>();
|
||||
}
|
||||
if (element instanceof PsiWhiteSpace) {
|
||||
return getSmartSelectSuggestions(file, offset - 1);
|
||||
return getSmartSelectSuggestions(file, offset - 1, elementKind);
|
||||
}
|
||||
|
||||
List<KtExpression> expressions = new ArrayList<KtExpression>();
|
||||
List<KtElement> elements = new ArrayList<KtElement>();
|
||||
while (element != null && !(element instanceof KtBlockExpression && !(element.getParent() instanceof KtFunctionLiteral)) &&
|
||||
!(element instanceof KtNamedFunction)
|
||||
&& !(element instanceof KtClassBody)) {
|
||||
if (element instanceof KtExpression && !(element instanceof KtStatementExpression)) {
|
||||
boolean addExpression = true;
|
||||
boolean addElement = false;
|
||||
boolean keepPrevious = true;
|
||||
|
||||
if (element instanceof KtParenthesizedExpression) {
|
||||
addExpression = false;
|
||||
if (element instanceof KtTypeElement) {
|
||||
addElement = elementKind == CodeInsightUtils.ElementKind.TYPE_ELEMENT;
|
||||
if (!addElement) {
|
||||
keepPrevious = false;
|
||||
}
|
||||
else if (KtPsiUtil.isLabelIdentifierExpression(element)) {
|
||||
addExpression = false;
|
||||
}
|
||||
else if (element.getParent() instanceof KtQualifiedExpression) {
|
||||
KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) element.getParent();
|
||||
if (qualifiedExpression.getReceiverExpression() != element) {
|
||||
addExpression = false;
|
||||
}
|
||||
else if (element instanceof KtExpression && !(element instanceof KtStatementExpression)) {
|
||||
addElement = elementKind == CodeInsightUtils.ElementKind.EXPRESSION;
|
||||
|
||||
if (addElement) {
|
||||
if (element instanceof KtParenthesizedExpression) {
|
||||
addElement = false;
|
||||
}
|
||||
}
|
||||
else if (element.getParent() instanceof KtCallElement
|
||||
|| element.getParent() instanceof KtThisExpression
|
||||
|| PsiTreeUtil.getParentOfType(element, KtSuperExpression.class) != null) {
|
||||
addExpression = false;
|
||||
}
|
||||
else if (element.getParent() instanceof KtOperationExpression) {
|
||||
KtOperationExpression operationExpression = (KtOperationExpression) element.getParent();
|
||||
if (operationExpression.getOperationReference() == element) {
|
||||
addExpression = false;
|
||||
else if (KtPsiUtil.isLabelIdentifierExpression(element)) {
|
||||
addElement = false;
|
||||
}
|
||||
}
|
||||
if (addExpression) {
|
||||
KtExpression expression = (KtExpression)element;
|
||||
BindingContext bindingContext = ResolutionUtils.analyze(expression, BodyResolveMode.FULL);
|
||||
KotlinType expressionType = bindingContext.getType(expression);
|
||||
if (expressionType == null || !KotlinBuiltIns.isUnit(expressionType)) {
|
||||
expressions.add(expression);
|
||||
else if (element.getParent() instanceof KtQualifiedExpression) {
|
||||
KtQualifiedExpression qualifiedExpression = (KtQualifiedExpression) element.getParent();
|
||||
if (qualifiedExpression.getReceiverExpression() != element) {
|
||||
addElement = false;
|
||||
}
|
||||
}
|
||||
else if (element.getParent() instanceof KtCallElement
|
||||
|| element.getParent() instanceof KtThisExpression
|
||||
|| PsiTreeUtil.getParentOfType(element, KtSuperExpression.class) != null) {
|
||||
addElement = false;
|
||||
}
|
||||
else if (element.getParent() instanceof KtOperationExpression) {
|
||||
KtOperationExpression operationExpression = (KtOperationExpression) element.getParent();
|
||||
if (operationExpression.getOperationReference() == element) {
|
||||
addElement = false;
|
||||
}
|
||||
}
|
||||
if (addElement) {
|
||||
KtExpression expression = (KtExpression)element;
|
||||
BindingContext bindingContext = ResolutionUtils.analyze(expression, BodyResolveMode.FULL);
|
||||
KotlinType expressionType = bindingContext.getType(expression);
|
||||
if (expressionType != null && KotlinBuiltIns.isUnit(expressionType)) {
|
||||
addElement = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element instanceof KtTypeElement) {
|
||||
expressions.clear();
|
||||
|
||||
if (addElement) {
|
||||
elements.add((KtElement) element);
|
||||
}
|
||||
|
||||
if (!keepPrevious) {
|
||||
elements.clear();
|
||||
}
|
||||
|
||||
element = element.getParent();
|
||||
}
|
||||
return expressions;
|
||||
return elements;
|
||||
}
|
||||
|
||||
private static void smartSelectExpression(
|
||||
@NotNull Editor editor, @NotNull PsiFile file, int offset,
|
||||
private static void smartSelectElement(
|
||||
@NotNull Editor editor,
|
||||
@NotNull PsiFile file,
|
||||
int offset,
|
||||
boolean failOnEmptySuggestion,
|
||||
@NotNull final SelectExpressionCallback callback) throws IntroduceRefactoringException {
|
||||
List<KtExpression> expressions = getSmartSelectSuggestions(file, offset);
|
||||
if (expressions.size() == 0) {
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind,
|
||||
@NotNull final SelectElementCallback callback
|
||||
) throws IntroduceRefactoringException {
|
||||
List<KtElement> elements = getSmartSelectSuggestions(file, offset, elementKind);
|
||||
if (elements.size() == 0) {
|
||||
if (failOnEmptySuggestion) throw new IntroduceRefactoringException(
|
||||
KotlinRefactoringBundle.message("cannot.refactor.not.expression"));
|
||||
callback.run(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (expressions.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
callback.run(expressions.get(0));
|
||||
if (elements.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
callback.run(elements.get(0));
|
||||
return;
|
||||
}
|
||||
|
||||
final DefaultListModel model = new DefaultListModel();
|
||||
for (KtExpression expression : expressions) {
|
||||
model.addElement(expression);
|
||||
for (PsiElement element : elements) {
|
||||
model.addElement(element);
|
||||
}
|
||||
|
||||
final ScopeHighlighter highlighter = new ScopeHighlighter(editor);
|
||||
@@ -447,7 +474,7 @@ public class KotlinRefactoringUtil {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(@NotNull JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
KtExpression element = (KtExpression) value;
|
||||
KtElement element = (KtElement) value;
|
||||
if (element.isValid()) {
|
||||
setText(getExpressionShortText(element));
|
||||
}
|
||||
@@ -461,7 +488,7 @@ public class KotlinRefactoringUtil {
|
||||
highlighter.dropHighlight();
|
||||
int selectedIndex = list.getSelectedIndex();
|
||||
if (selectedIndex < 0) return;
|
||||
KtExpression expression = (KtExpression) model.get(selectedIndex);
|
||||
KtElement expression = (KtElement) model.get(selectedIndex);
|
||||
List<PsiElement> toExtract = new ArrayList<PsiElement>();
|
||||
toExtract.add(expression);
|
||||
highlighter.highlight(expression, toExtract);
|
||||
@@ -473,7 +500,7 @@ public class KotlinRefactoringUtil {
|
||||
setRequestFocus(true).setItemChoosenCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.run((KtExpression) list.getSelectedValue());
|
||||
callback.run((KtElement) list.getSelectedValue());
|
||||
}
|
||||
}).addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
@@ -493,10 +520,17 @@ public class KotlinRefactoringUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KtExpression findExpression(
|
||||
@NotNull KtFile file, int startOffset, int endOffset, boolean failOnNoExpression
|
||||
private static PsiElement findElement(
|
||||
@NotNull KtFile file,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
boolean failOnNoExpression,
|
||||
@NotNull CodeInsightUtils.ElementKind elementKind
|
||||
) throws IntroduceRefactoringException {
|
||||
KtExpression element = IntroduceUtilKt.findExpressionOrStringFragment(file, startOffset, endOffset);
|
||||
PsiElement element = CodeInsightUtils.findElement(file, startOffset, endOffset, elementKind);
|
||||
if (element == null && elementKind == CodeInsightUtils.ElementKind.EXPRESSION) {
|
||||
element = IntroduceUtilKt.findExpressionOrStringFragment(file, startOffset, endOffset);
|
||||
}
|
||||
if (element == null) {
|
||||
//todo: if it's infix expression => add (), then commit document then return new created expression
|
||||
|
||||
|
||||
+3
-1
@@ -22,8 +22,9 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.RefactoringActionHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringBundle
|
||||
import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.selectElementsWithTargetSibling
|
||||
@@ -67,6 +68,7 @@ class ExtractKotlinFunctionHandler(
|
||||
editor,
|
||||
file,
|
||||
"Select target code block",
|
||||
CodeInsightUtils.ElementKind.EXPRESSION,
|
||||
{ elements, parent -> parent.getExtractionContainers(elements.size == 1, allContainersEnabled) },
|
||||
continuation
|
||||
)
|
||||
|
||||
+4
-3
@@ -36,22 +36,22 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.core.moveInsideParenthesesAndReplaceWith
|
||||
import org.jetbrains.kotlin.idea.refactoring.removeTemplateEntryBracesIfPossible
|
||||
import org.jetbrains.kotlin.idea.refactoring.runRefactoringWithPostprocessing
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringBundle
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.removeTemplateEntryBracesIfPossible
|
||||
import org.jetbrains.kotlin.idea.refactoring.runRefactoringWithPostprocessing
|
||||
import org.jetbrains.kotlin.idea.refactoring.runSynchronouslyWithProgress
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.KotlinPsiRange
|
||||
@@ -191,6 +191,7 @@ fun selectNewParameterContext(
|
||||
editor = editor,
|
||||
file = file,
|
||||
title = "Introduce parameter to declaration",
|
||||
elementKind = CodeInsightUtils.ElementKind.EXPRESSION,
|
||||
getContainers = { elements, parent ->
|
||||
val parents = parent.parents
|
||||
val stopAt = (parent.parents.zip(parent.parents.drop(1)))
|
||||
|
||||
+2
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
|
||||
import org.jetbrains.kotlin.idea.util.psi.patternMatching.*
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.refactoring.RefactoringActionHandler
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers
|
||||
import java.util.*
|
||||
|
||||
@@ -58,6 +59,7 @@ class KotlinIntroducePropertyHandler(
|
||||
editor,
|
||||
file,
|
||||
"Select target code block",
|
||||
CodeInsightUtils.ElementKind.EXPRESSION,
|
||||
{ elements, parent ->
|
||||
parent.getExtractionContainers(strict = true, includeAll = true).filter { it is KtClassBody || (it is KtFile && !it.isScript) }
|
||||
},
|
||||
|
||||
@@ -45,6 +45,7 @@ fun selectElementsWithTargetSibling(
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKind: CodeInsightUtils.ElementKind,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit
|
||||
) {
|
||||
@@ -67,7 +68,7 @@ fun selectElementsWithTargetSibling(
|
||||
continuation(elements, outermostParent)
|
||||
}
|
||||
|
||||
selectElementsWithTargetParent(operationName, editor, file, title, getContainers, ::onSelectionComplete)
|
||||
selectElementsWithTargetParent(operationName, editor, file, title, elementKind, getContainers, ::onSelectionComplete)
|
||||
}
|
||||
|
||||
fun selectElementsWithTargetParent(
|
||||
@@ -75,6 +76,7 @@ fun selectElementsWithTargetParent(
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKind: CodeInsightUtils.ElementKind,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetParent: PsiElement) -> Unit
|
||||
) {
|
||||
@@ -103,11 +105,11 @@ fun selectElementsWithTargetParent(
|
||||
)
|
||||
}
|
||||
|
||||
fun selectMultipleExpressions() {
|
||||
fun selectMultipleElements() {
|
||||
val startOffset = editor.selectionModel.selectionStart
|
||||
val endOffset = editor.selectionModel.selectionEnd
|
||||
|
||||
val elements = CodeInsightUtils.findStatements(file, startOffset, endOffset)
|
||||
val elements = CodeInsightUtils.findElements(file, startOffset, endOffset, elementKind)
|
||||
if (elements.isEmpty()) {
|
||||
showErrorHintByKey("cannot.refactor.no.expression")
|
||||
return
|
||||
@@ -116,27 +118,29 @@ fun selectElementsWithTargetParent(
|
||||
selectTargetContainer(elements.toList())
|
||||
}
|
||||
|
||||
fun selectSingleExpression() {
|
||||
KotlinRefactoringUtil.selectExpression(editor, file, false) { expr ->
|
||||
fun selectSingleElement() {
|
||||
KotlinRefactoringUtil.selectElement(editor, file, false, elementKind) { expr ->
|
||||
if (expr != null) {
|
||||
selectTargetContainer(listOf(expr))
|
||||
}
|
||||
else {
|
||||
if (!editor.selectionModel.hasSelection()) {
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
elementAtCaret?.getParentOfTypeAndBranch<KtProperty> { nameIdentifier }?.let {
|
||||
return@selectExpression selectTargetContainer(listOf(it))
|
||||
if (elementKind == CodeInsightUtils.ElementKind.EXPRESSION) {
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
elementAtCaret?.getParentOfTypeAndBranch<KtProperty> { nameIdentifier }?.let {
|
||||
return@selectElement selectTargetContainer(listOf(it))
|
||||
}
|
||||
}
|
||||
|
||||
editor.selectionModel.selectLineAtCaret()
|
||||
}
|
||||
selectMultipleExpressions()
|
||||
selectMultipleElements()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
|
||||
selectSingleExpression()
|
||||
selectSingleElement()
|
||||
}
|
||||
|
||||
fun PsiElement.findExpressionByCopyableDataAndClearIt(key: Key<Boolean>): KtExpression {
|
||||
@@ -158,8 +162,6 @@ fun PsiElement.findExpressionsByCopyableDataAndClearIt(key: Key<Boolean>): List<
|
||||
}
|
||||
|
||||
fun findExpressionOrStringFragment(file: KtFile, startOffset: Int, endOffset: Int): KtExpression? {
|
||||
CodeInsightUtils.findExpression(file, startOffset, endOffset)?.let { return it }
|
||||
|
||||
val entry1 = file.findElementAt(startOffset)?.getNonStrictParentOfType<KtStringTemplateEntry>() ?: return null
|
||||
val entry2 = file.findElementAt(endOffset - 1)?.getNonStrictParentOfType<KtStringTemplateEntry>() ?: return null
|
||||
|
||||
|
||||
+2
-1
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||
import org.jetbrains.kotlin.idea.analysis.computeTypeInfoInContext
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
import org.jetbrains.kotlin.idea.intentions.ConvertToBlockBodyIntention
|
||||
import org.jetbrains.kotlin.idea.refactoring.*
|
||||
@@ -718,7 +719,7 @@ object KotlinIntroduceVariableHandler : RefactoringActionHandler {
|
||||
if (file !is KtFile) return
|
||||
|
||||
try {
|
||||
KotlinRefactoringUtil.selectExpression(editor, file) { doRefactoring(project, editor, it, null, null) }
|
||||
KotlinRefactoringUtil.selectElement(editor, file, CodeInsightUtils.ElementKind.EXPRESSION) { doRefactoring(project, editor, it as KtExpression?, null, null) }
|
||||
}
|
||||
catch (e: KotlinRefactoringUtil.IntroduceRefactoringException) {
|
||||
showErrorHint(project, editor, e.message!!)
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
@@ -31,11 +32,11 @@ public abstract class AbstractExpressionSelectionTest extends LightCodeInsightTe
|
||||
final String expectedExpression = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
||||
|
||||
try {
|
||||
KotlinRefactoringUtil.selectExpression(getEditor(), (KtFile) getFile(), new KotlinRefactoringUtil.SelectExpressionCallback() {
|
||||
KotlinRefactoringUtil.selectElement(getEditor(), (KtFile) getFile(), CodeInsightUtils.ElementKind.EXPRESSION, new KotlinRefactoringUtil.SelectElementCallback() {
|
||||
@Override
|
||||
public void run(@Nullable KtExpression expression) {
|
||||
assertNotNull("Selected expression mustn't be null", expression);
|
||||
assertEquals(expectedExpression, expression.getText());
|
||||
public void run(@Nullable PsiElement element) {
|
||||
assertNotNull("Selected expression mustn't be null", element);
|
||||
assertEquals(expectedExpression, element.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ package org.jetbrains.kotlin.idea;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
@@ -33,12 +34,12 @@ public abstract class AbstractSmartSelectionTest extends LightCodeInsightTestCas
|
||||
configureByFile(path);
|
||||
String expectedResultText = KotlinTestUtils.getLastCommentInFile((KtFile) getFile());
|
||||
|
||||
List<KtExpression> expressions = KotlinRefactoringUtil.getSmartSelectSuggestions(
|
||||
getFile(), getEditor().getCaretModel().getOffset());
|
||||
List<KtElement> elements = KotlinRefactoringUtil.getSmartSelectSuggestions(
|
||||
getFile(), getEditor().getCaretModel().getOffset(), CodeInsightUtils.ElementKind.EXPRESSION);
|
||||
|
||||
List<String> textualExpressions = new ArrayList<String>();
|
||||
for (KtExpression expression : expressions) {
|
||||
textualExpressions.add(KotlinRefactoringUtil.getExpressionShortText(expression));
|
||||
for (KtElement element : elements) {
|
||||
textualExpressions.add(KotlinRefactoringUtil.getExpressionShortText(element));
|
||||
}
|
||||
assertEquals(expectedResultText, StringUtil.join(textualExpressions, "\n"));
|
||||
}
|
||||
|
||||
+4
-2
@@ -36,6 +36,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.EXTRACT_FUNCTION
|
||||
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ExtractKotlinFunctionHandler
|
||||
@@ -48,6 +49,7 @@ import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
@@ -109,8 +111,8 @@ abstract class AbstractExtractionTest() : KotlinLightCodeInsightFixtureTestCase(
|
||||
with (handler) {
|
||||
val target = (file as KtFile).findElementByCommentPrefix("// TARGET:") as? KtNamedDeclaration
|
||||
if (target != null) {
|
||||
KotlinRefactoringUtil.selectExpression(fixture.getEditor(), file, true) { expression ->
|
||||
invoke(fixture.getProject(), fixture.getEditor(), expression!!, target)
|
||||
KotlinRefactoringUtil.selectElement(fixture.getEditor(), file, true, CodeInsightUtils.ElementKind.EXPRESSION) { element ->
|
||||
invoke(fixture.getProject(), fixture.getEditor(), element as KtExpression, target)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+11
-3
@@ -17,8 +17,10 @@
|
||||
package org.jetbrains.kotlin.idea.refactoring.nameSuggester
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringUtil
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
@@ -88,9 +90,15 @@ class KotlinNameSuggesterTest : LightCodeInsightFixtureTestCase() {
|
||||
if (withRuntime) {
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())
|
||||
}
|
||||
KotlinRefactoringUtil.selectExpression(myFixture.editor, file, object : KotlinRefactoringUtil.SelectExpressionCallback {
|
||||
override fun run(expression: KtExpression?) {
|
||||
val names = KotlinNameSuggester.suggestNamesByExpressionAndType(expression!!, null, expression.analyze(BodyResolveMode.PARTIAL), { true }, "value").sorted()
|
||||
KotlinRefactoringUtil.selectElement(myFixture.editor, file, CodeInsightUtils.ElementKind.EXPRESSION, object : KotlinRefactoringUtil.SelectElementCallback {
|
||||
override fun run(element: PsiElement?) {
|
||||
val names = KotlinNameSuggester
|
||||
.suggestNamesByExpressionAndType(element as KtExpression,
|
||||
null,
|
||||
element.analyze(BodyResolveMode.PARTIAL),
|
||||
{ true },
|
||||
"value")
|
||||
.sorted()
|
||||
val result = StringUtil.join(names, "\n").trim()
|
||||
assertEquals(expectedResultText, result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user