mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-31442 Handle f-strings terminated by other string literals in fragments
When the terminating quote is either at the beginning of a string literal or inside it, either in the given f-string itself or inside a nested one and either in normal fragment or in a fragment located inside a format part of another fragment. Normal string literals and nested f-strings are also checked separately.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ package com.jetbrains.python.lexer;
|
||||
|
||||
import com.intellij.lexer.FlexLexer;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.intellij.util.containers.ContainerUtil;import com.jetbrains.python.PyTokenTypes;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.jetbrains.python.psi.PyStringLiteralUtil;
|
||||
@@ -136,10 +136,7 @@ boolean hasMatchingFStringStart(String endQuotes){
|
||||
if (endQuotes.startsWith(state.quotes)){
|
||||
final int nestedNum = fStringStates.size() - i;
|
||||
for(int j = 0; j < nestedNum; j++) {
|
||||
final FStringState removedFString = fStringStates.pop();
|
||||
while (!fragmentStates.isEmpty() && fragmentStates.peek().containingFString == removedFString) {
|
||||
fragmentStates.pop();
|
||||
}
|
||||
popFString();
|
||||
}
|
||||
yybegin(state.oldState);
|
||||
final int unmatchedQuotes = endQuotes.length() - state.quotes.length();
|
||||
@@ -150,6 +147,47 @@ boolean hasMatchingFStringStart(String endQuotes){
|
||||
return false;
|
||||
}
|
||||
|
||||
private void popFString() {
|
||||
final FStringState removedFString = fStringStates.pop();
|
||||
while (!fragmentStates.isEmpty() && fragmentStates.peek().containingFString == removedFString) {
|
||||
fragmentStates.pop();
|
||||
}
|
||||
}
|
||||
|
||||
IElementType findFStringEndInStringLiteral(String stringLiteral, IElementType stringType){
|
||||
int i = 0;
|
||||
while(i < stringLiteral.length()) {
|
||||
final char c = stringLiteral.charAt(i);
|
||||
if (c == '\\') {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
final int prefixLength = PyStringLiteralUtil.getPrefixLength(stringLiteral);
|
||||
final String nextThree = stringLiteral.substring(i, Math.min(stringLiteral.length(), i + 3));
|
||||
for(int j = fStringStates.size() - 1; j >= 0; j--) {
|
||||
final FStringState state = fStringStates.get(j);
|
||||
if (nextThree.startsWith(state.quotes)){
|
||||
if (i == 0) {
|
||||
final int nestedNum = fStringStates.size() - j;
|
||||
for(int k = 0; k < nestedNum; k++) {
|
||||
popFString();
|
||||
}
|
||||
yybegin(state.oldState);
|
||||
final int unmatched = stringLiteral.length() - state.quotes.length();
|
||||
yypushback(unmatched);
|
||||
return PyTokenTypes.FSTRING_END;
|
||||
}
|
||||
else {
|
||||
yypushback(stringLiteral.length() - i);
|
||||
return i == prefixLength ? PyTokenTypes.IDENTIFIER : stringType;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return stringType;
|
||||
}
|
||||
|
||||
private final Stack<FragmentState> fragmentStates = new Stack<>();
|
||||
private final Stack<FStringState> fStringStates = new Stack<>();
|
||||
|
||||
@@ -194,6 +232,9 @@ return yylength()-s.length();
|
||||
":" { if (braceBalance == 0) { yybegin(FSTRING_FRAGMENT_FORMAT); return PyTokenTypes.FSTRING_FRAGMENT_FORMAT_START; }
|
||||
else { return PyTokenTypes.COLON; } }
|
||||
|
||||
{SINGLE_QUOTED_STRING} { return findFStringEndInStringLiteral(yytext().toString(), PyTokenTypes.SINGLE_QUOTED_STRING); }
|
||||
{TRIPLE_QUOTED_LITERAL} { return findFStringEndInStringLiteral(yytext().toString(), PyTokenTypes.TRIPLE_QUOTED_STRING); }
|
||||
|
||||
// Should be impossible inside expression fragments: any quotes should be matched as a string literal there
|
||||
{FSTRING_QUOTES} { return hasMatchingFStringStart(yytext().toString()) ? PyTokenTypes.FSTRING_END : PyTokenTypes.FSTRING_TEXT; }
|
||||
}
|
||||
@@ -324,7 +365,12 @@ return PyTokenTypes.DOCSTRING; }
|
||||
"=" { return PyTokenTypes.EQ; }
|
||||
";" { return PyTokenTypes.SEMICOLON; }
|
||||
|
||||
{FSTRING_START} { pushFString(); return PyTokenTypes.FSTRING_START; }
|
||||
{FSTRING_START} { IElementType type = findFStringEndInStringLiteral(yytext().toString(), PyTokenTypes.FSTRING_START);
|
||||
if (type == PyTokenTypes.FSTRING_START) {
|
||||
pushFString();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
[^] { return PyTokenTypes.BAD_CHARACTER; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideFStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }baz'
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PsiElement(Py:FSTRING_TEXT)('foo')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}baz'')
|
||||
@@ -0,0 +1,27 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideFStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }}'
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}}'')
|
||||
@@ -0,0 +1,37 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideNestedFStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"""')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected """
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}"')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('""')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiElement(Py:RBRACE)('}')
|
||||
PsiErrorElement:Statement expected, found Py:RBRACE
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''')
|
||||
+1
-1
@@ -1 +1 @@
|
||||
s = f'{f"""{42:f"'"}"""}'
|
||||
s = f'{f"""{42:{f"'"}}"""}'
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideNestedFStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }}
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"""')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected """
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}}"')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('""')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiElement(Py:RBRACE)('}')
|
||||
PsiErrorElement:Statement expected, found Py:RBRACE
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''')
|
||||
@@ -0,0 +1,34 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideNestedStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"""')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected """
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}"')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('""')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiElement(Py:RBRACE)('}')
|
||||
PsiErrorElement:Statement expected, found Py:RBRACE
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''')
|
||||
+1
-1
@@ -1 +1 @@
|
||||
s = f'{f"""{42:"'"}"""}'
|
||||
s = f'{f"""{42:{"'"}}"""}'
|
||||
@@ -0,0 +1,40 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideNestedStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }}
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"""')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected """
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}}"')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('""')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiElement(Py:RBRACE)('}')
|
||||
PsiErrorElement:Statement expected, found Py:RBRACE
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''')
|
||||
@@ -0,0 +1,19 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }baz'
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PsiElement(Py:FSTRING_TEXT)('foo')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}baz'')
|
||||
@@ -0,0 +1,24 @@
|
||||
PyFile:FStringTerminatedByQuoteInsideStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression: }}'
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('"}}'')
|
||||
@@ -0,0 +1,28 @@
|
||||
PyFile:FStringTerminatedByQuoteOfFStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PsiElement(Py:FSTRING_TEXT)('foo')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyReferenceExpression: f
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }baz
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}baz'')
|
||||
@@ -0,0 +1,33 @@
|
||||
PyFile:FStringTerminatedByQuoteOfFStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyReferenceExpression: f
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}}'')
|
||||
@@ -0,0 +1,34 @@
|
||||
PyFile:FStringTerminatedByQuoteOfNestedFStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyReferenceExpression: f
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }"}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}"}'')
|
||||
@@ -1 +1 @@
|
||||
s = f'{f"{42:f'foo'}"}'
|
||||
s = f'{f"{42:{f'foo'}}"}'
|
||||
@@ -0,0 +1,40 @@
|
||||
PyFile:FStringTerminatedByQuoteOfNestedFStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyReferenceExpression: f
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PsiErrorElement:type conversion, : or } expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }}"}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}}"}'')
|
||||
@@ -0,0 +1,32 @@
|
||||
PyFile:FStringTerminatedByQuoteOfNestedStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PsiErrorElement:expression expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }"}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}"}'')
|
||||
@@ -1 +1 @@
|
||||
s = f'{f"{42:'foo'}"}'
|
||||
s = f'{f"{42:{'foo'}}"}'
|
||||
@@ -0,0 +1,38 @@
|
||||
PyFile:FStringTerminatedByQuoteOfNestedStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f"')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PsiErrorElement:expression expected
|
||||
<empty list>
|
||||
PsiErrorElement:Expected "
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }}"}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}}"}'')
|
||||
@@ -0,0 +1,26 @@
|
||||
PyFile:FStringTerminatedByQuoteOfStringLiteral.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PsiElement(Py:FSTRING_TEXT)('foo')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PsiErrorElement:expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }baz
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}baz'')
|
||||
@@ -0,0 +1,31 @@
|
||||
PyFile:FStringTerminatedByQuoteOfStringLiteralInFormatPart.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: s
|
||||
PsiElement(Py:IDENTIFIER)('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStringLiteralExpression:
|
||||
PyFormattedStringNode
|
||||
PsiElement(Py:FSTRING_START)('f'')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PyFStringFragmentFormatPart
|
||||
PsiElement(Py:FSTRING_FRAGMENT_FORMAT_START)(':')
|
||||
PyFStringFragment
|
||||
PsiElement(Py:FSTRING_FRAGMENT_START)('{')
|
||||
PsiErrorElement:expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:FSTRING_END)(''')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyStringLiteralExpression: }}
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)(''}}'')
|
||||
Reference in New Issue
Block a user