diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinCodeBlockSelectioner.kt b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinCodeBlockSelectioner.kt index a7ae72e8c15..61e0ca957de 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinCodeBlockSelectioner.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinCodeBlockSelectioner.kt @@ -16,60 +16,69 @@ package org.jetbrains.kotlin.idea.editor.wordSelection -import com.intellij.lang.ASTNode +import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.kotlin.psi.KtWhenExpression -import org.jetbrains.kotlin.lexer.KtTokens - -import java.util.ArrayList -import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase import org.jetbrains.kotlin.psi.psiUtil.allChildren import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import java.util.* /** * Originally from IDEA platform: CodeBlockOrInitializerSelectioner */ class KotlinCodeBlockSelectioner : ExtendWordSelectionHandlerBase() { - override fun canSelect(e: PsiElement) - = e is KtBlockExpression || e is KtWhenExpression + + companion object { + fun canSelect(e: PsiElement) = isTarget(e) || (isBrace(e) && isTarget(e.parent)) + + private fun isTarget(e: PsiElement) = e is KtBlockExpression || e is KtWhenExpression + + private fun isBrace(e: PsiElement): Boolean { + val elementType = e.node.elementType + return elementType == KtTokens.LBRACE || elementType == KtTokens.RBRACE + } + } + + override fun canSelect(e: PsiElement) = KotlinCodeBlockSelectioner.canSelect(e) override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List? { val result = ArrayList() - val start = findBlockContentStart(e) - val end = findBlockContentEnd(e) + val block = if (isBrace(e)) e.parent else e + val start = findBlockContentStart(block) + val end = findBlockContentEnd(block) if (end > start) { result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, TextRange(start, end))) } - - result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, e.textRange!!)) + result.addAll(ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, block.textRange!!)) return result } private fun findBlockContentStart(block: PsiElement): Int { val element = block.allChildren - .dropWhile { it.node.elementType != KtTokens.LBRACE } // search for '{' - .drop(1) // skip it - .dropWhile { it is PsiWhiteSpace } // and skip all whitespaces - .firstOrNull() ?: block + .dropWhile { it.node.elementType != KtTokens.LBRACE } // search for '{' + .drop(1) // skip it + .dropWhile { it is PsiWhiteSpace } // and skip all whitespaces + .firstOrNull() ?: block return element.startOffset } private fun findBlockContentEnd(block: PsiElement): Int { val element = block.allChildren - .toList() - .asReversed() - .asSequence() - .dropWhile { it.node.elementType != KtTokens.RBRACE } // search for '}' - .drop(1) // skip it - .dropWhile { it is PsiWhiteSpace } // and skip all whitespaces - .firstOrNull() ?: block + .toList() + .asReversed() + .asSequence() + .dropWhile { it.node.elementType != KtTokens.RBRACE } // search for '}' + .drop(1) // skip it + .dropWhile { it is PsiWhiteSpace } // and skip all whitespaces + .firstOrNull() ?: block return element.endOffset } } diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt index cd00ec258b1..2d92647d05b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt @@ -29,6 +29,7 @@ class KotlinWordSelectionFilter : Condition{ if (e.language != KotlinLanguage.INSTANCE) return true if (KotlinListSelectioner.canSelect(e)) return false + if (KotlinCodeBlockSelectioner.canSelect(e)) return false val elementType = e.node.elementType if (elementType == KtTokens.REGULAR_STRING_PART || elementType == KtTokens.ESCAPE_SEQUENCE) return true diff --git a/idea/testData/wordSelection/LeftBrace/0.kt b/idea/testData/wordSelection/LeftBrace/0.kt new file mode 100644 index 00000000000..cc47cf8491c --- /dev/null +++ b/idea/testData/wordSelection/LeftBrace/0.kt @@ -0,0 +1,4 @@ +fun test() { + f() + g() +} \ No newline at end of file diff --git a/idea/testData/wordSelection/LeftBrace/1.kt b/idea/testData/wordSelection/LeftBrace/1.kt new file mode 100644 index 00000000000..75ed8aafd4f --- /dev/null +++ b/idea/testData/wordSelection/LeftBrace/1.kt @@ -0,0 +1,4 @@ +fun test() { + f() + g() +} \ No newline at end of file diff --git a/idea/testData/wordSelection/RightBrace/0.kt b/idea/testData/wordSelection/RightBrace/0.kt new file mode 100644 index 00000000000..c1fb1c75f10 --- /dev/null +++ b/idea/testData/wordSelection/RightBrace/0.kt @@ -0,0 +1,4 @@ +fun test() { + f() + g() +} \ No newline at end of file diff --git a/idea/testData/wordSelection/RightBrace/1.kt b/idea/testData/wordSelection/RightBrace/1.kt new file mode 100644 index 00000000000..81cac52847d --- /dev/null +++ b/idea/testData/wordSelection/RightBrace/1.kt @@ -0,0 +1,4 @@ +fun test() { + f() + g() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/WordSelectionTest.java b/idea/tests/org/jetbrains/kotlin/idea/WordSelectionTest.java index 534d58f9251..5f9871fae31 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/WordSelectionTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/WordSelectionTest.java @@ -130,6 +130,9 @@ public class WordSelectionTest extends KotlinLightCodeInsightFixtureTestCase { public void testDeclarationWithComment3() { doTest(); } public void testDeclarationWithComment4() { doTest(); } + public void testLeftBrace() { doTest(); } + public void testRightBrace() { doTest(); } + private void doTest() { String dirName = getTestName(false);