PsiElement (@NotNull PsiElement expression) { final PsiElement copied = expression.copy(); final char hostQuote = myNodeInfo.getSingleQuote(); final PyElementGenerator generator = PyElementGenerator.getInstance(myPyString.getProject()); final Collection<PyStringLiteralExpression> innerStrings = PsiTreeUtil.collectElementsOfType(copied, PyStringLiteralExpression.class); for (PyStringLiteralExpression literal : innerStrings) { final List<ASTNode> nodes = literal.getStringNodes(); // TODO figure out what to do with those if (nodes.size() > 1) { return copied; } final StringNodeInfo info = new StringNodeInfo(nodes.get(0)); // 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(); if (content.indexOf(hostQuote) >= 0) { return null; } if (!info.isTerminated()) { return null; } if (info.getQuote().startsWith(myNodeInfo.getQuote())) { final char targetSingleQuote = PyStringLiteralUtil.flipQuote(hostQuote); 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)); if (literal == copied) { return replaced; } } } return copied; }