convert raw literal to string intention (IDEA-189855)

This commit is contained in:
Anna.Kozlova
2018-04-13 16:57:14 +02:00
parent d2cf6479d5
commit 9bc349a38b
9 changed files with 121 additions and 13 deletions

View File

@@ -945,6 +945,10 @@
<className>com.intellij.codeInsight.daemon.impl.quickfix.ConvertToStringLiteralAction</className>
<category>Java/Strings</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.daemon.impl.quickfix.ConvertRawToStringLiteralAction</className>
<category>Java/Strings</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.InsertLiteralUnderscoresAction</className>
<category>Java/Numbers</category>

View File

@@ -0,0 +1,55 @@
// 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.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.editorActions.StringLiteralCopyPasteProcessor;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class ConvertRawToStringLiteralAction implements IntentionAction {
@NotNull
@Override
public String getText() {
return QuickFixBundle.message("convert.to.string.text");
}
@NotNull
@Override
public String getFamilyName() {
return "Convert raw to String literal";
}
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
return PsiUtil.isJavaToken(element, JavaTokenType.RAW_STRING_LITERAL);
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element != null && PsiUtil.isJavaToken(element, JavaTokenType.RAW_STRING_LITERAL)) {
PsiElement parent = element.getParent();
if (parent instanceof PsiLiteralExpressionImpl) {
String text = ((PsiLiteralExpressionImpl)parent).getRawString();
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiElement literalToken = elementFactory.createExpressionFromText("\"\"", file).getFirstChild();
String preprocessedValue = new StringLiteralCopyPasteProcessor().escapeAndSplit(text, literalToken);
CodeStyleManager.getInstance(project).reformat(
parent.replace(elementFactory.createExpressionFromText('\"' + preprocessedValue + '\"', null)));
}
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -132,19 +132,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
if (rawText != null && wasUnescaped(text, rawText.rawText)) return rawText.rawText;
if (isStringLiteral(token)) {
StringBuilder buffer = new StringBuilder(text.length());
@NonNls String breaker = getLineBreaker(token);
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
for (int i = 0; i < lines.length; i++) {
buffer.append(escapeCharCharacters(lines[i], token));
if (i != lines.length - 1) {
buffer.append(breaker);
}
else if (text.endsWith("\n")) {
buffer.append("\\n");
}
}
text = buffer.toString();
text = escapeAndSplit(text, token);
}
else if (isCharLiteral(token)) {
return escapeCharCharacters(text, token);
@@ -152,6 +140,23 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
return text;
}
public String escapeAndSplit(String text, PsiElement token) {
StringBuilder buffer = new StringBuilder(text.length());
@NonNls String breaker = getLineBreaker(token);
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
for (int i = 0; i < lines.length; i++) {
buffer.append(escapeCharCharacters(lines[i], token));
if (i != lines.length - 1) {
buffer.append(breaker);
}
else if (text.endsWith("\n")) {
buffer.append("\\n");
}
}
text = buffer.toString();
return text;
}
private static boolean wasUnescaped(String text, String originalText) {
try {
return new TextBlockTransferable(unescapeStringCharacters(originalText), Collections.emptyList(), null)

View File

@@ -0,0 +1,3 @@
String s = <spot>"</spot>raw<spot>\n"</spot> +
"string\n" +
"literal";

View File

@@ -0,0 +1,4 @@
String s = <spot>`</spot>raw
string
literal
<spot>`</spot>;

View File

@@ -0,0 +1,5 @@
<html>
<body>
This intention converts raw string literal into (multi-line) string literal.
</body>
</html>

View File

@@ -0,0 +1,8 @@
class A {
{
String s = "a\n" +
" symbol to escape: \"\\\" (slash)\n" +
" and something else as well\n" +
" ";
}
}

View File

@@ -0,0 +1,8 @@
class A {
{
String s = `a
symbol to escape: "\" (slash)
and somet<caret>hing else as well
`;
}
}

View File

@@ -2,6 +2,8 @@
package com.intellij.java.codeInsight.daemon;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElementFactory;
@@ -11,6 +13,8 @@ import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCase {
@Override
@@ -28,6 +32,10 @@ public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCa
doTestHighlighting();
}
public void testRawToStringTransformation() {
doTestIntention(QuickFixBundle.message("convert.to.string.text"));
}
public void testPasteInRawStringLiteral() {
doTestPaste("class A {{String s = `q<caret>`;}}", "a\nb`\nc", "class A {{String s = ``qa\nb`\nc``;}}");
}
@@ -70,6 +78,14 @@ public class LightAdvRawStringLiteralsTest extends LightCodeInsightFixtureTestCa
myFixture.checkResult(expectedDocumentText);
}
private void doTestIntention(final String hint) {
myFixture.configureByFile(getTestName(false) + ".java");
List<IntentionAction> actions = myFixture.filterAvailableIntentions(hint);
assertNotEmpty(actions);
myFixture.launchAction(actions.get(0));
myFixture.checkResultByFile(getTestName(false) + ".after.java");
}
private void performPaste() {
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_PASTE);
}