diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml
index fcf1d2f2146d..0e4bbe658265 100644
--- a/java/java-impl/src/META-INF/JavaPlugin.xml
+++ b/java/java-impl/src/META-INF/JavaPlugin.xml
@@ -987,6 +987,10 @@
com.intellij.codeInsight.intention.impl.BreakStringOnLineBreaksIntentionAction
Java/Strings
+
+ com.intellij.codeInsight.intention.impl.SplitRawStringIntentionAction
+ Java/Strings
+
com.intellij.codeInsight.intention.impl.ReplaceCastWithVariableAction
Java/Imports
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitRawStringIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitRawStringIntentionAction.java
new file mode 100644
index 000000000000..b37b76ea5aa2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitRawStringIntentionAction.java
@@ -0,0 +1,86 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.codeInsight.intention.impl;
+
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+public class SplitRawStringIntentionAction extends PsiElementBaseIntentionAction {
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
+ if (!(element instanceof PsiJavaToken)) {
+ return false;
+ }
+
+ final PsiJavaToken token = (PsiJavaToken)element;
+
+ if (token.getTokenType() != JavaTokenType.RAW_STRING_LITERAL) {
+ return false;
+ }
+
+ final String text = token.getText();
+ if (text == null) {
+ return false;
+ }
+
+ int leadingTicsSequence = PsiRawStringLiteralUtil.getLeadingTicsSequence(text);
+ int trailingTicsSequence = PsiRawStringLiteralUtil.getTrailingTicsSequence(text);
+ if (leadingTicsSequence == trailingTicsSequence) {
+ int offset = editor.getCaretModel().getOffset();
+ int caretInTokenIdx = offset - token.getTextOffset();
+ if (caretInTokenIdx > leadingTicsSequence &&
+ offset < token.getTextRange().getEndOffset() - trailingTicsSequence &&
+ text.charAt(caretInTokenIdx) != '`' &&
+ text.charAt(caretInTokenIdx - 1) != '`') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+ if (!(element instanceof PsiJavaToken)) {
+ return;
+ }
+
+ final PsiJavaToken token = (PsiJavaToken)element;
+
+ if (token.getTokenType() != JavaTokenType.RAW_STRING_LITERAL) {
+ return;
+ }
+
+
+ final String text = token.getText();
+ if (text == null) {
+ return;
+ }
+
+ int ticsSequenceLength = PsiRawStringLiteralUtil.getLeadingTicsSequence(text);
+ String breakSequence = StringUtil.repeat("`", ticsSequenceLength);
+
+ int offset = editor.getCaretModel().getOffset();
+ int splitIdx = offset - token.getTextOffset();
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+ PsiBinaryExpression concatenation =
+ (PsiBinaryExpression)token.getParent().replace(factory.createExpressionFromText(text.substring(0, splitIdx) + breakSequence + " + " +
+ breakSequence + text.substring(splitIdx), element));
+ editor.getCaretModel().moveToOffset(concatenation.getOperationSign().getTextOffset());
+ }
+
+ @NotNull
+ @Override
+ public String getText() {
+ return getFamilyName();
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Split raw string literal";
+ }
+}
diff --git a/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/after.java.template b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/after.java.template
new file mode 100644
index 000000000000..f0f6d121b227
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/after.java.template
@@ -0,0 +1 @@
+String s = ```Hello, ``` + ```world!```;
\ No newline at end of file
diff --git a/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/before.java.template b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/before.java.template
new file mode 100644
index 000000000000..f74b3af6c8a4
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/before.java.template
@@ -0,0 +1 @@
+String s = ```Hello, world!```;
\ No newline at end of file
diff --git a/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/description.html b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/description.html
new file mode 100644
index 000000000000..f6182e73603f
--- /dev/null
+++ b/java/java-impl/src/intentionDescriptions/SplitRawStringIntentionAction/description.html
@@ -0,0 +1,5 @@
+
+
+This intention allows to break raw string literal into 2 parts at caret position.
+
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.after.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.after.java
new file mode 100644
index 000000000000..e7eb78860c68
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.after.java
@@ -0,0 +1,5 @@
+class Test {
+ {
+ String s = ```ab``` + ```c```;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.java
new file mode 100644
index 000000000000..f9f6d8170dfb
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteral.java
@@ -0,0 +1,5 @@
+class Test {
+ {
+ String s = ```abc```;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteralDisabledOnTic.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteralDisabledOnTic.java
new file mode 100644
index 000000000000..b2701608c305
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advRawStringLiteral/SplitRawStringLiteralDisabledOnTic.java
@@ -0,0 +1,5 @@
+class Test {
+ {
+ String s = ```ab`c```;
+ }
+}
\ 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 bafd7b302717..cccfa6dd8d82 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
@@ -40,9 +40,7 @@ public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCa
public void testStringToRawTransformation() { doTestIntention(QuickFixBundle.message("convert.to.raw.string.text")); }
public void testStringToRawTransformationWithWrongSeparators() { doTestIntention(QuickFixBundle.message("convert.to.raw.string.text")); }
- public void testStringToRawTransformationLeadingTics() {
- doTestIntention(QuickFixBundle.message("convert.to.raw.string.text"));
- }
+ public void testStringToRawTransformationLeadingTics() { doTestIntention(QuickFixBundle.message("convert.to.raw.string.text")); }
public void testStringToRawTransformationOnlyTics() {
myFixture.configureByFile(getTestName(false) + ".java");
@@ -53,6 +51,12 @@ public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCa
doTestIntention(QuickFixBundle.message("convert.to.raw.string.text"));
}
+ public void testSplitRawStringLiteral() { doTestIntention("Split raw string literal"); }
+ public void testSplitRawStringLiteralDisabledOnTic() {
+ myFixture.configureByFile(getTestName(false) + ".java");
+ assertEmpty(myFixture.filterAvailableIntentions("Split raw string literal"));
+ }
+
public void testPasteInRawStringLiteral() {
doTestPaste("class A {{String s = `q`;}}", "a\nb`\nc", "class A {{String s = ``qa\nb`\nc``;}}");
}