blob: a9c0e5f62668ea9c70622471f56fa2e23436b4a9 [file] [log] [blame]
/*
* Copyright 2000-2014 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.plugins.groovy.editor.selection;
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
import com.intellij.codeInsight.editorActions.SelectWordUtil;
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.tree.IElementType;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
import java.util.ArrayList;
import java.util.List;
/**
* @author Maxim.Medvedev
*/
public class GroovyGStringSelectioner extends ExtendWordSelectionHandlerBase {
@Override
public boolean canSelect(PsiElement e) {
PsiElement parent = e.getParent();
return parent instanceof GrStringInjection || parent instanceof GrString;
}
@Override
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
List<TextRange> ranges = super.select(e, editorText, cursorOffset, editor);
PsiElement parent = e.getParent();
if (parent instanceof GrString) {
final TextRange selection =
new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd());
TextRange range = getLineTextRange(e, cursorOffset);
ranges.add(range);
if (selection.contains(range)) {
PsiElement firstChild = parent.getFirstChild();
PsiElement lastChild = parent.getLastChild();
if (firstChild.getNode().getElementType() == GroovyTokenTypes.mGSTRING_BEGIN) {
firstChild = firstChild.getNextSibling();
}
if (lastChild.getNode().getElementType() == GroovyTokenTypes.mGSTRING_END) {
lastChild = lastChild.getPrevSibling();
}
if (firstChild != null && lastChild != null) {
range = new TextRange(firstChild.getTextOffset(), lastChild.getTextOffset() + lastChild.getTextLength());
ranges.add(range);
}
if (selection.contains(range) || firstChild == null || lastChild == null) {
ranges.add(parent.getTextRange());
}
}
}
else if (parent instanceof GrStringInjection) {
if (e instanceof GrReferenceExpression) {
List<TextRange> r = new ArrayList<TextRange>(2);
SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, r);
for (TextRange textRange : r) {
if (editorText.charAt(textRange.getStartOffset()) == '$') {
textRange = new TextRange(textRange.getStartOffset() + 1, textRange.getEndOffset());
}
ranges.add(textRange);
}
}
ranges.add(parent.getTextRange());
ranges.add(e.getTextRange());
}
return ranges;
}
private static TextRange getLineTextRange(PsiElement e, int cursorOffset) {
assert e.getParent() instanceof GrString;
PsiElement next = e;
int startOffset = cursorOffset;
int endOffset = cursorOffset;
if (e.getNode().getElementType() == GroovyTokenTypes.mGSTRING_CONTENT) {
final String text = e.getText();
int cur;
int index = -1;
while (true) {
cur = text.indexOf('\n', index + 1);
if (cur < 0 || cur + e.getTextOffset() > cursorOffset) break;
index = cur;
}
if (index >= 0) {
startOffset = e.getTextOffset() + index + 1;
}
index = text.indexOf('\n', cursorOffset - e.getTextOffset());
if (index >= 0) {
endOffset = e.getTextOffset() + index + 1;
}
}
if (startOffset == cursorOffset) {
do {
if (next == null) break;
final ASTNode node = next.getNode();
if (node == null) break;
final IElementType type = node.getElementType();
if (type == GroovyTokenTypes.mGSTRING_BEGIN) break;
if (type == GroovyElementTypes.GSTRING_CONTENT) {
final int i = next.getText().lastIndexOf('\n');
if (i >= 0) {
startOffset = next.getTextOffset() + i + 1;
break;
}
}
startOffset = next.getTextOffset();
next = next.getPrevSibling();
}
while (true);
}
if (endOffset == cursorOffset) {
next = e;
do {
if (next == null) break;
final ASTNode node = next.getNode();
if (node == null) break;
final IElementType type = node.getElementType();
if (type == GroovyTokenTypes.mGSTRING_END) {
endOffset = next.getTextOffset();
break;
}
if (type == GroovyElementTypes.GSTRING_CONTENT) {
final int i = next.getText().indexOf('\n');
if (i >= 0) {
endOffset = next.getTextOffset() + i + 1;
break;
}
}
endOffset = next.getTextOffset() + next.getTextLength();
next = next.getNextSibling();
}
while (true);
}
return new TextRange(startOffset, endOffset);
}
}