Refactoring: Extend expression selection utilities to support KtTypeElement

This commit is contained in:
Alexey Sedunov
2016-07-12 15:43:11 +03:00
parent ef0318e038
commit 301f86cc96
13 changed files with 180 additions and 106 deletions
@@ -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)) {
@@ -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;
}
@@ -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
@@ -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
)
@@ -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)))
@@ -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
@@ -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"));
}
@@ -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 {
@@ -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)
}