diff --git a/python/src/com/jetbrains/python/validation/FStringsAnnotator.java b/python/src/com/jetbrains/python/validation/FStringsAnnotator.java index f6f61fa049b9..1b62624c7c18 100644 --- a/python/src/com/jetbrains/python/validation/FStringsAnnotator.java +++ b/python/src/com/jetbrains/python/validation/FStringsAnnotator.java @@ -17,6 +17,7 @@ package com.jetbrains.python.validation; import com.google.common.collect.Lists; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; @@ -24,6 +25,7 @@ import com.jetbrains.python.psi.PyFStringFragment; import com.jetbrains.python.psi.PyFStringFragmentFormatPart; import com.jetbrains.python.psi.PyFormattedStringElement; import com.jetbrains.python.psi.PyStringLiteralExpression; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -75,6 +77,11 @@ public class FStringsAnnotator extends PyAnnotator { for (TextRange textRange : node.getLiteralPartRanges()) { int i = textRange.getStartOffset(); while (i < textRange.getEndOffset()) { + final int nextOffset = skipNamedUnicodeEscape(wholeNodeText, i, textRange.getEndOffset()); + if (i != nextOffset) { + i = nextOffset; + continue; + } final char c = wholeNodeText.charAt(i); if (c == '}') { if (i + 1 < textRange.getEndOffset() && wholeNodeText.charAt(i + 1) == '}') { @@ -88,6 +95,14 @@ public class FStringsAnnotator extends PyAnnotator { } } + private static int skipNamedUnicodeEscape(@NotNull String nodeText, int offset, int endOffset) { + if (StringUtil.startsWith(nodeText, offset, "\\N{")) { + final int rightBraceOffset = nodeText.indexOf('}', offset + 3); + return rightBraceOffset < 0 ? endOffset : rightBraceOffset + 1; + } + return offset; + } + @Override public void visitComment(PsiComment comment) { final boolean insideFragment = PsiTreeUtil.getParentOfType(comment, PyFStringFragment.class) != null; diff --git a/python/testData/highlighting/fStringSingleRightBraces.py b/python/testData/highlighting/fStringSingleRightBraces.py index b1039c46d476..00549e982a8e 100644 --- a/python/testData/highlighting/fStringSingleRightBraces.py +++ b/python/testData/highlighting/fStringSingleRightBraces.py @@ -3,4 +3,5 @@ f'{x}{y}}' f'{x}}}}' f'{x:{y}}}' f'{x:{y}}}}' -f'{"}":{"}"}}' \ No newline at end of file +f'{"}":{"}"}}' +f'\N{FOO BAR}' \ No newline at end of file