2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.groovy.editor.selection;
18 import com.intellij.codeInsight.editorActions.SelectWordUtil;
19 import com.intellij.lang.ASTNode;
20 import com.intellij.openapi.editor.Editor;
21 import com.intellij.openapi.util.TextRange;
22 import com.intellij.psi.PsiElement;
23 import com.intellij.psi.tree.IElementType;
24 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
25 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
26 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
28 import java.util.ArrayList;
29 import java.util.List;
31 import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
34 * @author Maxim.Medvedev
36 public class GroovyGStringSelectioner extends GroovyBasicSelectioner {
37 public boolean canSelect(PsiElement e) {
38 PsiElement parent = e.getParent();
39 return parent instanceof GrStringInjection || parent instanceof GrString;
43 public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
44 List<TextRange> ranges = new ArrayList<TextRange>();
45 PsiElement parent = e.getParent();
47 if (parent instanceof GrString) {
48 final TextRange selection =
49 new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd());
51 TextRange range = getLineTextRange(e, cursorOffset);
53 if (selection.contains(range)) {
55 PsiElement firstChild = parent.getFirstChild();
56 PsiElement lastChild = parent.getLastChild();
57 if (firstChild.getNode().getElementType() == mGSTRING_BEGIN) {
58 firstChild = firstChild.getNextSibling();
60 if (lastChild.getNode().getElementType() == mGSTRING_END) {
61 lastChild = lastChild.getPrevSibling();
64 if (firstChild != null && lastChild != null) {
65 range = new TextRange(firstChild.getTextOffset(), lastChild.getTextOffset() + lastChild.getTextLength());
69 if (selection.contains(range) || firstChild == null || lastChild == null) {
70 ranges.add(parent.getTextRange());
74 else if (parent instanceof GrStringInjection) {
75 if (e instanceof GrReferenceExpression) {
76 List<TextRange> r = new ArrayList<TextRange>(2);
77 SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, r);
78 for (TextRange textRange : r) {
79 if (editorText.charAt(textRange.getStartOffset()) == '$') {
80 textRange = new TextRange(textRange.getStartOffset() + 1, textRange.getEndOffset());
82 ranges.add(textRange);
86 ranges.add(parent.getTextRange());
87 ranges.add(e.getTextRange());
93 private static TextRange getLineTextRange(PsiElement e, int cursorOffset) {
94 assert e.getParent() instanceof GrString;
97 int startOffset = cursorOffset;
98 int endOffset = cursorOffset;
99 if (e.getNode().getElementType() == mGSTRING_CONTENT) {
100 final String text = e.getText();
104 cur = text.indexOf('\n', index + 1);
105 if (cur < 0 || cur + e.getTextOffset() > cursorOffset) break;
109 startOffset = e.getTextOffset() + index + 1;
112 index = text.indexOf('\n', cursorOffset - e.getTextOffset());
114 endOffset = e.getTextOffset() + index + 1;
118 if (startOffset == cursorOffset) {
120 if (next == null) break;
121 final ASTNode node = next.getNode();
122 if (node == null) break;
123 final IElementType type = node.getElementType();
124 if (type == mGSTRING_BEGIN) break;
125 if (type == mGSTRING_CONTENT) {
126 final int i = next.getText().lastIndexOf('\n');
128 startOffset = next.getTextOffset() + i + 1;
132 startOffset = next.getTextOffset();
133 next = next.getPrevSibling();
138 if (endOffset == cursorOffset) {
141 if (next == null) break;
142 final ASTNode node = next.getNode();
143 if (node == null) break;
145 final IElementType type = node.getElementType();
146 if (type == mGSTRING_END) {
147 endOffset = next.getTextOffset();
150 if (type == mGSTRING_CONTENT) {
151 final int i = next.getText().indexOf('\n');
153 endOffset = next.getTextOffset() + i + 1;
157 endOffset = next.getTextOffset() + next.getTextLength();
158 next = next.getNextSibling();
163 return new TextRange(startOffset, endOffset);