diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java index d810761c5d3..506951488d5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/CodeInsightUtils.java @@ -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 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)) { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java index c85137b5518..8528796a38d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/expression/KotlinExpressionSurroundDescriptor.java @@ -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; } diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/statement/KotlinStatementSurroundDescriptor.java b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/statement/KotlinStatementSurroundDescriptor.java index 09c54819c29..4683c2639e1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/statement/KotlinStatementSurroundDescriptor.java +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/surroundWith/statement/KotlinStatementSurroundDescriptor.java @@ -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 diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringUtil.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringUtil.java index ab8524bdbcc..47edf8f7a26 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringUtil.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringUtil.java @@ -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 getSmartSelectSuggestions( + public static List getSmartSelectSuggestions( @NotNull PsiFile file, - int offset + int offset, + @NotNull CodeInsightUtils.ElementKind elementKind ) throws IntroduceRefactoringException { if (offset < 0) { - return new ArrayList(); + return new ArrayList(); } PsiElement element = file.findElementAt(offset); if (element == null) { - return new ArrayList(); + return new ArrayList(); } if (element instanceof PsiWhiteSpace) { - return getSmartSelectSuggestions(file, offset - 1); + return getSmartSelectSuggestions(file, offset - 1, elementKind); } - List expressions = new ArrayList(); + List elements = new ArrayList(); 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 expressions = getSmartSelectSuggestions(file, offset); - if (expressions.size() == 0) { + @NotNull CodeInsightUtils.ElementKind elementKind, + @NotNull final SelectElementCallback callback + ) throws IntroduceRefactoringException { + List 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 toExtract = new ArrayList(); 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 diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt index da6fdebc104..62c173683d0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ExtractKotlinFunctionHandler.kt @@ -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 ) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt index 80125e0a23e..09bd1247823 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterHandler.kt @@ -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))) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceProperty/KotlinIntroducePropertyHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceProperty/KotlinIntroducePropertyHandler.kt index edde8a735be..d22f6d76688 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceProperty/KotlinIntroducePropertyHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceProperty/KotlinIntroducePropertyHandler.kt @@ -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) } }, diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt index 342186460f3..7f4782d2509 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceUtil.kt @@ -45,6 +45,7 @@ fun selectElementsWithTargetSibling( editor: Editor, file: KtFile, title: String, + elementKind: CodeInsightUtils.ElementKind, getContainers: (elements: List, commonParent: PsiElement) -> List, continuation: (elements: List, 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, commonParent: PsiElement) -> List, continuation: (elements: List, 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 { nameIdentifier }?.let { - return@selectExpression selectTargetContainer(listOf(it)) + if (elementKind == CodeInsightUtils.ElementKind.EXPRESSION) { + val elementAtCaret = file.findElementAt(editor.caretModel.offset) + elementAtCaret?.getParentOfTypeAndBranch { 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): KtExpression { @@ -158,8 +162,6 @@ fun PsiElement.findExpressionsByCopyableDataAndClearIt(key: Key): List< } fun findExpressionOrStringFragment(file: KtFile, startOffset: Int, endOffset: Int): KtExpression? { - CodeInsightUtils.findExpression(file, startOffset, endOffset)?.let { return it } - val entry1 = file.findElementAt(startOffset)?.getNonStrictParentOfType() ?: return null val entry2 = file.findElementAt(endOffset - 1)?.getNonStrictParentOfType() ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt index 8bac06cce49..063dd49bf8e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceVariable/KotlinIntroduceVariableHandler.kt @@ -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!!) diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java b/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java index be2037752f5..40e18da82fd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractExpressionSelectionTest.java @@ -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()); } }); } diff --git a/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java b/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java index f9218bf37ea..39ebd4ad679 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/AbstractSmartSelectionTest.java @@ -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 expressions = KotlinRefactoringUtil.getSmartSelectSuggestions( - getFile(), getEditor().getCaretModel().getOffset()); + List elements = KotlinRefactoringUtil.getSmartSelectSuggestions( + getFile(), getEditor().getCaretModel().getOffset(), CodeInsightUtils.ElementKind.EXPRESSION); List textualExpressions = new ArrayList(); - for (KtExpression expression : expressions) { - textualExpressions.add(KotlinRefactoringUtil.getExpressionShortText(expression)); + for (KtElement element : elements) { + textualExpressions.add(KotlinRefactoringUtil.getExpressionShortText(element)); } assertEquals(expectedResultText, StringUtil.join(textualExpressions, "\n")); } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt index 0b5e83ded58..ddc343e5681 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt @@ -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 { diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt index e083d72c7a0..ba59a4f1902 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/nameSuggester/KotlinNameSuggesterTest.kt @@ -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) }