diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertToFStringIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertToFStringIntention.java index d0d53a9a3791..e4e14704cd90 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertToFStringIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertToFStringIntention.java @@ -148,13 +148,17 @@ public class PyConvertToFStringIntention extends PyBaseIntentionAction { // Nest string contain the same type of quote as host string inside, and we cannot escape inside f-string -- retreat final String content = info.getContent(); final char targetSingleQuote = flipQuote(hostQuote); - if (content.indexOf(hostQuote) >= 0 || content.indexOf(targetSingleQuote) >= 0) { + if (content.indexOf(hostQuote) >= 0) { return null; } if (!info.isTerminated()) { return null; } - if (info.getSingleQuote() == hostQuote) { + if (info.getQuote().startsWith(hostInfo.getQuote())) { + if (content.indexOf(targetSingleQuote) >= 0) { + return null; + } + final String targetQuote = info.getQuote().replace(hostQuote, targetSingleQuote); final String stringWithSwappedQuotes = info.getPrefix() + targetQuote + content + targetQuote; final PsiElement replaced = literal.replace(generator.createStringLiteralAlreadyEscaped(stringWithSwappedQuotes)); diff --git a/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString.py b/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString.py new file mode 100644 index 000000000000..e7f8502e160d --- /dev/null +++ b/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString.py @@ -0,0 +1,3 @@ +''' +%s +''' % '"' \ No newline at end of file diff --git a/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString_after.py b/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString_after.py new file mode 100644 index 000000000000..f90c6bae17fd --- /dev/null +++ b/python/testData/intentions/PyConvertToFStringIntentionTest/percentOperatorInlineSingleQuotedStringInsideTripleQuotedString_after.py @@ -0,0 +1,3 @@ +f''' +{'"'} +''' \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/intentions/PyConvertToFStringIntentionTest.java b/python/testSrc/com/jetbrains/python/intentions/PyConvertToFStringIntentionTest.java index bdf6ecb08a0b..e79bbb1958f6 100644 --- a/python/testSrc/com/jetbrains/python/intentions/PyConvertToFStringIntentionTest.java +++ b/python/testSrc/com/jetbrains/python/intentions/PyConvertToFStringIntentionTest.java @@ -120,6 +120,10 @@ public class PyConvertToFStringIntentionTest extends PyIntentionTestCase { doTest(); } + public void testPercentOperatorInlineSingleQuotedStringInsideTripleQuotedString() { + doTest(); + } + public void testExtractItemAndAttributeAccess() { assertSameElements(PyConvertToFStringIntention.extractItemsAndAttributes("{0.foo.bar.baz}"), ".foo", ".bar", ".baz"); assertSameElements(PyConvertToFStringIntention.extractItemsAndAttributes("{0[foo][.!:][}]}"), "[foo]", "[.!:]", "[}]");