mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-20785 Do not inject inside f-string fragments which contain named unicode escapes
We cannot decode them properly yet because JDK doesn't offer any analog of unicodedata.lookup() in Python.
This commit is contained in:
@@ -76,12 +76,14 @@ public class FStringParser {
|
||||
int bracesBalance = 0;
|
||||
char stringLiteralQuote = '\0';
|
||||
int quotesNum = 0;
|
||||
boolean containsNamedUnicodeEscape = false;
|
||||
|
||||
int offset = leftBraceOffset + 1;
|
||||
while (offset < myNodeContentRange.getEndOffset()) {
|
||||
// Actually they aren't allowed inside expression fragments, but we skip them anyway to prevent injection errors
|
||||
final int nextOffset = skipNamedUnicodeEscape(offset);
|
||||
if (offset != nextOffset) {
|
||||
containsNamedUnicodeEscape = true;
|
||||
offset = nextOffset;
|
||||
continue;
|
||||
}
|
||||
@@ -139,7 +141,7 @@ public class FStringParser {
|
||||
if (contentEndOffset == -1) {
|
||||
contentEndOffset = offset;
|
||||
}
|
||||
myFragments.add(new FragmentOffsets(leftBraceOffset, contentEndOffset, rightBraceOffset));
|
||||
myFragments.add(new FragmentOffsets(leftBraceOffset, contentEndOffset, rightBraceOffset, containsNamedUnicodeEscape));
|
||||
return offset;
|
||||
}
|
||||
|
||||
@@ -155,14 +157,16 @@ public class FStringParser {
|
||||
private final int myLeftBraceOffset;
|
||||
private final int myRightBraceOffset;
|
||||
private final int myContentEndOffset;
|
||||
private final boolean myContainsNamedUnicodeEscape;
|
||||
|
||||
public FragmentOffsets(int leftBraceOffset, int contentEndOffset, int rightBraceOffset) {
|
||||
private FragmentOffsets(int leftBraceOffset, int contentEndOffset, int rightBraceOffset, boolean escape) {
|
||||
assert contentEndOffset > leftBraceOffset;
|
||||
assert rightBraceOffset < 0 || (contentEndOffset <= rightBraceOffset && leftBraceOffset < rightBraceOffset);
|
||||
|
||||
myLeftBraceOffset = leftBraceOffset;
|
||||
myRightBraceOffset = rightBraceOffset;
|
||||
myContentEndOffset = contentEndOffset;
|
||||
myContainsNamedUnicodeEscape = escape;
|
||||
}
|
||||
|
||||
public int getLeftBraceOffset() {
|
||||
@@ -177,6 +181,10 @@ public class FStringParser {
|
||||
return myContentEndOffset;
|
||||
}
|
||||
|
||||
public boolean containsNamedUnicodeEscape() {
|
||||
return myContainsNamedUnicodeEscape;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextRange getContentRange() {
|
||||
return TextRange.create(myLeftBraceOffset + 1, myContentEndOffset);
|
||||
|
||||
@@ -46,6 +46,7 @@ public class PyFStringsInjector extends PyInjectorBase {
|
||||
for (ASTNode node : pyString.getStringNodes()) {
|
||||
final int relNodeOffset = node.getTextRange().getStartOffset() - pyString.getTextRange().getStartOffset();
|
||||
for (FragmentOffsets offsets : getInjectionRanges(node)) {
|
||||
if (offsets.containsNamedUnicodeEscape()) continue;
|
||||
registrar.startInjecting(PyDocstringLanguageDialect.getInstance());
|
||||
registrar.addPlace(null, null, pyString, offsets.getContentRange().shiftRight(relNodeOffset));
|
||||
registrar.doneInjecting();
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -97,4 +96,19 @@ public class PyFStringTest extends PyTestCase {
|
||||
doTestRanges("f'\\N{foo}\\N{}\\N{{{{{}{|42 + \\N{DIGIT ONE}|}'");
|
||||
doTestRanges("f'{|x|:\\N{DIGIT_ONE}}'");
|
||||
}
|
||||
|
||||
// PY-20785
|
||||
public void testUnicodeEscapeInsideExpressionFragment() {
|
||||
doTestUnicodeEscapeDetection("f'{\\N{FOO}}'", true);
|
||||
doTestUnicodeEscapeDetection("f'{\"\\N{FOO\"}'", true);
|
||||
doTestUnicodeEscapeDetection("f'{\"\\N{\"}'", true);
|
||||
doTestUnicodeEscapeDetection("f'{\"\\\\N{FOO}\"}'", false);
|
||||
}
|
||||
|
||||
private static void doTestUnicodeEscapeDetection(String fStringText, boolean expected) {
|
||||
final List<FragmentOffsets> fragments = FStringParser.parse(fStringText);
|
||||
assertSize(1, fragments);
|
||||
final FragmentOffsets offsets = fragments.get(0);
|
||||
assertEquals(expected, offsets.containsNamedUnicodeEscape());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user