mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
spacing options in Python formatter (PY-951)
This commit is contained in:
@@ -137,6 +137,9 @@ public class PyTokenTypes {
|
||||
public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS);
|
||||
public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, FLOORDIV, DIV, PERC);
|
||||
public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE);
|
||||
public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR);
|
||||
public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD);
|
||||
public static final TokenSet RELATIONAL_OPERATIONS = TokenSet.create(LT, GT, LE, GE);
|
||||
public static final TokenSet END_OF_STATEMENT = TokenSet.create(STATEMENT_BREAK, SEMICOLON);
|
||||
public static final TokenSet WHITESPACE = TokenSet.create(SPACE, TAB, FORMFEED);
|
||||
public static final TokenSet WHITESPACE_OR_LINEBREAK = TokenSet.create(SPACE, TAB, FORMFEED, LINE_BREAK);
|
||||
|
||||
@@ -212,15 +212,71 @@ public class PyBlock implements ASTBlock {
|
||||
if (type1 == PyTokenTypes.COLON && type2 == PyElementTypes.STATEMENT_LIST) {
|
||||
return Spacing.createSpacing(1, Integer.MAX_VALUE, 0, true, 0);
|
||||
}
|
||||
if (type2 == PyTokenTypes.COLON) {
|
||||
return getSpacingForOption(getPySettings().SPACE_BEFORE_COLON);
|
||||
}
|
||||
|
||||
if (type1 == PyTokenTypes.COMMA) {
|
||||
return getSpacingForOption(mySettings.SPACE_AFTER_COMMA);
|
||||
}
|
||||
/*
|
||||
if (type1 == PyTokenTypes.COLON && type2 == PyElementTypes.STATEMENT_LIST) {
|
||||
return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, true, Integer.MAX_VALUE);
|
||||
}
|
||||
*/
|
||||
if (type2 == PyTokenTypes.COMMA) {
|
||||
return getSpacingForOption(mySettings.SPACE_BEFORE_COMMA);
|
||||
}
|
||||
if (type2 == PyTokenTypes.SEMICOLON) {
|
||||
return getSpacingForOption(mySettings.SPACE_BEFORE_SEMICOLON);
|
||||
}
|
||||
|
||||
if (type1 == PyTokenTypes.LPAR || type2 == PyTokenTypes.RPAR) {
|
||||
if (parentType == PyElementTypes.ARGUMENT_LIST) {
|
||||
return getSpacingForOption(mySettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
}
|
||||
if (type2 == PyTokenTypes.LBRACKET) {
|
||||
return getSpacingForOption(getPySettings().SPACE_BEFORE_LBRACKET);
|
||||
}
|
||||
if (type1 == PyTokenTypes.LBRACKET || type2 == PyTokenTypes.RBRACKET) {
|
||||
return getSpacingForOption(mySettings.SPACE_WITHIN_BRACKETS);
|
||||
}
|
||||
if (type1 == PyTokenTypes.LBRACE || type2 == PyTokenTypes.RBRACE) {
|
||||
return getSpacingForOption(getPySettings().SPACE_WITHIN_BRACES);
|
||||
}
|
||||
if (type2 == PyElementTypes.ARGUMENT_LIST) {
|
||||
return getSpacingForOption(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
|
||||
}
|
||||
|
||||
if (type1 == PyTokenTypes.EQ || type2 == PyTokenTypes.EQ) {
|
||||
if (parentType == PyElementTypes.ASSIGNMENT_STATEMENT) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
|
||||
}
|
||||
if (parentType == PyElementTypes.NAMED_PARAMETER) {
|
||||
return getSpacingForOption(getPySettings().SPACE_AROUND_EQ_IN_NAMED_PARAMETER);
|
||||
}
|
||||
if (parentType == PyElementTypes.KEYWORD_ARGUMENT_EXPRESSION) {
|
||||
return getSpacingForOption(getPySettings().SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT);
|
||||
}
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.AUG_ASSIGN_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_ASSIGNMENT_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.ADDITIVE_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_ADDITIVE_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.MULTIPLICATIVE_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_MULTIPLICATIVE_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.SHIFT_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_SHIFT_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.BITWISE_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_BITWISE_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.EQUALITY_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_EQUALITY_OPERATORS);
|
||||
}
|
||||
if (isAround(type1, type2, PyTokenTypes.RELATIONAL_OPERATIONS)) {
|
||||
return getSpacingForOption(mySettings.SPACE_AROUND_RELATIONAL_OPERATORS);
|
||||
}
|
||||
|
||||
|
||||
//if (parentType == PyElementTypes.ARGUMENT_LIST
|
||||
// || parentType == PyElementTypes.LIST_LITERAL_EXPRESSION) {
|
||||
@@ -240,6 +296,14 @@ public class PyBlock implements ASTBlock {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isAround(IElementType type1, IElementType type2, final TokenSet tokenSet) {
|
||||
return tokenSet.contains(type1) || tokenSet.contains(type2);
|
||||
}
|
||||
|
||||
private PyCodeStyleSettings getPySettings() {
|
||||
return mySettings.getCustomSettings(PyCodeStyleSettings.class);
|
||||
}
|
||||
|
||||
private Spacing getSpacingForOption(boolean isOptionSet) {
|
||||
int spaces = isOptionSet ? 1 : 0;
|
||||
return Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.formatter.PyCodeStylePanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.jetbrains.python.formatter;
|
||||
|
||||
import com.intellij.application.options.CodeStyleAbstractPanel;
|
||||
import com.intellij.ide.highlighter.HighlighterFactory;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.jetbrains.python.PyHighlighter;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyCodeStylePanel extends CodeStyleAbstractPanel {
|
||||
private JPanel myPanel;
|
||||
|
||||
protected PyCodeStylePanel(CodeStyleSettings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) {
|
||||
return HighlighterFactory.createHighlighter(new PyHighlighter(LanguageLevel.PYTHON26), scheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightMargin() {
|
||||
return 80;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareForReformat(PsiFile psiFile) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FileType getFileType() {
|
||||
return PythonFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPreviewText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl(CodeStyleSettings settings) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(CodeStyleSettings settings) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified(CodeStyleSettings settings) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.jetbrains.python.formatter;
|
||||
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
public boolean SPACE_WITHIN_BRACES = false;
|
||||
public boolean SPACE_BEFORE_COLON = false;
|
||||
public boolean SPACE_BEFORE_LBRACKET = false;
|
||||
public boolean SPACE_AROUND_EQ_IN_NAMED_PARAMETER = false;
|
||||
public boolean SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT = false;
|
||||
|
||||
protected PyCodeStyleSettings(CodeStyleSettings container) {
|
||||
super("Python", container);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jetbrains.python.formatter;
|
||||
|
||||
import com.intellij.application.options.CodeStyleAbstractConfigurable;
|
||||
import com.intellij.application.options.CodeStyleAbstractPanel;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
|
||||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
|
||||
@Override
|
||||
public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
|
||||
return new PyCodeStyleSettings(settings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) {
|
||||
return new CodeStyleAbstractConfigurable(settings, originalSettings, "Ruby") {
|
||||
protected CodeStyleAbstractPanel createPanel(final CodeStyleSettings settings) {
|
||||
return new PyCodeStylePanel(settings);
|
||||
}
|
||||
|
||||
public String getHelpTopic() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigurableDisplayName() {
|
||||
return "Python";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
spam( ham[ 1 ], { eggs: 2 } )
|
||||
if x == 4 : print x , y ; x , y = y , x
|
||||
spam (1)
|
||||
dict ['key'] = list [index]
|
||||
@@ -0,0 +1,4 @@
|
||||
spam(ham[1], {eggs: 2})
|
||||
if x == 4: print x, y; x, y = y, x
|
||||
spam(1)
|
||||
dict['key'] = list[index]
|
||||
@@ -0,0 +1,2 @@
|
||||
def complex(real, imag = 0.0):
|
||||
return magic(r = real, i = imag)
|
||||
@@ -0,0 +1,2 @@
|
||||
def complex(real, imag=0.0):
|
||||
return magic(r=real, i=imag)
|
||||
@@ -0,0 +1,3 @@
|
||||
i=i+1
|
||||
submitted+=1
|
||||
x = x*2-1
|
||||
@@ -0,0 +1,3 @@
|
||||
i = i + 1
|
||||
submitted += 1
|
||||
x = x * 2 - 1
|
||||
@@ -20,6 +20,18 @@ public class PyFormatterTest extends PyLightFixtureTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPep8ExtraneousWhitespace() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPep8Operators() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPep8KeywordArguments() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
myFixture.configureByFile("formatter/" + getTestName(true) + ".py");
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
|
||||
Reference in New Issue
Block a user