From 5ff6f01db9d7b14bfdbd5c79be8996b4fa8aa781 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Tue, 17 Apr 2018 12:01:02 +0200 Subject: [PATCH] raw string literal: insert whitespace to avoid literal till end of file IDEA-190406 --- .../editorActions/JavaQuoteHandler.java | 24 ++++++++++++++++--- .../TypingOpeningTic.after.java | 5 ++++ .../advRawStringLiteral/TypingOpeningTic.java | 5 ++++ .../daemon/LightAdvRawStringLiteralsTest.java | 6 +++++ .../editorActions/MultiCharQuoteHandler.java | 10 ++++++++ .../editorActions/TypedHandler.java | 2 +- 6 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.after.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.java diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaQuoteHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaQuoteHandler.java index 41e27196bb90..23e265307d92 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaQuoteHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaQuoteHandler.java @@ -15,21 +15,23 @@ */ package com.intellij.codeInsight.editorActions; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author peter */ -public class JavaQuoteHandler extends SimpleTokenSetQuoteHandler implements JavaLikeQuoteHandler { +public class JavaQuoteHandler extends SimpleTokenSetQuoteHandler implements JavaLikeQuoteHandler, MultiCharQuoteHandler { private final TokenSet concatenatableStrings; public JavaQuoteHandler() { - super(JavaTokenType.STRING_LITERAL, JavaTokenType.CHARACTER_LITERAL); + super(JavaTokenType.STRING_LITERAL, JavaTokenType.CHARACTER_LITERAL, JavaTokenType.RAW_STRING_LITERAL); concatenatableStrings = TokenSet.create(JavaTokenType.STRING_LITERAL); } @@ -95,6 +97,21 @@ public class JavaQuoteHandler extends SimpleTokenSetQuoteHandler implements Java return element.getParent() instanceof PsiLiteralExpression && element.getParent().getParent() instanceof PsiReferenceExpression; } + @Nullable + @Override + public CharSequence getClosingQuote(HighlighterIterator iterator, int offset) { + if (isOpeningQuote(iterator, offset - 1) && iterator.getTokenType() == JavaTokenType.RAW_STRING_LITERAL) { + return " `"; + } + return null; + } + + @Override + public void insertString(Editor editor, int offset, CharSequence closingQuote) { + MultiCharQuoteHandler.super.insertString(editor, offset, closingQuote); + editor.getSelectionModel().setSelection(offset, offset + closingQuote.length() - 1); + } + public static boolean isAppropriateElementTypeForLiteralStatic(final IElementType tokenType) { return ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(tokenType) || tokenType == JavaTokenType.SEMICOLON @@ -103,6 +120,7 @@ public class JavaQuoteHandler extends SimpleTokenSetQuoteHandler implements Java || tokenType == JavaTokenType.RBRACKET || tokenType == JavaTokenType.RBRACE || tokenType == JavaTokenType.STRING_LITERAL - || tokenType == JavaTokenType.CHARACTER_LITERAL; + || tokenType == JavaTokenType.CHARACTER_LITERAL + || tokenType == JavaTokenType.RAW_STRING_LITERAL; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.after.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.after.java new file mode 100644 index 000000000000..f08573f9b607 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.after.java @@ -0,0 +1,5 @@ +class A { + { + String s = ` ` + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.java new file mode 100644 index 000000000000..bd10887251c0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/TypingOpeningTic.java @@ -0,0 +1,5 @@ +class A { + { + String s = + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvRawStringLiteralsTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvRawStringLiteralsTest.java index 1e918059c119..6c5a8915f943 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvRawStringLiteralsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvRawStringLiteralsTest.java @@ -90,6 +90,12 @@ public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCa assertEquals("abc", ((PsiLiteralExpressionImpl)rawStringLiteral).getRawString()); } + public void testTypingOpeningTic() { + myFixture.configureByFile(getTestName(false ) + ".java"); + myFixture.type('`'); + myFixture.checkResultByFile(getTestName(false) + ".after.java"); + } + private void doTestHighlighting() { myFixture.configureByFile(getTestName(false) + ".java"); myFixture.checkHighlighting(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MultiCharQuoteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MultiCharQuoteHandler.java index b42490d4944d..1f2364e62640 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MultiCharQuoteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MultiCharQuoteHandler.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.editorActions; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import org.jetbrains.annotations.Nullable; @@ -28,4 +29,13 @@ public interface MultiCharQuoteHandler extends QuoteHandler { */ @Nullable CharSequence getClosingQuote(HighlighterIterator iterator, int offset); + + /** + * Should insert closingQuote in the document. + * + * May select the inserted quote + */ + default void insertString(Editor editor, int offset, CharSequence closingQuote) { + editor.getDocument().insertString(offset, closingQuote); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java index 0beaccb365c7..682e56d67da5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -496,7 +496,7 @@ public class TypedHandler extends TypedActionHandlerBase { if (closingQuote != null && hasNonClosedLiterals(editor, quoteHandler, offset - 1)) { if (offset == document.getTextLength() || !Character.isUnicodeIdentifierPart(document.getCharsSequence().charAt(offset))) { //any better heuristic or an API? - document.insertString(offset, closingQuote); + ((MultiCharQuoteHandler)quoteHandler).insertString(editor, offset, closingQuote); return true; } }