Merge branch 'master' of git.labs.intellij.net:idea/ultimate

This commit is contained in:
Dmitry Trofimov
2010-05-07 18:19:26 +04:00
21 changed files with 320 additions and 19 deletions
@@ -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);
@@ -106,7 +106,9 @@ public class StatementMover extends LineMover {
}
@Nullable
private static LineRange expandLineRange(LineRange range, Editor editor, PsiFile file) {
private static LineRange expandLineRange(@NotNull final LineRange range,
@NotNull final Editor editor,
@NotNull final PsiFile file) {
final SelectionModel selectionModel = editor.getSelectionModel();
Pair<PsiElement, PsiElement> psiRange;
if (selectionModel.hasSelection()) {
@@ -136,11 +138,14 @@ public class StatementMover extends LineMover {
return null;
}
if (elementRange.getFirst() == elementRange.getSecond() && elementRange.getFirst() instanceof PyPassStatement) {
final PsiElement first = elementRange.getFirst();
final PsiElement second = elementRange.getSecond();
if (first == second && first instanceof PyPassStatement) {
return null;
}
final int endOffset = elementRange.getSecond().getTextRange().getEndOffset();
int startOffset = first.getTextOffset();
int endOffset = second.getTextRange().getEndOffset();
final Document document = editor.getDocument();
if (endOffset > document.getTextLength()) {
LOG.assertTrue(!PsiDocumentManager.getInstance(file.getProject()).isUncommited(document));
@@ -156,7 +161,7 @@ public class StatementMover extends LineMover {
endLine = Math.min(endLine, document.getLineCount());
}
endLine = Math.max(endLine, range.endLine);
final int startLine = Math.min(range.startLine, editor.offsetToLogicalPosition(elementRange.getFirst().getTextOffset()).line);
final int startLine = Math.min(range.startLine, editor.offsetToLogicalPosition(startOffset).line);
return new LineRange(startLine, endLine);
}
@@ -257,22 +262,27 @@ public class StatementMover extends LineMover {
}
info.toMove2 = new LineRange(statement, statement, document);
final PyStatementPart[] statementParts = PsiTreeUtil.getChildrenOfType(statement, PyStatementPart.class);
// next/previous statement has a statement parts
// move inside statement part
if (statementParts != null) {
// move inside statement part
int startLineNumber;
int endLineNumber;
PyStatementPart statementPart;
if (down) {
final PyStatementPart statementPart = statementParts[0];
final int lineNumber = document.getLineNumber(statementPart.getTextRange().getStartOffset());
info.toMove2 = new LineRange(lineNumber, lineNumber + 1);
myStatementListToRemovePass = statementPart.getStatementList();
myElementsToIncreaseIndent = statements;
statementPart = statementParts[0];
startLineNumber = document.getLineNumber(statementPart.getTextRange().getStartOffset());
endLineNumber = document.getLineNumber(statementPart.getTextRange().getEndOffset());
}
else {
final PyStatementPart statementPart = statementParts[statementParts.length - 1];
final int lineNumber = document.getLineNumber(statementPart.getTextRange().getEndOffset());
info.toMove2 = new LineRange(lineNumber, lineNumber + 1);
statementPart = statementParts[statementParts.length - 1];
startLineNumber = document.getLineNumber(statementPart.getTextRange().getEndOffset());
endLineNumber = document.getLineNumber(statementPart.getTextRange().getStartOffset());
}
if (startLineNumber != endLineNumber) {
info.toMove2 = new LineRange(startLineNumber, startLineNumber + 1);
myStatementListToRemovePass = statementPart.getStatementList();
myElementsToIncreaseIndent = statements;
}
@@ -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
+7
View File
@@ -0,0 +1,7 @@
class A:
def foo(self):
if a: pass
else: pass
a <caret>= 0
if a: pass
else: pass
+7
View File
@@ -0,0 +1,7 @@
class A:
def foo(self):
if a: pass
else: pass
if a: pass
else: pass
a <caret>= 0
+7
View File
@@ -0,0 +1,7 @@
class A:
def foo(self):
a <caret>= 0
if a: pass
else: pass
if a: pass
else: pass
@@ -0,0 +1,9 @@
if a:
a = 1
b =<caret> 2
c = 3
@@ -0,0 +1,9 @@
if a:
a = 1
c = 3
b = 2
@@ -0,0 +1,9 @@
if a:
b = 2
a = 1
c = 3
@@ -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() {
@@ -60,4 +60,12 @@ public class PyStatementMoverTest extends PyLightFixtureTestCase {
public void testSelection() throws Exception {
doTest();
}
public void testSimpleBlankLines() throws Exception {
doTest();
}
public void testPY950() throws Exception {
doTest();
}
}