PY-14962 Allow to specify wrapping for key-value pairs of dict literals

This commit is contained in:
Mikhail Golubev
2015-05-25 20:29:37 +03:00
parent db9a64bb63
commit e0bb7c5a6d
6 changed files with 59 additions and 21 deletions

View File

@@ -88,6 +88,7 @@ public class PyBlock implements ASTBlock {
private List<PyBlock> mySubBlocks = null;
private Alignment myChildAlignment;
private final Alignment myDictAlignment;
private final Wrap myDictWrapping;
private final boolean myEmptySequence;
public PyBlock(final PyBlock parent,
@@ -104,7 +105,14 @@ public class PyBlock implements ASTBlock {
myContext = context;
myEmptySequence = isEmptySequence(node);
myDictAlignment = node.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION ? Alignment.createAlignment(true) : null;
if (node.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION) {
myDictAlignment = Alignment.createAlignment(true);
myDictWrapping = Wrap.createWrap(myContext.getPySettings().DICT_WRAPPING, true);
}
else {
myDictAlignment = null;
myDictWrapping = null;
}
}
@NotNull
@@ -267,11 +275,8 @@ public class PyBlock implements ASTBlock {
}
}
}
else if (parentType == PyElementTypes.KEY_VALUE_EXPRESSION) {
final PyKeyValueExpression keyValue = (PyKeyValueExpression)myNode.getPsi();
if (keyValue != null && child.getPsi() == keyValue.getValue()) {
childIndent = Indent.getNormalIndent();
}
else if (isValueOfKeyValuePair(child)) {
childIndent = Indent.getNormalIndent();
}
//Align elements vertically if there is an argument in the first line of parenthesized expression
else if (!hasHangingIndent(myNode.getPsi()) &&
@@ -341,23 +346,28 @@ public class PyBlock implements ASTBlock {
}
}
}
if (childType == PyElementTypes.KEY_VALUE_EXPRESSION && isChildOfDictLiteral(child)) {
wrap = myDictWrapping;
childIndent = Indent.getNormalIndent();
}
if (isAfterStatementList(child) && !hasLineBreaksBefore(child, 2) && child.getElementType() != PyTokenTypes.END_OF_LINE_COMMENT) {
// maybe enter was pressed and cut us from a previous (nested) statement list
childIndent = Indent.getNormalIndent();
}
if (settings.DICT_ALIGNMENT == DICT_ALIGNMENT_ON_VALUE) {
if (isDictLiteralPropertyValue(child) && !ourListElementTypes.contains(childType)) {
if (isValueOfKeyValuePairOfDictLiteral(child) && !ourListElementTypes.contains(childType)) {
childAlignment = myParent.myDictAlignment;
}
else if (isDictLiteralPropertyValue(myNode) &&
else if (isValueOfKeyValuePairOfDictLiteral(myNode) &&
ourListElementTypes.contains(parentType) &&
PyTokenTypes.OPEN_BRACES.contains(childType)) {
childAlignment = myParent.myParent.myDictAlignment;
}
}
else if (myContext.getPySettings().DICT_ALIGNMENT == DICT_ALIGNMENT_ON_COLON) {
if (isInsideDictLiteralKeyValue(child) && childType == PyTokenTypes.COLON) {
if (isChildOfKeyValuePairOfDictLiteral(child) && childType == PyTokenTypes.COLON) {
childAlignment = myParent.myDictAlignment;
}
}
@@ -376,21 +386,26 @@ public class PyBlock implements ASTBlock {
return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext);
}
private static boolean isDictLiteralPropertyValue(@NotNull ASTNode node) {
return isInsideDictLiteralKeyValue(node) && node.getTreeParent().getPsi(PyKeyValueExpression.class).getValue() == node.getPsi();
private static boolean isValueOfKeyValuePairOfDictLiteral(@NotNull ASTNode node) {
return isValueOfKeyValuePair(node) && isChildOfDictLiteral(node.getTreeParent());
}
private static boolean isInsideDictLiteralKeyValue(@NotNull ASTNode node) {
private static boolean isChildOfKeyValuePairOfDictLiteral(@NotNull ASTNode node) {
return isChildOfKeyValuePair(node) && isChildOfDictLiteral(node.getTreeParent());
}
private static boolean isChildOfDictLiteral(@NotNull ASTNode node) {
final ASTNode nodeParent = node.getTreeParent();
if (nodeParent == null) {
return false;
}
final ASTNode nodeGrandParent = nodeParent.getTreeParent();
if (nodeGrandParent == null) {
return false;
}
return nodeParent.getElementType() == PyElementTypes.KEY_VALUE_EXPRESSION &&
nodeGrandParent.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION;
return nodeParent != null && nodeParent.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION;
}
private static boolean isChildOfKeyValuePair(@NotNull ASTNode node) {
final ASTNode nodeParent = node.getTreeParent();
return nodeParent != null && nodeParent.getElementType() == PyElementTypes.KEY_VALUE_EXPRESSION;
}
private static boolean isValueOfKeyValuePair(@NotNull ASTNode node) {
return isChildOfKeyValuePair(node) && node.getTreeParent().getPsi(PyKeyValueExpression.class).getValue() == node.getPsi();
}
private static boolean isEmptySequence(@NotNull ASTNode node) {

View File

@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.formatter;
import com.intellij.formatting.WrapType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.jetbrains.python.PyBundle;
@@ -72,6 +73,8 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings {
public boolean SPACE_BEFORE_NUMBER_SIGN = true;
public int DICT_ALIGNMENT = DICT_ALIGNMENT_NONE;
public int DICT_WRAPPING = WrapType.NORMAL.getLegacyRepresentation();
public PyCodeStyleSettings(CodeStyleSettings container) {
super("Python", container);

View File

@@ -103,6 +103,7 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
"Collections and Comprehensions");
consumer.showCustomOption(PyCodeStyleSettings.class, "ALIGN_MULTILINE_IMPORTS", "Align when multiline",
"Import Statements");
consumer.showCustomOption(PyCodeStyleSettings.class, "DICT_WRAPPING", "Dictionary literals", null, WRAP_OPTIONS, WRAP_VALUES);
}
}

View File

@@ -0,0 +1,2 @@
handlers = {ACTION_1: handle_action_1, ACTION_2: handle_action_2, ACTION_3: handle_action_3, ACTION_4: handle_action_4,
ACTION_5: handle_action_5, ACTION_6: handle_action_6, ACTION_7: handle_action_7, ACTION_8: handle_action_8}

View File

@@ -0,0 +1,9 @@
handlers = {
ACTION_1: handle_action_1,
ACTION_2: handle_action_2,
ACTION_3: handle_action_3,
ACTION_4: handle_action_4,
ACTION_5: handle_action_5,
ACTION_6: handle_action_6,
ACTION_7: handle_action_7,
ACTION_8: handle_action_8}

View File

@@ -15,6 +15,7 @@
*/
package com.jetbrains.python;
import com.intellij.formatting.WrapType;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -579,6 +580,13 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
// PY-14962
public void testDictWrappingChopDownIfLong() {
settings().setRightMargin(PythonLanguage.getInstance(), 80);
getCustomSettings().DICT_WRAPPING = WrapType.CHOP_DOWN_IF_LONG.getLegacyRepresentation();
doTest();
}
// PY-15530
public void testAlignmentInArgumentListWhereFirstArgumentIsEmptyCall() {
doTest();