mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-8989 Support raw strings in "Convert triple-quoted to single-quoted" intention
This commit is contained in:
+64
-17
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -75,23 +76,18 @@ public class PyConvertTripleQuotedStringIntention extends BaseIntentionAction {
|
||||
if (docStringOwner.getDocStringExpression() == string) return false;
|
||||
}
|
||||
|
||||
boolean insideTripleQuotedString = false;
|
||||
for (StringNodeInfo info : extractStringNodesInfo(string)) {
|
||||
// Can't handle triple quoted raw strings: there is no obvious way to insert linefeed or escape quote inside them
|
||||
if (StringUtil.containsIgnoreCase(info.prefix, "r") && info.isTripleQuoted) {
|
||||
return false;
|
||||
}
|
||||
if (info.isTripleQuoted && info.node.getTextRange().contains(caretOffset)) {
|
||||
insideTripleQuotedString = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return insideTripleQuotedString;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) throws IncorrectOperationException {
|
||||
final PyStringLiteralExpression pyString = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyStringLiteralExpression.class);
|
||||
final PyStringLiteralExpression pyString = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()),
|
||||
PyStringLiteralExpression.class);
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
if (pyString != null) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
@@ -107,15 +103,64 @@ public class PyConvertTripleQuotedStringIntention extends BaseIntentionAction {
|
||||
|
||||
final boolean inLastNode = i == nodeInfos.size() - 1;
|
||||
for (int j = 0; j < lines.size(); j++) {
|
||||
|
||||
final String line = lines.get(j);
|
||||
final boolean inLastLine = j == lines.size() - 1;
|
||||
result.append(info.prefix);
|
||||
result.append(info.quote);
|
||||
result.append(convertToValidSubString(lines.get(j), info.quote, info.isTripleQuoted));
|
||||
if (!inLastLine || lastLineExcluded) {
|
||||
result.append("\\n");
|
||||
|
||||
if (StringUtil.containsIgnoreCase(info.prefix, "r")) {
|
||||
boolean singleQuoteUsed = false, doubleQuoteUsed = false;
|
||||
int chunkStart = 0;
|
||||
boolean firstChunk = true;
|
||||
for (int k = 0; k < line.length(); k++) {
|
||||
if (line.charAt(k) == '\'') {
|
||||
singleQuoteUsed = true;
|
||||
if (doubleQuoteUsed) {
|
||||
if (!firstChunk) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(info.prefix).append('\'').append(line.substring(chunkStart, k)).append('\'');
|
||||
chunkStart = k;
|
||||
doubleQuoteUsed = false;
|
||||
firstChunk = false;
|
||||
}
|
||||
}
|
||||
else if (line.charAt(k) == '"') {
|
||||
doubleQuoteUsed = true;
|
||||
if (singleQuoteUsed) {
|
||||
if (!firstChunk) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(info.prefix).append('"').append(line.substring(chunkStart, k)).append('"');
|
||||
chunkStart = k;
|
||||
singleQuoteUsed = false;
|
||||
firstChunk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!firstChunk) {
|
||||
result.append(" ");
|
||||
}
|
||||
if (singleQuoteUsed) {
|
||||
result.append(info.prefix).append('"').append(line.substring(chunkStart)).append('"');
|
||||
}
|
||||
else if (doubleQuoteUsed) {
|
||||
result.append(info.prefix).append('\'').append(line.substring(chunkStart)).append('\'');
|
||||
}
|
||||
else {
|
||||
result.append(info.prefix).append(info.quote).append(line.substring(chunkStart)).append(info.quote);
|
||||
}
|
||||
if (!inLastLine || lastLineExcluded) {
|
||||
result.append(" ").append(info.quote).append("\\n").append(info.quote);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.append(info.prefix);
|
||||
result.append(info.quote);
|
||||
result.append(convertToValidSubString(line, info.quote, info.isTripleQuoted));
|
||||
if (!inLastLine || lastLineExcluded) {
|
||||
result.append("\\n");
|
||||
}
|
||||
result.append(info.quote);
|
||||
}
|
||||
result.append(info.quote);
|
||||
if (!(inLastNode && inLastLine)) {
|
||||
result.append("\n");
|
||||
}
|
||||
@@ -128,8 +173,10 @@ public class PyConvertTripleQuotedStringIntention extends BaseIntentionAction {
|
||||
PyExpression expression = elementGenerator.createExpressionFromText(LanguageLevel.forElement(pyString), result.toString());
|
||||
|
||||
final PsiElement parent = pyString.getParent();
|
||||
if ((parent instanceof PyParenthesizedExpression || parent instanceof PyTupleExpression)
|
||||
&& expression instanceof PyParenthesizedExpression) {
|
||||
if (expression instanceof PyParenthesizedExpression &&
|
||||
(parent instanceof PyParenthesizedExpression ||
|
||||
parent instanceof PyTupleExpression ||
|
||||
parent instanceof PyArgumentList && ArrayUtil.getFirstElement(((PyArgumentList)parent).getArguments()) == pyString)) {
|
||||
expression = ((PyParenthesizedExpression)expression).getContainedExpression();
|
||||
}
|
||||
if (expression != null) {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
S = r"""foo<caret>
|
||||
bar"""
|
||||
@@ -0,0 +1,6 @@
|
||||
S = (r'foo' '\n'
|
||||
r'double-only"' '\n'
|
||||
r"single-only'" '\n'
|
||||
r"mix'ed" r'"' '\n'
|
||||
"\r\n"
|
||||
r'one line')
|
||||
@@ -0,0 +1,7 @@
|
||||
S = (<caret>r'''foo
|
||||
double-only"
|
||||
single-only'
|
||||
mix'ed"
|
||||
'''
|
||||
"""\r\n"""
|
||||
r'one line')
|
||||
@@ -252,9 +252,8 @@ public class PyIntentionTest extends PyTestCase {
|
||||
}
|
||||
|
||||
// PY-8989
|
||||
public void testConvertTripleQuotedStringIsNotAvailableForRawStrings() {
|
||||
myFixture.configureByFile("intentions/" + getTestName(false) + ".py");
|
||||
assertEmpty(myFixture.filterAvailableIntentions(PyBundle.message("INTN.triple.quoted.string")));
|
||||
public void testConvertTripleQuotedStringRawStrings() {
|
||||
doTest(PyBundle.message("INTN.triple.quoted.string"));
|
||||
}
|
||||
|
||||
// PY-8989
|
||||
|
||||
Reference in New Issue
Block a user