mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
enter handler for strings
This commit is contained in:
@@ -16,15 +16,15 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.EditorHighlighterProvider;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeEditorHighlighterProviders;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.lang.Language;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,7 +50,7 @@ public class GroovyFileType extends LanguageFileType {
|
||||
public EditorHighlighter getEditorHighlighter(@Nullable Project project,
|
||||
@NotNull FileType fileType, @Nullable VirtualFile virtualFile,
|
||||
@NotNull EditorColorsScheme colors) {
|
||||
return new GroovyEditorHighlighter(colors, project, virtualFile);
|
||||
return new GroovyEditorHighlighter(colors);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+1
-3
@@ -20,8 +20,6 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.ex.util.LayerDescriptor;
|
||||
import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.highlighter.GroovyDocSyntaxHighlighter;
|
||||
import org.jetbrains.plugins.groovy.lang.groovydoc.parser.GroovyDocElementTypes;
|
||||
|
||||
@@ -30,7 +28,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.parser.GroovyDocElementTypes;
|
||||
*/
|
||||
public class GroovyEditorHighlighter extends LayeredLexerEditorHighlighter {
|
||||
|
||||
public GroovyEditorHighlighter(EditorColorsScheme scheme, Project project, VirtualFile virtualFile) {
|
||||
public GroovyEditorHighlighter(EditorColorsScheme scheme) {
|
||||
super(new GroovySyntaxHighlighter(), scheme);
|
||||
registerGroovydocHighlighter();
|
||||
}
|
||||
|
||||
+43
-25
@@ -33,15 +33,17 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.formatter.GeeseUtil;
|
||||
import org.jetbrains.plugins.groovy.formatter.GroovyCodeStyleSettings;
|
||||
import org.jetbrains.plugins.groovy.lang.editor.HandlerUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
@@ -152,9 +154,7 @@ public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
if (element == null || !GeeseUtil.isClosureRBrace(element)) return false;
|
||||
|
||||
element = GeeseUtil.getNextNonWhitespaceToken(element);
|
||||
if (element == null ||
|
||||
element.getNode().getElementType() != GroovyTokenTypes.mNLS ||
|
||||
StringUtil.countChars(element.getText(), '\n') > 1) {
|
||||
if (element == null || element.getNode().getElementType() != mNLS || StringUtil.countChars(element.getText(), '\n') > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -206,8 +206,10 @@ public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
|
||||
private static final TokenSet AFTER_DOLLAR = TokenSet.create(mLCURLY, mIDENT, mGSTRING_CONTENT, mDOLLAR, mGSTRING_END);
|
||||
|
||||
private static final TokenSet ALL_STRINGS =
|
||||
TokenSet.create(mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_BEGIN, mGSTRING_END, mGSTRING_CONTENT, mRCURLY, mIDENT, mDOLLAR);
|
||||
private static final TokenSet ALL_STRINGS = TokenSet
|
||||
.create(mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_BEGIN, mGSTRING_END, mGSTRING_CONTENT, mRCURLY, mIDENT, mDOLLAR, mREGEX_BEGIN,
|
||||
mREGEX_CONTENT, mREGEX_END, mDOLLAR_SLASH_REGEX_BEGIN, mDOLLAR_SLASH_REGEX_CONTENT, mDOLLAR_SLASH_REGEX_END, mREGEX_LITERAL,
|
||||
mDOLLAR_SLASH_REGEX_LITERAL);
|
||||
|
||||
private static final TokenSet BEFORE_DOLLAR = TokenSet.create(mGSTRING_BEGIN, mGSTRING_CONTENT);
|
||||
|
||||
@@ -222,7 +224,9 @@ public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
Project project = PlatformDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) return false;
|
||||
|
||||
PsiFile file = PsiManager.getInstance(project).findFile(FileDocumentManager.getInstance().getFile(editor.getDocument()));
|
||||
final VirtualFile vfile = FileDocumentManager.getInstance().getFile(editor.getDocument());
|
||||
assert vfile != null;
|
||||
PsiFile file = PsiManager.getInstance(project).findFile(vfile);
|
||||
|
||||
Document document = editor.getDocument();
|
||||
String fileText = document.getText();
|
||||
@@ -241,7 +245,14 @@ public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
if (mSTRING_LITERAL == node.getElementType()) {
|
||||
if (GroovyEditorActionUtil.isPlainStringLiteral(node)) {
|
||||
TextRange literalRange = stringElement.getTextRange();
|
||||
document.insertString(literalRange.getEndOffset(), "''");
|
||||
|
||||
//the case of print '\<caret>'
|
||||
if (fileText.charAt(caretOffset) == '\'' && caretOffset > 0 && fileText.charAt(caretOffset - 1) == '\\') {
|
||||
convertEndToMultiline(caretOffset, document, fileText);
|
||||
}
|
||||
else {
|
||||
convertEndToMultiline(literalRange.getEndOffset(), document, fileText);
|
||||
}
|
||||
document.insertString(literalRange.getStartOffset(), "''");
|
||||
editor.getCaretModel().moveToOffset(caretOffset + 2);
|
||||
EditorModificationUtil.insertStringAtCaret(editor, "\n");
|
||||
@@ -292,30 +303,37 @@ public class GroovyEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkStringApplicable(Editor editor, int caret) {
|
||||
final EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
|
||||
HighlighterIterator iteratorLeft = highlighter.createIterator(caret - 1);
|
||||
HighlighterIterator iteratorRight = highlighter.createIterator(caret);
|
||||
private static void convertEndToMultiline(int caretOffset, Document document, String fileText) {
|
||||
if (caretOffset < fileText.length() && fileText.charAt(caretOffset) == '\'' ||
|
||||
caretOffset > 0 && fileText.charAt(caretOffset - 1) == '\'') {
|
||||
document.insertString(caretOffset, "''");
|
||||
}
|
||||
else {
|
||||
document.insertString(caretOffset, "'''");
|
||||
}
|
||||
}
|
||||
|
||||
if (iteratorLeft != null && !(ALL_STRINGS.contains(iteratorLeft.getTokenType()))) {
|
||||
private static boolean checkStringApplicable(Editor editor, int caret) {
|
||||
final GroovyLexer lexer = new GroovyLexer();
|
||||
lexer.start(editor.getDocument().getText());
|
||||
|
||||
while (lexer.getTokenEnd() < caret) {
|
||||
lexer.advance();
|
||||
}
|
||||
final IElementType leftToken = lexer.getTokenType();
|
||||
if (lexer.getTokenEnd() <= caret) lexer.advance();
|
||||
final IElementType rightToken = lexer.getTokenType();
|
||||
|
||||
if (!(ALL_STRINGS.contains(leftToken))) {
|
||||
return false;
|
||||
}
|
||||
if (iteratorLeft != null &&
|
||||
BEFORE_DOLLAR.contains(iteratorLeft.getTokenType()) &&
|
||||
iteratorRight != null &&
|
||||
!AFTER_DOLLAR.contains(iteratorRight.getTokenType())) {
|
||||
if (BEFORE_DOLLAR.contains(leftToken) && !AFTER_DOLLAR.contains(rightToken)) {
|
||||
return false;
|
||||
}
|
||||
if (iteratorLeft != null &&
|
||||
EXPR_END.contains(iteratorLeft.getTokenType()) &&
|
||||
iteratorRight != null &&
|
||||
!AFTER_EXPR_END.contains(iteratorRight.getTokenType())) {
|
||||
if (EXPR_END.contains(leftToken) && !AFTER_EXPR_END.contains(rightToken)) {
|
||||
return false;
|
||||
}
|
||||
if (iteratorLeft != null &&
|
||||
STRING_END.contains(iteratorLeft.getTokenType()) &&
|
||||
iteratorRight != null &&
|
||||
!STRING_END.contains(iteratorRight.getTokenType())) {
|
||||
if (STRING_END.contains(leftToken) && !STRING_END.contains(rightToken)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
+1
-20
@@ -209,25 +209,6 @@ public class GroovyFoldingBuilder implements FoldingBuilder, GroovyElementTypes,
|
||||
return element.getText().endsWith("*/");
|
||||
}
|
||||
|
||||
private static boolean isWellEndedString(PsiElement element) {
|
||||
final String text = element.getText();
|
||||
|
||||
if (!text.endsWith("'''") && !text.endsWith("\"\"\"") && !text.endsWith("/") && !text.endsWith("/$")) return false;
|
||||
|
||||
|
||||
final IElementType type = element.getNode().getElementType();
|
||||
if (TokenSets.STRING_LITERAL_SET.contains(type)) return true;
|
||||
|
||||
final PsiElement lastChild = element.getLastChild();
|
||||
if (lastChild == null) return false;
|
||||
|
||||
final IElementType lastType = lastChild.getNode().getElementType();
|
||||
if (type == GSTRING) return lastType == mGSTRING_END;
|
||||
if (type == REGEX) return lastType == mREGEX_END || lastType == mDOLLAR_SLASH_REGEX_END;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isMultiline(PsiElement element) {
|
||||
String text = element.getText();
|
||||
return text.contains("\n") || text.contains("\r") || text.contains("\r\n");
|
||||
@@ -297,6 +278,6 @@ public class GroovyFoldingBuilder implements FoldingBuilder, GroovyElementTypes,
|
||||
node.getElementType().equals(GSTRING) ||
|
||||
node.getElementType().equals(REGEX)) &&
|
||||
isMultiline(node.getPsi()) &&
|
||||
isWellEndedString(node.getPsi());
|
||||
GrStringUtil.isWellEndedString(node.getPsi());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
|
||||
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
@@ -801,4 +803,23 @@ public class GrStringUtil {
|
||||
final IElementType elementType = literal.getFirstChild().getNode().getElementType();
|
||||
return elementType == mREGEX_LITERAL || elementType == mDOLLAR_SLASH_REGEX_LITERAL;
|
||||
}
|
||||
|
||||
public static boolean isWellEndedString(PsiElement element) {
|
||||
final String text = element.getText();
|
||||
|
||||
if (!text.endsWith("'''") && !text.endsWith("\"\"\"") && !text.endsWith("/") && !text.endsWith("/$")) return false;
|
||||
|
||||
|
||||
final IElementType type = element.getNode().getElementType();
|
||||
if (TokenSets.STRING_LITERAL_SET.contains(type)) return true;
|
||||
|
||||
final PsiElement lastChild = element.getLastChild();
|
||||
if (lastChild == null) return false;
|
||||
|
||||
final IElementType lastType = lastChild.getNode().getElementType();
|
||||
if (type == GroovyElementTypes.GSTRING) return lastType == mGSTRING_END;
|
||||
if (type == GroovyElementTypes.REGEX) return lastType == mREGEX_END || lastType == mDOLLAR_SLASH_REGEX_END;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -69,6 +69,9 @@ public class EnterActionTest extends GroovyFormatterTestCase {
|
||||
public void testGstring11() throws Throwable { doTest(); }
|
||||
public void testGstring12() throws Throwable { doTest(); }
|
||||
public void testGstring13() throws Throwable { doTest(); }
|
||||
public void testGstring14() throws Throwable { doTest(); }
|
||||
public void testGstring15() throws Throwable { doTest(); }
|
||||
public void testGstring16() throws Throwable { doTest(); }
|
||||
public void testGstring2() throws Throwable { doTest(); }
|
||||
public void testGstring3() throws Throwable { doTest(); }
|
||||
public void testGstring4() throws Throwable { doTest(); }
|
||||
@@ -85,6 +88,10 @@ public class EnterActionTest extends GroovyFormatterTestCase {
|
||||
public void testString4() throws Throwable { doTest(); }
|
||||
public void testString5() throws Throwable { doTest(); }
|
||||
public void testString6() throws Throwable { doTest(); }
|
||||
public void testString7() throws Throwable { doTest(); }
|
||||
public void testString8() throws Throwable { doTest(); }
|
||||
public void testString9() throws Throwable { doTest(); }
|
||||
public void testString10() throws Throwable { doTest(); }
|
||||
|
||||
def doTest(String before, String after) {
|
||||
myFixture.configureByText("a.groovy", before)
|
||||
@@ -287,7 +294,6 @@ foo {
|
||||
<caret>
|
||||
} }
|
||||
'''
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
"p<caret>\nreved $id medved"
|
||||
-----
|
||||
"""p
|
||||
<caret>\nreved $id medved"""
|
||||
@@ -0,0 +1,4 @@
|
||||
"p\<caret>nreved $id medved"
|
||||
-----
|
||||
"""p\
|
||||
<caret>nreved $id medved"""
|
||||
@@ -0,0 +1,4 @@
|
||||
"p\n<caret>reved $id medved"
|
||||
-----
|
||||
"""p\n
|
||||
<caret>reved $id medved"""
|
||||
@@ -0,0 +1,8 @@
|
||||
def cl = {
|
||||
print ('foo<caret>\n')
|
||||
}
|
||||
-----
|
||||
def cl = {
|
||||
print ('''foo
|
||||
<caret>\n''')
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
def cl = {
|
||||
print ('foo\<caret>')
|
||||
}
|
||||
-----
|
||||
def cl = {
|
||||
print ('''foo\
|
||||
<caret>''')
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
def cl = {
|
||||
print ('foo<caret>\')
|
||||
}
|
||||
-----
|
||||
def cl = {
|
||||
print ('''foo
|
||||
<caret>\')'''
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
def cl = {
|
||||
print ('foo\<caret>n')
|
||||
}
|
||||
-----
|
||||
def cl = {
|
||||
print ('''foo\
|
||||
<caret>n''')
|
||||
}
|
||||
Reference in New Issue
Block a user