mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
PY-59594 PEP 701: Make the intention for flipping string quotes aware of the syntax
(cherry picked from commit a62f78cfdee24eccf3fcf2d341807565f26d2fbd) IJ-MR-115763 GitOrigin-RevId: 059a289a9006d592a88a677137647c0660c68fc2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b3351b941e
commit
0d34a0e88f
@@ -11,6 +11,7 @@ import java.util.Collection;
|
|||||||
import static com.jetbrains.python.psi.PyUtil.as;
|
import static com.jetbrains.python.psi.PyUtil.as;
|
||||||
|
|
||||||
public final class PyQuotesUtil {
|
public final class PyQuotesUtil {
|
||||||
|
|
||||||
private PyQuotesUtil() {
|
private PyQuotesUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ public final class PyQuotesUtil {
|
|||||||
PyFormattedStringElement parentFString = PsiTreeUtil.getParentOfType(stringElement, PyFormattedStringElement.class, true,
|
PyFormattedStringElement parentFString = PsiTreeUtil.getParentOfType(stringElement, PyFormattedStringElement.class, true,
|
||||||
PyStatement.class);
|
PyStatement.class);
|
||||||
char targetQuote = PyStringLiteralUtil.flipQuote(stringElement.getQuote().charAt(0));
|
char targetQuote = PyStringLiteralUtil.flipQuote(stringElement.getQuote().charAt(0));
|
||||||
if (parentFString != null) {
|
if (parentFString != null && LanguageLevel.forElement(stringElement).isOlderThan(LanguageLevel.PYTHON312)) {
|
||||||
boolean parentFStringUsesTargetQuotes = parentFString.getQuote().equals(Character.toString(targetQuote));
|
boolean parentFStringUsesTargetQuotes = parentFString.getQuote().equals(Character.toString(targetQuote));
|
||||||
if (parentFStringUsesTargetQuotes) return false;
|
if (parentFStringUsesTargetQuotes) return false;
|
||||||
boolean conversionIntroducesBackslashEscapedQuote = stringElement.textContains(targetQuote);
|
boolean conversionIntroducesBackslashEscapedQuote = stringElement.textContains(targetQuote);
|
||||||
@@ -51,11 +52,17 @@ public final class PyQuotesUtil {
|
|||||||
processStringElementText(builder, stringElement.getText(), originalQuote);
|
processStringElementText(builder, stringElement.getText(), originalQuote);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
boolean fStringCanIncludeArbitraryStringLiterals = LanguageLevel.forElement(stringElement).isAtLeast(LanguageLevel.PYTHON312);
|
||||||
stringElement.acceptChildren(new PyRecursiveElementVisitor() {
|
stringElement.acceptChildren(new PyRecursiveElementVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitElement(@NotNull PsiElement element) {
|
public void visitElement(@NotNull PsiElement element) {
|
||||||
if (element instanceof PyStringElement) {
|
if (element instanceof PyStringElement) {
|
||||||
processStringElement(builder, (PyStringElement)element);
|
if (fStringCanIncludeArbitraryStringLiterals) {
|
||||||
|
builder.append(element.getText());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
processStringElement(builder, (PyStringElement)element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (PyTokenTypes.FSTRING_TOKENS.contains(element.getNode().getElementType())) {
|
else if (PyTokenTypes.FSTRING_TOKENS.contains(element.getNode().getElementType())) {
|
||||||
processStringElementText(builder, element.getText(), originalQuote);
|
processStringElementText(builder, element.getText(), originalQuote);
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f"<caret>foo{'bar'}baz"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f'<caret>foo{"bar"}baz'
|
||||||
@@ -1 +1 @@
|
|||||||
s = f'<caret>foo{"bar"}baz'
|
s = f'foo{'bar'}baz'
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
s = (f<caret>'{"foo"}'
|
||||||
|
f'{"bar"}'
|
||||||
|
f'{"baz"}')
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
s = (f"{'foo'}"
|
||||||
|
f"{'bar'}"
|
||||||
|
f"{'baz'}")
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
s = (f"{'foo'}"
|
s = (f"{"foo"}"
|
||||||
f"{'bar'}"
|
f"{"bar"}"
|
||||||
f"{'baz'}")
|
f"{"baz"}")
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f"""foo{'<caret>ba"r'}baz"""
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f"""foo{"ba\"r"}baz"""
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f"foo{'<caret>bar'}baz"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = f"foo{"bar"}baz"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = rf'f<caret>oo{"bar"}'
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
s = rf"f<caret>oo{'bar'}"
|
||||||
@@ -1 +1 @@
|
|||||||
s = rf"f<caret>oo{'bar'}"
|
s = rf"f<caret>oo{"bar"}"
|
||||||
|
|||||||
@@ -224,22 +224,37 @@ public class PyIntentionTest extends PyTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
|
public void testConvertingRawFStringQuotesBefore312() {
|
||||||
|
runWithLanguageLevel(LanguageLevel.PYTHON311, () -> doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-59594
|
||||||
public void testConvertingRawFStringQuotes() {
|
public void testConvertingRawFStringQuotes() {
|
||||||
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
public void testConvertingQuotesNotSuggestedForStringInsideFStringWithOppositeQuotes() {
|
public void testConvertingQuotesNotSuggestedForStringInsideFStringWithOppositeQuotesBefore312() {
|
||||||
doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
runWithLanguageLevel(LanguageLevel.PYTHON311, () -> doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-59594
|
||||||
|
public void testConvertingQuotesOfStringInsideFStringWithOppositeQuotes() {
|
||||||
|
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
public void testConvertingQuotesNotSuggestedForStringInsideFStringThatWouldRequireEscapingInsideFragment() {
|
public void testConvertingQuotesNotSuggestedForStringContainingQuotesOfParentFStringBefore312() {
|
||||||
doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
runWithLanguageLevel(LanguageLevel.PYTHON311, () -> doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-59594
|
||||||
|
public void testConvertingQuotesOfStringContainingQuotesOfParentFString() {
|
||||||
|
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
public void testConvertingQuotesNotSuggestedForFStringContainingStringWithInconvertibleQuotes() {
|
public void testConvertingQuotesNotSuggestedForFStringContainingTripleQuotedString() {
|
||||||
doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
doNegativeTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +264,11 @@ public class PyIntentionTest extends PyTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
|
public void testConvertingQuotesOfFStringContainingOtherStringsBefore312() {
|
||||||
|
runWithLanguageLevel(LanguageLevel.PYTHON311, () -> doTest(PyPsiBundle.message("INTN.quoted.string.double.to.single")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-59594
|
||||||
public void testConvertingQuotesOfFStringContainingOtherStrings() {
|
public void testConvertingQuotesOfFStringContainingOtherStrings() {
|
||||||
doTest(PyPsiBundle.message("INTN.quoted.string.double.to.single"));
|
doTest(PyPsiBundle.message("INTN.quoted.string.double.to.single"));
|
||||||
}
|
}
|
||||||
@@ -259,6 +279,11 @@ public class PyIntentionTest extends PyTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PY-30798
|
// PY-30798
|
||||||
|
public void testConvertingQuotesOfGluedFStringContainingOtherStringsBefore312() {
|
||||||
|
runWithLanguageLevel(LanguageLevel.PYTHON311, () -> doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PY-59594
|
||||||
public void testConvertingQuotesOfGluedFStringContainingOtherStrings() {
|
public void testConvertingQuotesOfGluedFStringContainingOtherStrings() {
|
||||||
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
doTest(PyPsiBundle.message("INTN.quoted.string.single.to.double"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user