From 0bcdb9a95ed22299de936ea0a996c308241412ad Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 24 Feb 2012 19:05:34 +0400 Subject: [PATCH] Added smart Ctrl+W support in Kotlin plugin. #KT-1267 fixed #KT-1271 fixed --- idea/src/META-INF/plugin.xml | 3 + .../jet/plugin/JetCodeBlockSelectioner.java | 93 +++++++++++++++ .../plugin/JetStatementGroupSelectioner.java | 112 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/JetCodeBlockSelectioner.java create mode 100644 idea/src/org/jetbrains/jet/plugin/JetStatementGroupSelectioner.java diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 87a93df2976..a58f10797e2 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -120,6 +120,9 @@ + + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetCodeBlockSelectioner.java b/idea/src/org/jetbrains/jet/plugin/JetCodeBlockSelectioner.java new file mode 100644 index 00000000000..0abdd99a22b --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetCodeBlockSelectioner.java @@ -0,0 +1,93 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jet.plugin; + +import com.intellij.codeInsight.editorActions.wordSelection.BasicSelectioner; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.impl.source.tree.LeafPsiElement; +import org.jetbrains.jet.lang.psi.JetBlockExpression; +import org.jetbrains.jet.lang.psi.JetWhenExpression; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.ArrayList; +import java.util.List; + +/** + * Originally from IDEA platform: CodeBlockOrInitializerSelectioner + */ +public class JetCodeBlockSelectioner extends BasicSelectioner { + public boolean canSelect(PsiElement e) { + return e instanceof JetBlockExpression || e instanceof JetWhenExpression; + } + + public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) { + List result = new ArrayList(); + + ASTNode[] children = e.getNode().getChildren(null); + + int start = findOpeningBrace(children); + int end = findClosingBrace(children, start); + + result.add(e.getTextRange()); + result.addAll(expandToWholeLine(editorText, new TextRange(start, end))); + + return result; + } + + public static int findOpeningBrace(ASTNode[] children) { + int start = children[children.length - 1].getTextRange().getStartOffset(); + for (int i = 0; i < children.length; i++) { + PsiElement child = children[i].getPsi(); + + if (child instanceof LeafPsiElement) { + if (((LeafPsiElement) child).getElementType() == JetTokens.LBRACE) { + int j = i + 1; + + while (children[j] instanceof PsiWhiteSpace) { + j++; + } + + start = children[j].getTextRange().getStartOffset(); + } + } + } + return start; + } + + public static int findClosingBrace(ASTNode[] children, int startOffset) { + int end = children[children.length - 1].getTextRange().getEndOffset(); + for (int i = 0; i < children.length; i++) { + PsiElement child = children[i].getPsi(); + + if (child instanceof LeafPsiElement) { + if (((LeafPsiElement) child).getElementType() == JetTokens.RBRACE) { + int j = i - 1; + + while (children[j] instanceof PsiWhiteSpace && children[j].getTextRange().getStartOffset() > startOffset) { + j--; + } + + end = children[j].getTextRange().getEndOffset(); + } + } + } + return end; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/JetStatementGroupSelectioner.java b/idea/src/org/jetbrains/jet/plugin/JetStatementGroupSelectioner.java new file mode 100644 index 00000000000..40086378ab6 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/JetStatementGroupSelectioner.java @@ -0,0 +1,112 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin; + +import com.intellij.codeInsight.editorActions.wordSelection.BasicSelectioner; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.LineTokenizer; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.impl.source.tree.LeafPsiElement; +import org.jetbrains.jet.lang.psi.JetBlockExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetWhenEntry; +import org.jetbrains.jet.lang.psi.JetWhenExpression; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.ArrayList; +import java.util.List; + +/** + * Originally from IDEA platform: StatementGroupSelectioner + */ +public class JetStatementGroupSelectioner extends BasicSelectioner { + public boolean canSelect(PsiElement e) { + return e instanceof JetExpression || e instanceof JetWhenEntry; + } + + public List select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) { + List result = new ArrayList(); + + PsiElement parent = e.getParent(); + + if (!(parent instanceof JetBlockExpression) && !(parent instanceof JetWhenExpression)) { + return result; + } + + + PsiElement startElement = e; + PsiElement endElement = e; + + + while (startElement.getPrevSibling() != null) { + PsiElement sibling = startElement.getPrevSibling(); + + if (sibling instanceof LeafPsiElement) { + if (((LeafPsiElement) sibling).getElementType() == JetTokens.LBRACE) { + break; + } + } + + if (sibling instanceof PsiWhiteSpace) { + PsiWhiteSpace whiteSpace = (PsiWhiteSpace) sibling; + + String[] strings = LineTokenizer.tokenize(whiteSpace.getText().toCharArray(), false); + if (strings.length > 2) { + break; + } + } + + startElement = sibling; + } + + while (startElement instanceof PsiWhiteSpace) { + startElement = startElement.getNextSibling(); + } + + while (endElement.getNextSibling() != null) { + PsiElement sibling = endElement.getNextSibling(); + + if (sibling instanceof LeafPsiElement) { + if (((LeafPsiElement) sibling).getElementType() == JetTokens.RBRACE) { + break; + } + } + + if (sibling instanceof PsiWhiteSpace) { + PsiWhiteSpace whiteSpace = (PsiWhiteSpace) sibling; + + String[] strings = LineTokenizer.tokenize(whiteSpace.getText().toCharArray(), false); + if (strings.length > 2) { + break; + } + } + + endElement = sibling; + } + + while (endElement instanceof PsiWhiteSpace) { + endElement = endElement.getPrevSibling(); + } + + result.addAll(expandToWholeLine(editorText, new TextRange(startElement.getTextRange().getStartOffset(), + endElement.getTextRange().getEndOffset()))); + + return result; + } +}