PY-10972 Recursively detect the alignment owner for the new block on enter

by properly implementing Block.isIncomplete() for collection literals,
comprehensions and parenthesized expressions instead of hand-written
search for the preceding expression lacking the closing bracket.
This commit is contained in:
Mikhail Golubev
2018-04-04 17:49:34 +03:00
parent 1145384502
commit dbf49edb14
8 changed files with 40 additions and 16 deletions

View File

@@ -891,7 +891,6 @@ public class PyBlock implements ASTBlock {
@NotNull
public ChildAttributes getChildAttributes(int newChildIndex) {
int statementListsBelow = 0;
PyBlock incompleteAlignedBlock = null;
if (newChildIndex > 0) {
// always pass decision to a sane block from top level from file or definition
@@ -936,19 +935,6 @@ public class PyBlock implements ASTBlock {
}
lastChild = getLastNonSpaceChild(lastChild, true);
}
if ((prevElt instanceof PySequenceExpression || prevElt instanceof PyComprehensionElement) &&
prevElt.getLastChild() instanceof PsiErrorElement) {
incompleteAlignedBlock = insertAfterBlock;
}
else if (prevElt instanceof PyParenthesizedExpression && prevElt.getLastChild() instanceof PsiErrorElement) {
final PyExpression contained = ((PyParenthesizedExpression)prevElt).getContainedExpression();
// In case of parenthesized string literal we can use both the alignment of the containing parenthesized expression
// and the literal itself, since it's not clear whether user is going to insert another string node or the closing parenthesis
if (contained instanceof PyTupleExpression || contained instanceof PyStringLiteralExpression) {
incompleteAlignedBlock = insertAfterBlock.getSubBlockByNode(contained.getNode());
}
}
}
// HACKETY-HACK
@@ -973,7 +959,7 @@ public class PyBlock implements ASTBlock {
final Indent childIndent = getChildIndent(newChildIndex);
final Alignment childAlignment = incompleteAlignedBlock != null ? incompleteAlignedBlock.getChildAlignment() : getChildAlignment();
final Alignment childAlignment = getChildAlignment();
return new ChildAttributes(childIndent, childAlignment);
}
@@ -1140,7 +1126,7 @@ public class PyBlock implements ASTBlock {
final PyArgumentList argumentList = (PyArgumentList)myNode.getPsi();
return argumentList.getClosingParen() == null;
}
if (isIncompleteCall(myNode)) {
if (isIncompleteCall(myNode) || isIncompleteExpressionWithBrackets(myNode.getPsi())) {
return true;
}
@@ -1158,6 +1144,14 @@ public class PyBlock implements ASTBlock {
return false;
}
private static boolean isIncompleteExpressionWithBrackets(@NotNull PsiElement elem) {
if (elem instanceof PySequenceExpression || elem instanceof PyComprehensionElement || elem instanceof PyParenthesizedExpression) {
return PyTokenTypes.OPEN_BRACES.contains(elem.getFirstChild().getNode().getElementType()) &&
!PyTokenTypes.CLOSE_BRACES.contains(elem.getLastChild().getNode().getElementType());
}
return false;
}
@Override
public boolean isLeaf() {
return myNode.getFirstChildNode() == null;

View File

@@ -0,0 +1,3 @@
x3 = ('foo'
('bar'
'baz'

View File

@@ -0,0 +1,2 @@
x3 = ('foo'
('bar'<caret>

View File

@@ -0,0 +1,3 @@
x3 = ['foo',
['bar',
'baz'

View File

@@ -0,0 +1,2 @@
x3 = ['foo',
['bar',<caret>

View File

@@ -0,0 +1,3 @@
x3 = ('foo',
('bar',
'baz'

View File

@@ -0,0 +1,2 @@
x3 = ('foo',
('bar',<caret>

View File

@@ -642,4 +642,19 @@ public class PyEditingTest extends PyTestCase {
public void testEnterInIncompleteParenthesizedGenerator() {
doTypingTest("\nfoo");
}
// PY-10972
public void testEnterInIncompleteNestedListLiteral() {
doTypingTest("\n'baz'");
}
// PY-10972
public void testEnterInIncompleteNestedTupleLiteral() {
doTypingTest("\n'baz'");
}
// PY-10972
public void testEnterInIncompleteNestedGluedStringInParentheses() {
doTypingTest("\n'baz'");
}
}