PY-15874 Closing brackets in comprehensions are positioned according to "hang_closing" setting

This commit is contained in:
Mikhail Golubev
2017-01-13 11:58:33 +03:00
parent ad6582b62e
commit 5e888e75a7
6 changed files with 128 additions and 17 deletions
@@ -49,10 +49,10 @@ import static com.jetbrains.python.psi.PyUtil.as;
public class PyBlock implements ASTBlock {
private static final TokenSet ourListElementTypes = TokenSet.create(PyElementTypes.LIST_LITERAL_EXPRESSION,
PyElementTypes.LIST_COMP_EXPRESSION,
PyElementTypes.DICT_COMP_EXPRESSION,
PyElementTypes.SET_COMP_EXPRESSION,
PyElementTypes.DICT_LITERAL_EXPRESSION,
PyElementTypes.DICT_COMP_EXPRESSION,
PyElementTypes.SET_LITERAL_EXPRESSION,
PyElementTypes.SET_COMP_EXPRESSION,
PyElementTypes.ARGUMENT_LIST,
PyElementTypes.PARAMETER_LIST,
PyElementTypes.TUPLE_EXPRESSION,
@@ -66,8 +66,11 @@ public class PyBlock implements ASTBlock {
PyTokenTypes.LBRACKET, PyTokenTypes.RBRACKET);
private static final TokenSet ourHangingIndentOwners = TokenSet.create(PyElementTypes.LIST_LITERAL_EXPRESSION,
PyElementTypes.LIST_COMP_EXPRESSION,
PyElementTypes.DICT_LITERAL_EXPRESSION,
PyElementTypes.DICT_COMP_EXPRESSION,
PyElementTypes.SET_LITERAL_EXPRESSION,
PyElementTypes.SET_COMP_EXPRESSION,
PyElementTypes.ARGUMENT_LIST,
PyElementTypes.PARAMETER_LIST,
PyElementTypes.TUPLE_EXPRESSION,
@@ -315,9 +318,9 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.GENERATOR_EXPRESSION || parentType == PyElementTypes.PARENTHESIZED_EXPRESSION) {
final boolean insideTuple = parentType == PyElementTypes.PARENTHESIZED_EXPRESSION &&
myNode.getPsi(PyParenthesizedExpression.class).getContainedExpression() instanceof PyTupleExpression;
if ((childType == PyTokenTypes.RPAR && !(insideTuple && settings.HANG_CLOSING_BRACKETS)) ||
final boolean tupleOrGenerator = parentType == PyElementTypes.GENERATOR_EXPRESSION ||
myNode.getPsi(PyParenthesizedExpression.class).getContainedExpression() instanceof PyTupleExpression;
if ((childType == PyTokenTypes.RPAR && !(tupleOrGenerator && settings.HANG_CLOSING_BRACKETS)) ||
!hasLineBreaksBeforeInSameParent(child, 1)) {
childIndent = Indent.getNoneIndent();
}
@@ -471,12 +474,11 @@ public class PyBlock implements ASTBlock {
if (hasLineBreakAfterIgnoringComments(firstChildNode)) {
return true;
}
final PsiElement[] items = getItems(elem);
if (items.length == 0) {
final PsiElement firstItem = getFirstItem(elem);
if (firstItem == null) {
return !PyTokenTypes.CLOSE_BRACES.contains(elem.getLastChild().getNode().getElementType());
}
else {
final PsiElement firstItem = items[0];
if (firstItem instanceof PyNamedParameter) {
final PyExpression defaultValue = ((PyNamedParameter)firstItem).getDefaultValue();
return defaultValue != null && hasHangingIndent(defaultValue);
@@ -497,30 +499,34 @@ public class PyBlock implements ASTBlock {
}
}
@NotNull
private static PsiElement[] getItems(@NotNull PsiElement elem) {
@Nullable
private static PsiElement getFirstItem(@NotNull PsiElement elem) {
PsiElement[] items = PsiElement.EMPTY_ARRAY;
if (elem instanceof PySequenceExpression) {
return ((PySequenceExpression)elem).getElements();
items = ((PySequenceExpression)elem).getElements();
}
else if (elem instanceof PyParameterList) {
return ((PyParameterList)elem).getParameters();
items = ((PyParameterList)elem).getParameters();
}
else if (elem instanceof PyArgumentList) {
return ((PyArgumentList)elem).getArguments();
items = ((PyArgumentList)elem).getArguments();
}
else if (elem instanceof PyFromImportStatement) {
return ((PyFromImportStatement)elem).getImportElements();
items = ((PyFromImportStatement)elem).getImportElements();
}
else if (elem instanceof PyParenthesizedExpression) {
final PyExpression containedExpression = ((PyParenthesizedExpression)elem).getContainedExpression();
if (containedExpression instanceof PyTupleExpression) {
return ((PyTupleExpression)containedExpression).getElements();
items = ((PyTupleExpression)containedExpression).getElements();
}
else if (containedExpression != null) {
return new PsiElement[]{containedExpression};
return containedExpression;
}
}
return PsiElement.EMPTY_ARRAY;
else if (elem instanceof PyComprehensionElement) {
return ((PyComprehensionElement)elem).getResultExpression();
}
return ArrayUtil.getFirstElement(items);
}
private static boolean breaksAlignment(IElementType type) {
@@ -0,0 +1,23 @@
xs1 = [
x
for x in range(10)
if True
]
xs2 = {
x
for x in range(10)
if True
}
xs3 = {
x: None
for x in range(10)
if True
}
xs4 = (
x
for x in range(10)
if True
)
@@ -0,0 +1,23 @@
xs1 = [
x
for x in range(10)
if True
]
xs2 = {
x
for x in range(10)
if True
}
xs3 = {
x: None
for x in range(10)
if True
}
xs4 = (
x
for x in range(10)
if True
)
@@ -0,0 +1,23 @@
xs1 = [
x
for x in range(10)
if True
]
xs2 = {
x
for x in range(10)
if True
}
xs3 = {
x: None
for x in range(10)
if True
}
xs4 = (
x
for x in range(10)
if True
)
@@ -0,0 +1,23 @@
xs1 = [
x
for x in range(10)
if True
]
xs2 = {
x
for x in range(10)
if True
}
xs3 = {
x: None
for x in range(10)
if True
}
xs4 = (
x
for x in range(10)
if True
)
@@ -700,6 +700,19 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
// PY-15874
public void testHangClosingOffComprehensionsAndGeneratorExpressions() {
getPythonCodeStyleSettings().HANG_CLOSING_BRACKETS = false;
doTest();
}
// PY-15874
public void testHangClosingOnComprehensionsAndGeneratorExpressions() {
getPythonCodeStyleSettings().HANG_CLOSING_BRACKETS = true;
doTest();
}
public void testVariableAnnotations() {
runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
}