mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
PY-42200 Support parenthesized context managers in Python 3.9+
In case of syntactic ambiguity with previous versions of the grammar, such as "with (expr)" or "with (expr1, expr2)", PyWithStatement is still parsed as having its own parentheses, not a parenthesized expression or a tuple as a single context expression. The latter case, even though syntactically legal, is still reported by the compatibility inspection in Python <3.9. These changes also include proper formatter and editing support (e.g. not inserting backslashes on line breaks inside parentheses), as well as Complete Current Statement, which now takes possible parentheses into account while inserting a missing colon. The changes in the formatter are somewhat ad-hoc, intended to minimize the effect on other constructs. "With" statement is somewhat special in the sense that it's the first compound statement (having a statement list) with its own list-like part in parentheses. Existing tests on with statement processing were expanded and uniformly named. Co-authored-by: Semyon Proshev <semyon.proshev@jetbrains.com> GitOrigin-RevId: 15c33e97f177e81b5ed23891063555df016feb05
This commit is contained in:
committed by
intellij-monorepo-bot
parent
379444cdda
commit
97b22aaa13
@@ -806,6 +806,7 @@ INSP.compatibility.old.dict.methods.not.available.in.py3=dict.iterkeys(), dict.i
|
||||
INSP.compatibility.basestring.type.not.available.in.py3=basestring type is not available in Python 3
|
||||
INSP.compatibility.new.union.syntax.not.available.in.earlier.version=allow writing union types as X | Y
|
||||
INSP.compatibility.feature.support.match.statements=support match statements
|
||||
INSP.compatibility.feature.support.parenthesized.context.expressions=support parenthesized context expressions
|
||||
|
||||
# PyUnnecessaryBackslashInspection
|
||||
INSP.NAME.unnecessary.backslash=Unnecessary backslash
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonCodeStyleService;
|
||||
@@ -74,7 +75,8 @@ public class PyBlock implements ASTBlock {
|
||||
PyElementTypes.FROM_IMPORT_STATEMENT,
|
||||
PyElementTypes.SEQUENCE_PATTERN,
|
||||
PyElementTypes.MAPPING_PATTERN,
|
||||
PyElementTypes.PATTERN_ARGUMENT_LIST);
|
||||
PyElementTypes.PATTERN_ARGUMENT_LIST,
|
||||
PyElementTypes.WITH_STATEMENT);
|
||||
|
||||
private static final boolean ALIGN_CONDITIONS_WITHOUT_PARENTHESES = false;
|
||||
|
||||
@@ -456,6 +458,18 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
|
||||
if (parentType == PyElementTypes.WITH_STATEMENT && isInsideWithStatementParentheses(myNode, child)) {
|
||||
if (needListAlignment(child)) {
|
||||
childAlignment = getAlignmentForChildren();
|
||||
}
|
||||
else {
|
||||
childIndent = Indent.getNormalIndent();
|
||||
}
|
||||
if (childType == PyTokenTypes.RPAR && !settings.HANG_CLOSING_BRACKETS) {
|
||||
childIndent = Indent.getNoneIndent();
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode prev = child.getTreePrev();
|
||||
while (prev != null && prev.getElementType() == TokenType.WHITE_SPACE) {
|
||||
if (prev.textContains('\\') &&
|
||||
@@ -475,6 +489,23 @@ public class PyBlock implements ASTBlock {
|
||||
return new PyBlock(this, child, childAlignment, childIndent, childWrap, myContext);
|
||||
}
|
||||
|
||||
private static boolean isInsideWithStatementParentheses(@NotNull ASTNode withStatement, @NotNull ASTNode node) {
|
||||
ASTNode openingParenthesis = withStatement.findChildByType(PyTokenTypes.LPAR);
|
||||
if (openingParenthesis == null) {
|
||||
return false;
|
||||
}
|
||||
if (node.getStartOffset() < openingParenthesis.getStartOffset()) {
|
||||
return false;
|
||||
}
|
||||
ASTNode closingParenthesis = withStatement.findChildByType(PyTokenTypes.RPAR);
|
||||
if (closingParenthesis != null) {
|
||||
return node.getStartOffset() <= closingParenthesis.getStartOffset();
|
||||
}
|
||||
ASTNode afterParentheses = ObjectUtils.chooseNotNull(withStatement.findChildByType(PyTokenTypes.COLON),
|
||||
withStatement.findChildByType(PyElementTypes.STATEMENT_LIST));
|
||||
return afterParentheses == null || node.getStartOffset() < afterParentheses.getStartOffset();
|
||||
}
|
||||
|
||||
private static boolean isIfCondition(@NotNull ASTNode node) {
|
||||
@NotNull PsiElement element = node.getPsi();
|
||||
final PyIfPart ifPart = as(element.getParent(), PyIfPart.class);
|
||||
@@ -556,6 +587,9 @@ public class PyBlock implements ASTBlock {
|
||||
if (elem instanceof PyFromImportStatement) {
|
||||
firstChild = ((PyFromImportStatement)elem).getLeftParen();
|
||||
}
|
||||
else if (elem instanceof PyWithStatement) {
|
||||
firstChild = PyPsiUtils.getFirstChildOfType(elem, PyTokenTypes.LPAR);
|
||||
}
|
||||
else {
|
||||
firstChild = elem.getFirstChild();
|
||||
}
|
||||
@@ -585,6 +619,10 @@ public class PyBlock implements ASTBlock {
|
||||
final PyExpression value = ((PyKeyValueExpression)firstItem).getValue();
|
||||
return value != null && hasHangingIndent(value);
|
||||
}
|
||||
else if (firstItem instanceof PyWithItem) {
|
||||
PyExpression contextExpression = ((PyWithItem)firstItem).getExpression();
|
||||
return contextExpression != null && hasHangingIndent(contextExpression);
|
||||
}
|
||||
return hasHangingIndent(firstItem);
|
||||
}
|
||||
}
|
||||
@@ -608,6 +646,9 @@ public class PyBlock implements ASTBlock {
|
||||
else if (elem instanceof PyFromImportStatement) {
|
||||
items = ((PyFromImportStatement)elem).getImportElements();
|
||||
}
|
||||
else if (elem instanceof PyWithStatement) {
|
||||
items = ((PyWithStatement)elem).getWithItems();
|
||||
}
|
||||
else if (elem instanceof PyParenthesizedExpression) {
|
||||
final PyExpression containedExpression = ((PyParenthesizedExpression)elem).getContainedExpression();
|
||||
if (containedExpression instanceof PyTupleExpression) {
|
||||
@@ -730,6 +771,9 @@ public class PyBlock implements ASTBlock {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (myNode.getElementType() == PyElementTypes.WITH_STATEMENT) {
|
||||
return myNode.findChildByType(PyTokenTypes.LPAR) != null && !hasHangingIndent(myNode.getPsi());
|
||||
}
|
||||
return myContext.getPySettings().ALIGN_COLLECTIONS_AND_COMPREHENSIONS && !hasHangingIndent(myNode.getPsi());
|
||||
}
|
||||
|
||||
@@ -968,6 +1012,21 @@ public class PyBlock implements ASTBlock {
|
||||
final ASTNode prevNode = insertAfterBlock.getNode();
|
||||
final PsiElement prevElt = prevNode.getPsi();
|
||||
|
||||
// TODO Use the same approach for other list-like constructs
|
||||
if (myNode.getElementType() == PyElementTypes.WITH_STATEMENT && isInsideWithStatementParentheses(myNode, prevNode)) {
|
||||
ASTNode openingParenthesis = myNode.findChildByType(PyTokenTypes.LPAR);
|
||||
for (int i = newChildIndex - 1; i >= 0 ; i--) {
|
||||
PyBlock prevBlock = mySubBlocks.get(i);
|
||||
if (prevBlock.myNode == openingParenthesis) {
|
||||
break;
|
||||
}
|
||||
if (prevBlock.getAlignment() != null) {
|
||||
return new ChildAttributes(Indent.getNormalIndent(), prevBlock.getAlignment());
|
||||
}
|
||||
}
|
||||
return new ChildAttributes(Indent.getNormalIndent(), null);
|
||||
}
|
||||
|
||||
// stmt lists, parts and definitions should also think for themselves
|
||||
if (prevElt instanceof PyStatementList) {
|
||||
if (dedentAfterLastStatement((PyStatementList)prevElt)) {
|
||||
@@ -1079,6 +1138,9 @@ public class PyBlock implements ASTBlock {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (elem instanceof PyWithStatement && PyPsiUtils.getFirstChildOfType(elem, PyTokenTypes.LPAR) == null) {
|
||||
return null;
|
||||
}
|
||||
return getAlignmentForChildren();
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -838,27 +838,68 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
private void parseWithStatement(SyntaxTreeBuilder.Marker endMarker) {
|
||||
assertCurrentToken(PyTokenTypes.WITH_KEYWORD);
|
||||
myBuilder.advanceLexer();
|
||||
while (true) {
|
||||
SyntaxTreeBuilder.Marker withItem = myBuilder.mark();
|
||||
if (!getExpressionParser().parseSingleExpression(false)) {
|
||||
if (!parseParenthesizedWithItems()) {
|
||||
if (!parseWithItems(false)) {
|
||||
myBuilder.error(PyPsiBundle.message("PARSE.expected.expression"));
|
||||
}
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.AS_KEYWORD) {
|
||||
myBuilder.advanceLexer();
|
||||
if (!getExpressionParser().parseSingleExpression(true)) {
|
||||
myBuilder.error(PyPsiBundle.message("PARSE.expected.identifier"));
|
||||
// 'as' is followed by a target
|
||||
}
|
||||
}
|
||||
withItem.done(PyElementTypes.WITH_ITEM);
|
||||
if (!matchToken(PyTokenTypes.COMMA)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
parseColonAndSuite();
|
||||
endMarker.done(PyElementTypes.WITH_STATEMENT);
|
||||
}
|
||||
|
||||
private boolean parseParenthesizedWithItems() {
|
||||
if (!atToken(PyTokenTypes.LPAR)) {
|
||||
return false;
|
||||
}
|
||||
final SyntaxTreeBuilder.Marker leftPar = myBuilder.mark();
|
||||
nextToken();
|
||||
// Reparse empty parentheses as an empty tuple
|
||||
if (!parseWithItems(true)) {
|
||||
leftPar.rollbackTo();
|
||||
return false;
|
||||
}
|
||||
if (!matchToken(PyTokenTypes.RPAR)) {
|
||||
myBuilder.error(PyPsiBundle.message("PARSE.expected.rpar"));
|
||||
}
|
||||
// Reparse something like "(foo()) as bar" or (foo()).bar as a single WithItem
|
||||
if (!atAnyOfTokens(PyTokenTypes.COLON, PyTokenTypes.STATEMENT_BREAK)) {
|
||||
leftPar.rollbackTo();
|
||||
return false;
|
||||
}
|
||||
leftPar.drop();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean parseWithItems(boolean insideParentheses) {
|
||||
if (!parseWithItem()) {
|
||||
return false;
|
||||
}
|
||||
while (matchToken(PyTokenTypes.COMMA)) {
|
||||
if (!parseWithItem()) {
|
||||
if (!insideParentheses) {
|
||||
myBuilder.error(PyPsiBundle.message("PARSE.expected.expression"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean parseWithItem() {
|
||||
SyntaxTreeBuilder.Marker withItem = myBuilder.mark();
|
||||
if (!getExpressionParser().parseSingleExpression(false)) {
|
||||
withItem.drop();
|
||||
return false;
|
||||
}
|
||||
if (matchToken(PyTokenTypes.AS_KEYWORD)) {
|
||||
if (!getExpressionParser().parseSingleExpression(true)) {
|
||||
myBuilder.error(PyPsiBundle.message("PARSE.expected.identifier"));
|
||||
}
|
||||
}
|
||||
withItem.done(PyElementTypes.WITH_ITEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseClassDeclaration() {
|
||||
final SyntaxTreeBuilder.Marker classMarker = myBuilder.mark();
|
||||
parseClassDeclaration(classMarker);
|
||||
|
||||
@@ -317,9 +317,33 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
@Override
|
||||
public void visitPyWithStatement(@NotNull PyWithStatement node) {
|
||||
super.visitPyWithStatement(node);
|
||||
checkParenthesizedWithItems(node);
|
||||
checkAsyncKeyword(node);
|
||||
}
|
||||
|
||||
private void checkParenthesizedWithItems(@NotNull PyWithStatement node) {
|
||||
final PsiElement lpar = PyPsiUtils.getFirstChildOfType(node, PyTokenTypes.LPAR);
|
||||
final PsiElement rpar = PyPsiUtils.getFirstChildOfType(node, PyTokenTypes.RPAR);
|
||||
if (lpar == null && rpar == null) {
|
||||
return;
|
||||
}
|
||||
// Context expressions such as "(foo(), bar())" or "(foo(),)" are valid in Python < 3.9, but most likely indicate an error anyway
|
||||
PyWithItem[] withItems = node.getWithItems();
|
||||
boolean canBeParsedAsSingleParenthesizedExpression = (
|
||||
withItems.length == 1 &&
|
||||
PyPsiUtils.getFirstChildOfType(withItems[0], PyTokenTypes.AS_KEYWORD) == null &&
|
||||
PyPsiUtils.getFirstChildOfType(node, PyTokenTypes.COMMA) == null
|
||||
);
|
||||
if (canBeParsedAsSingleParenthesizedExpression) {
|
||||
return;
|
||||
}
|
||||
for (PsiElement parenthesis : ContainerUtil.packNullables(lpar, rpar)) {
|
||||
registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON39) && registerForLanguageLevel(level),
|
||||
PyPsiBundle.message("INSP.compatibility.feature.support.parenthesized.context.expressions"),
|
||||
parenthesis);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyForStatement(@NotNull PyForStatement node) {
|
||||
super.visitPyForStatement(node);
|
||||
@@ -690,8 +714,8 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
|
||||
@Override
|
||||
public void visitPyMatchStatement(@NotNull PyMatchStatement matchStatement) {
|
||||
registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON310),
|
||||
PyPsiBundle.message("INSP.compatibility.feature.support.match.statements"),
|
||||
registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON310),
|
||||
PyPsiBundle.message("INSP.compatibility.feature.support.match.statements"),
|
||||
matchStatement.getFirstChild());
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,12 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.PyWithItem;
|
||||
import com.jetbrains.python.psi.PyWithStatement;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
@@ -38,34 +39,38 @@ public class PyWithFixer extends PyFixer<PyWithStatement> {
|
||||
|
||||
@Override
|
||||
public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException {
|
||||
final PsiElement colonToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
|
||||
final PsiElement withToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
|
||||
assert withToken != null;
|
||||
final Document document = editor.getDocument();
|
||||
if (colonToken == null && withToken != null) {
|
||||
int insertAt = withToken.getTextRange().getEndOffset();
|
||||
String textToInsert = ":";
|
||||
final PyWithItem lastItem = ArrayUtil.getLastElement(withStatement.getWithItems());
|
||||
if (lastItem == null || lastItem.getExpression() == null) {
|
||||
textToInsert = " :";
|
||||
processor.registerUnresolvedError(insertAt + 1);
|
||||
}
|
||||
else {
|
||||
final PyExpression expression = lastItem.getExpression();
|
||||
insertAt = expression.getTextRange().getEndOffset();
|
||||
final PsiElement asToken = PyPsiUtils.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
|
||||
if (asToken != null) {
|
||||
insertAt = asToken.getTextRange().getEndOffset();
|
||||
final PyExpression target = lastItem.getTarget();
|
||||
if (target != null) {
|
||||
insertAt = target.getTextRange().getEndOffset();
|
||||
}
|
||||
else {
|
||||
textToInsert = " :";
|
||||
processor.registerUnresolvedError(insertAt + 1);
|
||||
final PsiElement colonToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
|
||||
if (colonToken == null) {
|
||||
PsiElement closingParenthesis = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.RPAR);
|
||||
PyWithItem lastWithItem = ArrayUtil.getLastElement(withStatement.getWithItems());
|
||||
PsiElement rightmostElement = closingParenthesis != null ? closingParenthesis :
|
||||
lastWithItem != null ? lastWithItem :
|
||||
withToken;
|
||||
document.insertString(rightmostElement.getTextRange().getEndOffset(), ":");
|
||||
}
|
||||
|
||||
if (withStatement.getWithItems().length != 0) {
|
||||
for (PyWithItem withItem : withStatement.getWithItems()) {
|
||||
final PsiElement asToken = PyPsiUtils.getFirstChildOfType(withItem, PyTokenTypes.AS_KEYWORD);
|
||||
if (asToken != null && withItem.getTarget() == null) {
|
||||
int asKeywordEndOffset = asToken.getTextRange().getEndOffset();
|
||||
if (!(PsiTreeUtil.nextLeaf(asToken, true) instanceof PsiWhiteSpace)) {
|
||||
document.insertString(asKeywordEndOffset," ");
|
||||
}
|
||||
processor.registerUnresolvedError(asKeywordEndOffset + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
document.insertString(insertAt, textToInsert);
|
||||
}
|
||||
else {
|
||||
int withKeywordEndOffset = withToken.getTextRange().getEndOffset();
|
||||
if (!(PsiTreeUtil.nextLeaf(withToken, true) instanceof PsiWhiteSpace)) {
|
||||
document.insertString(withKeywordEndOffset, " ");
|
||||
processor.registerUnresolvedError(withKeywordEndOffset + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.documentation.docstrings.*;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -189,7 +190,8 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
// if we're in middle of typing, it's expected that we will have error elements
|
||||
}
|
||||
|
||||
if (inFromImportParentheses(statementBefore, nodeAtCaret.getTextRange().getStartOffset())) {
|
||||
final int offset = nodeAtCaret.getTextRange().getStartOffset();
|
||||
if (inFromImportParentheses(statementBefore, offset) || inWithItemsParentheses(statementBefore, offset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -314,6 +316,15 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean inWithItemsParentheses(@NotNull PsiElement statement, int offset) {
|
||||
if (!(statement instanceof PyWithStatement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement leftParen = PyPsiUtils.getFirstChildOfType(statement, PyTokenTypes.LPAR);
|
||||
return leftParen != null && offset >= leftParen.getTextRange().getEndOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result postProcessEnter(@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
with<caret>
|
||||
@@ -0,0 +1 @@
|
||||
with <caret>:
|
||||
@@ -0,0 +1 @@
|
||||
with (foo() as <caret>)
|
||||
@@ -0,0 +1 @@
|
||||
with (foo() as <caret>):
|
||||
@@ -0,0 +1,2 @@
|
||||
with (foo() as,
|
||||
bar())<caret>:
|
||||
@@ -0,0 +1,2 @@
|
||||
with (foo() as <caret>,
|
||||
bar()):
|
||||
@@ -0,0 +1,3 @@
|
||||
with (foo()<caret>,
|
||||
bar() as):
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
with (foo(),
|
||||
bar() as <caret>):
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
with (foo(),
|
||||
bar() as baz<caret>):
|
||||
@@ -0,0 +1,3 @@
|
||||
with (foo(),
|
||||
bar() as baz):
|
||||
<caret>
|
||||
@@ -0,0 +1 @@
|
||||
with (foo()<caret>)
|
||||
@@ -0,0 +1,2 @@
|
||||
with (foo()):
|
||||
<caret>
|
||||
@@ -0,0 +1,6 @@
|
||||
with (
|
||||
foo(),
|
||||
bar(),
|
||||
baz()
|
||||
):
|
||||
pass
|
||||
@@ -0,0 +1,6 @@
|
||||
with (
|
||||
foo(),
|
||||
bar(),
|
||||
baz()
|
||||
):
|
||||
pass
|
||||
13
python/testData/formatter/parenthesizedWithItems.py
Normal file
13
python/testData/formatter/parenthesizedWithItems.py
Normal file
@@ -0,0 +1,13 @@
|
||||
with (foo(),
|
||||
bar(),
|
||||
# comment
|
||||
baz()):
|
||||
pass
|
||||
|
||||
with (
|
||||
# comment
|
||||
foo(),
|
||||
bar(),
|
||||
baz()
|
||||
):
|
||||
pass
|
||||
@@ -0,0 +1,26 @@
|
||||
if (foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)):
|
||||
pass
|
||||
|
||||
while [foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)]:
|
||||
pass
|
||||
|
||||
with (foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)):
|
||||
pass
|
||||
@@ -0,0 +1,26 @@
|
||||
if (foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)):
|
||||
pass
|
||||
|
||||
while [foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)]:
|
||||
pass
|
||||
|
||||
with (foo(
|
||||
1,
|
||||
2
|
||||
), foo(
|
||||
3,
|
||||
4
|
||||
)):
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
with (foo() as bar,
|
||||
foo() as bar):
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
with (foo() as bar,
|
||||
foo() as bar):
|
||||
pass
|
||||
13
python/testData/formatter/parenthesizedWithItems_after.py
Normal file
13
python/testData/formatter/parenthesizedWithItems_after.py
Normal file
@@ -0,0 +1,13 @@
|
||||
with (foo(),
|
||||
bar(),
|
||||
# comment
|
||||
baz()):
|
||||
pass
|
||||
|
||||
with (
|
||||
# comment
|
||||
foo(),
|
||||
bar(),
|
||||
baz()
|
||||
):
|
||||
pass
|
||||
@@ -0,0 +1,17 @@
|
||||
with <warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">(</warning>
|
||||
foo() as baz,
|
||||
foo() as bar
|
||||
<warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">)</warning>:
|
||||
pass
|
||||
|
||||
with (foo()) as baz:
|
||||
pass
|
||||
|
||||
with (foo()):
|
||||
pass
|
||||
|
||||
with <warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">(</warning>foo(),<warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">)</warning>:
|
||||
pass
|
||||
|
||||
with <warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">(</warning>foo(), bar()<warning descr="Python versions 2.7, 3.5, 3.6, 3.7, 3.8 do not support parenthesized context expressions">)</warning>:
|
||||
pass
|
||||
@@ -1,2 +0,0 @@
|
||||
with open("") as :
|
||||
pass
|
||||
@@ -1,23 +0,0 @@
|
||||
PyFile:WithMissingID.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: open
|
||||
PyReferenceExpression: open
|
||||
PsiElement(Py:IDENTIFIER)('open')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyStringLiteralExpression:
|
||||
PsiElement(Py:SINGLE_QUOTED_STRING)('""')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -1,3 +0,0 @@
|
||||
from __future__ import with_statement
|
||||
with x as y:
|
||||
pass
|
||||
@@ -1,29 +0,0 @@
|
||||
PyFile:WithStatement.py
|
||||
PyFromImportStatement
|
||||
PsiElement(Py:FROM_KEYWORD)('from')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: __future__
|
||||
PsiElement(Py:IDENTIFIER)('__future__')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IMPORT_KEYWORD)('import')
|
||||
PsiWhiteSpace(' ')
|
||||
PyImportElement:with_statement
|
||||
PyReferenceExpression: with_statement
|
||||
PsiElement(Py:IDENTIFIER)('with_statement')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -1,2 +0,0 @@
|
||||
with x as y:
|
||||
pass
|
||||
@@ -1,17 +0,0 @@
|
||||
PyFile:WithStatement26.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -1 +0,0 @@
|
||||
with x as a, y as b: pass
|
||||
@@ -1,27 +0,0 @@
|
||||
PyFile:WithStatement31.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: a
|
||||
PsiElement(Py:IDENTIFIER)('a')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: b
|
||||
PsiElement(Py:IDENTIFIER)('b')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,11 @@
|
||||
with (foo).bar:
|
||||
pass
|
||||
|
||||
with (foo)(bar):
|
||||
pass
|
||||
|
||||
with (foo)[bar]:
|
||||
pass
|
||||
|
||||
with (foo) | bar:
|
||||
pass
|
||||
@@ -0,0 +1,80 @@
|
||||
PyFile:WithStatementContextExpressionStartsWithParenthesis.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: bar
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:DOT)('.')
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyReferenceExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PySubscriptionExpression
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:LBRACKET)('[')
|
||||
PyReferenceExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RBRACKET)(']')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyBinaryExpression
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:OR)('|')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,11 @@
|
||||
with foo(), foo():
|
||||
pass
|
||||
with foo(), \
|
||||
foo():
|
||||
pass
|
||||
with foo() as bar, foo():
|
||||
pass
|
||||
with foo(), foo() as bar():
|
||||
pass
|
||||
with foo() as bar, foo() as bar:
|
||||
pass
|
||||
@@ -0,0 +1,150 @@
|
||||
PyFile:WithStatementMultipleWithItemsWithoutParentheses.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' \')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyCallExpression: bar
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
16
python/testData/psi/WithStatementParenthesizedWithItems.py
Normal file
16
python/testData/psi/WithStatementParenthesizedWithItems.py
Normal file
@@ -0,0 +1,16 @@
|
||||
with (foo()):
|
||||
pass
|
||||
with (foo(),):
|
||||
pass
|
||||
with (foo() as bar):
|
||||
pass
|
||||
with (foo() as bar,):
|
||||
pass
|
||||
with (foo(), foo()):
|
||||
pass
|
||||
with (foo() as bar, foo()):
|
||||
pass
|
||||
with (foo(), foo() as bar):
|
||||
pass
|
||||
with (foo() as bar, foo() as baz):
|
||||
pass
|
||||
212
python/testData/psi/WithStatementParenthesizedWithItems.txt
Normal file
212
python/testData/psi/WithStatementParenthesizedWithItems.txt
Normal file
@@ -0,0 +1,212 @@
|
||||
PyFile:WithStatementParenthesizedWithItems.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: baz
|
||||
PsiElement(Py:IDENTIFIER)('baz')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,5 @@
|
||||
with foo(),:
|
||||
pass
|
||||
with foo() as bar,:
|
||||
pass
|
||||
|
||||
43
python/testData/psi/WithStatementRecoveryDanglingComma.txt
Normal file
43
python/testData/psi/WithStatementRecoveryDanglingComma.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
PyFile:WithStatementRecoveryDanglingComma.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,2 @@
|
||||
with ():
|
||||
pass
|
||||
@@ -0,0 +1,13 @@
|
||||
PyFile:WithStatementRecoveryEmptyParentheses.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyTupleExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,10 @@
|
||||
with (:
|
||||
pass
|
||||
with (foo():
|
||||
pass
|
||||
with (foo() as:
|
||||
pass
|
||||
with (foo() as bar:
|
||||
pass
|
||||
with ((foo() as bar):
|
||||
pass
|
||||
@@ -0,0 +1,101 @@
|
||||
PyFile:WithStatementRecoveryIncompleteParentheses.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiErrorElement:Unexpected expression syntax
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected expression syntax
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,6 @@
|
||||
with foo() as :
|
||||
pass
|
||||
with (foo() as ):
|
||||
pass
|
||||
with foo() as, foo():
|
||||
pass
|
||||
73
python/testData/psi/WithStatementRecoveryMissingAsName.txt
Normal file
73
python/testData/psi/WithStatementRecoveryMissingAsName.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
PyFile:WithStatementRecoveryMissingAsName.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
10
python/testData/psi/WithStatementRecoveryMissingColon.py
Normal file
10
python/testData/psi/WithStatementRecoveryMissingColon.py
Normal file
@@ -0,0 +1,10 @@
|
||||
with foo()
|
||||
pass
|
||||
with (foo())
|
||||
pass
|
||||
with (foo()).bar
|
||||
pass
|
||||
with foo() as
|
||||
pass
|
||||
with foo() as bar
|
||||
pass
|
||||
100
python/testData/psi/WithStatementRecoveryMissingColon.txt
Normal file
100
python/testData/psi/WithStatementRecoveryMissingColon.txt
Normal file
@@ -0,0 +1,100 @@
|
||||
PyFile:WithStatementRecoveryMissingColon.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyReferenceExpression: bar
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:DOT)('.')
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
2
python/testData/psi/WithStatementRecoveryNoWithItems.py
Normal file
2
python/testData/psi/WithStatementRecoveryNoWithItems.py
Normal file
@@ -0,0 +1,2 @@
|
||||
with:
|
||||
pass
|
||||
10
python/testData/psi/WithStatementRecoveryNoWithItems.txt
Normal file
10
python/testData/psi/WithStatementRecoveryNoWithItems.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
PyFile:WithStatementRecoveryNoWithItems.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
14
python/testData/psi/WithStatementWithItemsOwnParentheses.py
Normal file
14
python/testData/psi/WithStatementWithItemsOwnParentheses.py
Normal file
@@ -0,0 +1,14 @@
|
||||
with (foo()):
|
||||
pass
|
||||
with ((foo())):
|
||||
pass
|
||||
with (foo()), (foo()):
|
||||
pass
|
||||
with (foo()) as bar:
|
||||
pass
|
||||
with ((foo()) as bar):
|
||||
pass
|
||||
with (bar := foo()):
|
||||
pass
|
||||
with (bar := foo()) as bar:
|
||||
pass
|
||||
175
python/testData/psi/WithStatementWithItemsOwnParentheses.txt
Normal file
175
python/testData/psi/WithStatementWithItemsOwnParentheses.txt
Normal file
@@ -0,0 +1,175 @@
|
||||
PyFile:WithStatementWithItemsOwnParentheses.py
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyAssignmentExpression
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:COLONEQ)(':=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiWhiteSpace('\n')
|
||||
PyWithStatement
|
||||
PsiElement(Py:WITH_KEYWORD)('with')
|
||||
PsiWhiteSpace(' ')
|
||||
PyWithItem
|
||||
PyParenthesizedExpression
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyAssignmentExpression
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:COLONEQ)(':=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyCallExpression: foo
|
||||
PyReferenceExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AS_KEYWORD)('as')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: bar
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -897,6 +897,121 @@ public class PyEditingTest extends PyTestCase {
|
||||
doTypingTest('\n');
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsEnterBeforeExistingItem() {
|
||||
doTestEnter("with (<caret>foo() as baz,\n" +
|
||||
" foo() as bar\n" +
|
||||
"):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar\n" +
|
||||
"):\n" +
|
||||
" pass");
|
||||
|
||||
doTestEnter("with (\n" +
|
||||
" foo() as baz,<caret>foo() as bar\n" +
|
||||
"):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar\n" +
|
||||
"):\n" +
|
||||
" pass");
|
||||
|
||||
doTestEnter("with (foo() as baz,<caret>foo() as bar):\n" +
|
||||
" pass",
|
||||
"with (foo() as baz,\n" +
|
||||
" foo() as bar):\n" +
|
||||
" pass");
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsEnterBeforeClosingParenthesis() {
|
||||
doTestEnter("with (foo(), \n" +
|
||||
" foo()<caret>):\n" +
|
||||
" pass",
|
||||
"with (foo(), \n" +
|
||||
" foo()\n" +
|
||||
" <caret>):\n" +
|
||||
" pass");
|
||||
|
||||
getPythonCodeStyleSettings().HANG_CLOSING_BRACKETS = false;
|
||||
doTestEnter("with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar<caret>):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar\n" +
|
||||
"):\n" +
|
||||
" pass");
|
||||
|
||||
getPythonCodeStyleSettings().HANG_CLOSING_BRACKETS = true;
|
||||
doTestEnter("with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar<caret>):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo() as baz,\n" +
|
||||
" foo() as bar\n" +
|
||||
" ):\n" +
|
||||
" pass");
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsEnterBeforeNonExistingItem() {
|
||||
doTestEnter("with (foo(),<caret>\n" +
|
||||
" bar()):\n" +
|
||||
" pass",
|
||||
"with (foo(),\n" +
|
||||
" <caret>\n" +
|
||||
" bar()):\n" +
|
||||
" pass");
|
||||
|
||||
doTestEnter("with (\n" +
|
||||
" foo(),<caret>\n" +
|
||||
" bar()\n" +
|
||||
"):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo(),\n" +
|
||||
" <caret>\n" +
|
||||
" bar()\n" +
|
||||
"):\n" +
|
||||
" pass");
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsEnterBeforeComment() {
|
||||
doTestEnter("with (\n" +
|
||||
" foo(),<caret># comment\n" +
|
||||
" bar()\n" +
|
||||
"):\n" +
|
||||
" pass",
|
||||
"with (\n" +
|
||||
" foo(),\n" +
|
||||
" <caret># comment\n" +
|
||||
" bar()\n" +
|
||||
"):\n" +
|
||||
" pass");
|
||||
|
||||
doTestEnter("with (foo(),<caret># comment\n" +
|
||||
" bar()):\n" +
|
||||
" pass",
|
||||
"with (foo(),\n" +
|
||||
" <caret># comment\n" +
|
||||
" bar()):\n" +
|
||||
" pass");
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsEnterBeforeStatementList() {
|
||||
doTestEnter("with (foo(), foo()):<caret>",
|
||||
"with (foo(), foo()):\n" +
|
||||
" <caret>");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PyCodeStyleSettings getPythonCodeStyleSettings() {
|
||||
return getCodeStyleSettings().getCustomSettings(PyCodeStyleSettings.class);
|
||||
|
||||
@@ -1217,4 +1217,26 @@ public class PyFormatterTest extends PyTestCase {
|
||||
getPythonCodeStyleSettings().SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT = true;
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItems() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testHangingClosingBracketInParenthesizedWithItems() {
|
||||
getPythonCodeStyleSettings().HANG_CLOSING_BRACKETS = true;
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsHangingIndentProcessedSimilarlyToCollectionsInStatementHeaders() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItemsWrapping() {
|
||||
getCodeStyleSettings().setRightMargin(PythonLanguage.getInstance(), 20);
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,11 +328,40 @@ public class PySmartEnterTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWithExpressionMissingNoSpaceAfterWithKeyword() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-12877
|
||||
public void testWithOnlyColonMissing() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithParenthesizedWithItemsOnlyColonMissing() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithParenthesizedWithItemsColonMissingAndTargetIncomplete() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithParenthesizedWithItemsFirstTargetIncomplete() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithParenthesizedWithItemsLastTargetIncomplete() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithParenthesizedWithItemsNothingToFix() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-9209
|
||||
public void testSpaceInsertedAfterHashSignInComment() {
|
||||
doTest();
|
||||
|
||||
@@ -61,6 +61,11 @@ public class PyCompatibilityInspectionTest extends PyInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testParenthesizedWithItems() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testPrintStatement() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -105,10 +105,6 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWithStatement() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDecoratedFunction() {
|
||||
doTest();
|
||||
}
|
||||
@@ -117,10 +113,6 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWithStatement26() {
|
||||
doTest(LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
public void testPrintAsFunction26() {
|
||||
doTest(LanguageLevel.PYTHON26);
|
||||
}
|
||||
@@ -205,10 +197,6 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWithStatement31() {
|
||||
doTest(LanguageLevel.PYTHON34);
|
||||
}
|
||||
|
||||
public void testLongString() {
|
||||
doTest();
|
||||
}
|
||||
@@ -421,10 +409,6 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testWithMissingID() { // PY-9853
|
||||
doTest(LanguageLevel.PYTHON27);
|
||||
}
|
||||
|
||||
public void testOverIndentedComment() { // PY-1909
|
||||
doTest();
|
||||
}
|
||||
@@ -1196,6 +1180,51 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithStatementParenthesizedWithItems() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
// PY-43505
|
||||
public void testWithStatementMultipleWithItemsWithoutParentheses() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithStatementWithItemsOwnParentheses() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
// PY-42200
|
||||
public void testWithStatementContextExpressionStartsWithParenthesis() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testWithStatementRecoveryDanglingComma() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testWithStatementRecoveryIncompleteParentheses() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testWithStatementRecoveryMissingColon() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testWithStatementRecoveryEmptyParentheses() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
// PY-9853
|
||||
public void testWithStatementRecoveryMissingAsName() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void testWithStatementRecoveryNoWithItems() {
|
||||
doTest(LanguageLevel.getLatest());
|
||||
}
|
||||
|
||||
public void doTest() {
|
||||
doTest(LanguageLevel.PYTHON26);
|
||||
}
|
||||
@@ -1227,6 +1256,4 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
functionToCheck.getStatementList(); //To make sure each function has statement list (does not throw exception)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user