Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2012-08-22 17:45:59 +02:00
25 changed files with 259 additions and 77 deletions
@@ -28,7 +28,15 @@ public abstract class PyRunConfigurationFactory {
return ServiceManager.getService(PyRunConfigurationFactory.class);
}
public abstract PythonRunConfigurationParams createPythonScriptRunConfiguration(Module module, String scriptName);
/**
* Creates a run configuration to run a specified Python script.
*
* @param module the module in the context of which the script is run.
* @param scriptName the path to the script file.
* @param singleton if true, the "Check no other instances are running" option will be set for the run configuration.
* @return the settings of the created run configuration.
*/
public abstract PythonRunConfigurationParams createPythonScriptRunConfiguration(Module module, String scriptName, boolean singleton);
public abstract RunnerAndConfigurationSettings createRunConfiguration(Module module, ConfigurationFactory factory);
}
@@ -8,6 +8,7 @@ import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.Stack;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.editor.PythonEnterHandler;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -30,13 +31,12 @@ public class RemoveUnnecessaryBackslashQuickFix implements LocalQuickFix {
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement problemElement = descriptor.getPsiElement();
if (problemElement != null) {
PyElement parent = PsiTreeUtil.getParentOfType(problemElement, PySequenceExpression.class, PyDictLiteralExpression.class,
PyParenthesizedExpression.class, PyArgumentList.class, PyParameterList.class);
PsiElement parent = PsiTreeUtil.getParentOfType(problemElement, PythonEnterHandler.IMPLICIT_WRAP_CLASSES);
removeBackSlash(parent);
}
}
private static void removeBackSlash(PyElement parent) {
private static void removeBackSlash(PsiElement parent) {
if (parent != null) {
Stack<PsiElement> stack = new Stack<PsiElement>();
if (parent instanceof PyParenthesizedExpression)
@@ -0,0 +1,14 @@
package com.jetbrains.python.codeInsight.controlflow;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.Nullable;
/**
* @author yole
*/
public interface InstructionTypeCallback {
@Nullable
PyType getType(TypeEvalContext context, @Nullable PsiElement anchor);
}
@@ -1,11 +1,12 @@
package com.jetbrains.python.codeInsight.controlflow;
import com.intellij.util.Function;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.CollectionFactory;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -43,9 +44,9 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
final PyExpression typeElement = args[1];
final boolean positive = myPositive;
if (!processTuple(target, typeElement)) {
pushAssertion(target, new Function<TypeEvalContext, PyType>() {
pushAssertion(target, new InstructionTypeCallback() {
@Override
public PyType fun(TypeEvalContext context) {
public PyType getType(TypeEvalContext context, PsiElement anchor) {
final List<PyType> types = new ArrayList<PyType>();
types.add(context.getType(typeElement));
return createAssertionType(context.getType(target), types, positive, context);
@@ -59,9 +60,9 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
if (args.length == 1 && args[0] instanceof PyReferenceExpression) {
final PyReferenceExpression target = (PyReferenceExpression)args[0];
final boolean positive = myPositive;
pushAssertion(target, new Function<TypeEvalContext, PyType>() {
pushAssertion(target, new InstructionTypeCallback() {
@Override
public PyType fun(TypeEvalContext context) {
public PyType getType(TypeEvalContext context, PsiElement anchor) {
final List<PyType> types = new ArrayList<PyType>();
types.add(PyTypeParser.getTypeByName(target, PyNames.CALLABLE));
return createAssertionType(context.getType(target), types, positive, context);
@@ -74,9 +75,9 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
@Override
public void visitPyReferenceExpression(final PyReferenceExpression node) {
if (node.getParent() instanceof PyIfPart) {
pushAssertion(node, new Function<TypeEvalContext, PyType>() {
pushAssertion(node, new InstructionTypeCallback() {
@Override
public PyType fun(TypeEvalContext context) {
public PyType getType(TypeEvalContext context, PsiElement anchor) {
final List<PyType> types = new ArrayList<PyType>();
types.add(PyNoneType.INSTANCE);
return createAssertionType(context.getType(node), types, false, context);
@@ -95,9 +96,9 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
if (lhs instanceof PyReferenceExpression && rhs instanceof PyReferenceExpression) {
final PyReferenceExpression target = (PyReferenceExpression)lhs;
if (PyNames.NONE.equals(rhs.getName())) {
pushAssertion(target, new Function<TypeEvalContext, PyType>() {
pushAssertion(target, new InstructionTypeCallback() {
@Override
public PyType fun(TypeEvalContext context) {
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
final List<PyType> types = new ArrayList<PyType>();
types.add(PyNoneType.INSTANCE);
return createAssertionType(context.getType(target), types, false, context);
@@ -117,9 +118,9 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
if (contained instanceof PyTupleExpression) {
final PyTupleExpression tuple = (PyTupleExpression)contained;
final boolean positive = myPositive;
pushAssertion(target, new Function<TypeEvalContext, PyType>() {
pushAssertion(target, new InstructionTypeCallback() {
@Override
public PyType fun(TypeEvalContext context) {
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
final List<PyType> types = new ArrayList<PyType>();
for (PyExpression e : tuple.getElements()) {
types.add(context.getType(e));
@@ -133,6 +134,7 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
return pushed;
}
@Nullable
private static PyType createAssertionType(PyType initial, List<PyType> types, boolean positive, TypeEvalContext context) {
final List<PyType> members = new ArrayList<PyType>();
for (PyType t : types) {
@@ -151,15 +153,15 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
return initial;
}
private void pushAssertion(PyReferenceExpression element, Function<TypeEvalContext, PyType> getType) {
private void pushAssertion(PyReferenceExpression element, InstructionTypeCallback getType) {
myStack.push(new Assertion(element, getType));
}
static class Assertion {
private final PyReferenceExpression element;
private Function<TypeEvalContext, PyType> myFunction;
private InstructionTypeCallback myFunction;
Assertion(PyReferenceExpression element, Function<TypeEvalContext, PyType> getType) {
Assertion(PyReferenceExpression element, InstructionTypeCallback getType) {
this.element = element;
this.myFunction = getType;
}
@@ -168,7 +170,7 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
return element;
}
public Function<TypeEvalContext, PyType> getTypeEvalFunction() {
public InstructionTypeCallback getTypeEvalFunction() {
return myFunction;
}
}
@@ -3,19 +3,28 @@ package com.jetbrains.python.codeInsight.controlflow;
import com.intellij.codeInsight.controlflow.ControlFlowBuilder;
import com.intellij.codeInsight.controlflow.impl.InstructionImpl;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.impl.PyTargetExpressionImpl;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
public class ReadWriteInstruction extends InstructionImpl {
final Function<TypeEvalContext, PyType> EXPR_TYPE = new Function<TypeEvalContext, PyType>() {
final InstructionTypeCallback EXPR_TYPE = new InstructionTypeCallback() {
@Nullable
@Override
public PyType fun(TypeEvalContext context) {
return myElement instanceof PyExpression ? context.getType((PyExpression)myElement) : null;
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
if (myElement instanceof PyTargetExpressionImpl) {
return ((PyTargetExpressionImpl) myElement).getTypeWithAnchor(context, anchor);
}
if (myElement instanceof PyExpression) {
return context.getType((PyExpression)myElement);
}
else {
return null;
}
}
};
@@ -50,7 +59,7 @@ public class ReadWriteInstruction extends InstructionImpl {
private final String myName;
private final ACCESS myAccess;
private final Function<TypeEvalContext, PyType> myGetType;
private final InstructionTypeCallback myGetType;
private ReadWriteInstruction(final ControlFlowBuilder builder,
final PsiElement element,
@@ -63,7 +72,7 @@ public class ReadWriteInstruction extends InstructionImpl {
final PsiElement element,
final String name,
final ACCESS access,
@Nullable final Function<TypeEvalContext, PyType> getType) {
@Nullable final InstructionTypeCallback getType) {
super(builder, element);
myName = name;
myAccess = access;
@@ -100,13 +109,13 @@ public class ReadWriteInstruction extends InstructionImpl {
public static ReadWriteInstruction assertType(final ControlFlowBuilder builder,
final PsiElement element,
final String name,
final Function<TypeEvalContext, PyType> getType) {
final InstructionTypeCallback getType) {
return new ReadWriteInstruction(builder, element, name, ACCESS.ASSERTTYPE, getType);
}
@Nullable
public PyType getType(TypeEvalContext context) {
return myGetType.fun(context);
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
return myGetType.getType(context, anchor);
}
@NonNls
@@ -179,7 +179,7 @@ public class ScopeImpl implements Scope {
@Override
public void visitPyElement(PyElement node) {
if (node instanceof PsiNamedElement) {
if (node instanceof PsiNamedElement && !(node instanceof PyKeywordArgument)) {
namedElements.put(node.getName(), (PsiNamedElement)node);
}
// TODO: Cython-specific code
@@ -29,7 +29,15 @@ import org.jetbrains.annotations.Nullable;
public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
private boolean needPostProcess = false;
private static final Class[] IMPLICIT_WRAP_CLASSES = new Class[]{
public static final Class[] IMPLICIT_WRAP_CLASSES = new Class[] {
PySequenceExpression.class,
PyDictLiteralExpression.class,
PyParenthesizedExpression.class,
PyArgumentList.class,
PyParameterList.class
};
private static final Class[] WRAPPABLE_CLASSES = new Class[]{
PsiComment.class,
PyParenthesizedExpression.class,
PyListCompExpression.class,
@@ -116,13 +124,11 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
final boolean isEscapedBackslash = "\\".equals(doc.getText(TextRange.create(offset-2, offset - 1))) && nextIsBackslash;
if (nextIsBackslash && !isEscapedQuote && !isEscapedBackslash) return Result.Continue;
final PsiElement parent = string.getParent();
final StringBuilder replacementString = new StringBuilder();
needPostProcess = true;
if (parent instanceof PySequenceExpression || parent instanceof PyParenthesizedExpression ||
parent instanceof PyBinaryExpression || parent instanceof PyKeyValueExpression ||
parent instanceof PyNamedParameter || parent instanceof PyArgumentList) {
replacementString.append(quote + pref + quote);
if (PsiTreeUtil.getParentOfType(string, IMPLICIT_WRAP_CLASSES) != null) {
replacementString.append(quote).append(pref).append(quote);
doc.insertString(offset, replacementString);
caretOffset.set(caretOffset.get() + 1);
return Result.Continue;
@@ -132,7 +138,7 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
replacementString.append(quote);
caretOffset.set(caretOffset.get() + 1);
}
replacementString.append(quote + " \\" + pref);
replacementString.append(quote).append(" \\").append(pref);
if (!isEscapedQuote)
replacementString.append(quote);
doc.insertString(offset, replacementString.toString());
@@ -187,7 +193,7 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
PsiElement wrappableAfter = findWrappable(file, offset, false);
if (!(wrappableBefore instanceof PsiComment)) {
while (wrappableBefore != null) {
PsiElement next = PsiTreeUtil.getParentOfType(wrappableBefore, IMPLICIT_WRAP_CLASSES);
PsiElement next = PsiTreeUtil.getParentOfType(wrappableBefore, WRAPPABLE_CLASSES);
if (next == null) {
break;
}
@@ -196,7 +202,7 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
}
if (!(wrappableAfter instanceof PsiComment)) {
while (wrappableAfter != null) {
PsiElement next = PsiTreeUtil.getParentOfType(wrappableAfter, IMPLICIT_WRAP_CLASSES);
PsiElement next = PsiTreeUtil.getParentOfType(wrappableAfter, WRAPPABLE_CLASSES);
if (next == null) {
break;
}
@@ -234,8 +240,8 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
@Nullable
private static PsiElement findWrappable(PsiFile file, int offset, boolean before) {
PsiElement wrappable = before
? findBeforeCaret(file, offset, IMPLICIT_WRAP_CLASSES)
: findAfterCaret(file, offset, IMPLICIT_WRAP_CLASSES);
? findBeforeCaret(file, offset, WRAPPABLE_CLASSES)
: findAfterCaret(file, offset, WRAPPABLE_CLASSES);
if (wrappable == null) {
PsiElement emptyTuple = before
? findBeforeCaret(file, offset, PyTupleExpression.class)
@@ -5,7 +5,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
@@ -29,12 +28,12 @@ import static com.jetbrains.python.psi.PyUtil.sure;
* @author yole
*/
public class PyBlock implements ASTBlock {
private final PyBlock myParent;
private final Alignment _alignment;
private final Indent _indent;
private final ASTNode _node;
private final Wrap _wrap;
private final CommonCodeStyleSettings mySettings;
private final SpacingBuilder mySpacingBuilder;
private final PyBlockContext myContext;
private List<PyBlock> _subBlocks = null;
private Alignment myChildAlignment;
private static final boolean DUMP_FORMATTING_BLOCKS = false;
@@ -56,18 +55,18 @@ public class PyBlock implements ASTBlock {
PyTokenTypes.LBRACE, PyTokenTypes.RBRACE,
PyTokenTypes.LBRACKET, PyTokenTypes.RBRACKET);
public PyBlock(final ASTNode node,
public PyBlock(final PyBlock parent,
final ASTNode node,
final Alignment alignment,
final Indent indent,
final Wrap wrap,
final CommonCodeStyleSettings settings,
SpacingBuilder spacingBuilder) {
final PyBlockContext context) {
myParent = parent;
_alignment = alignment;
_indent = indent;
_node = node;
_wrap = wrap;
mySettings = settings;
mySpacingBuilder = spacingBuilder;
myContext = context;
}
@NotNull
@@ -130,7 +129,7 @@ public class PyBlock implements ASTBlock {
if (ourListElementTypes.contains(parentType)) {
// wrapping in non-parenthesized tuple expression is not allowed (PY-1792)
if ((parentType != PyElementTypes.TUPLE_EXPRESSION || grandparentType == PyElementTypes.PARENTHESIZED_EXPRESSION) &&
!ourBrackets.contains(childType)) {
!ourBrackets.contains(childType) && childType != PyTokenTypes.COMMA) {
wrap = Wrap.createWrap(WrapType.NORMAL, true);
}
if (needListAlignment(child) && !isEmptyList(_node.getPsi())) {
@@ -138,9 +137,15 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.BINARY_EXPRESSION &&
PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(childType)) {
childAlignment = getAlignmentForChildren();
(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(childType) || PyTokenTypes.OPERATIONS.contains(childType))) {
if (grandparentType == PyElementTypes.BINARY_EXPRESSION && myParent != null) {
childAlignment = myParent.getAlignmentForChildren();
}
else {
childAlignment = getAlignmentForChildren();
}
}
if (parentType == PyElementTypes.LIST_LITERAL_EXPRESSION) {
if (childType == PyTokenTypes.RBRACKET || childType == PyTokenTypes.LBRACKET) {
childIndent = Indent.getNoneIndent();
@@ -160,7 +165,7 @@ public class PyBlock implements ASTBlock {
}
}
else if (parentType == PyElementTypes.DICT_LITERAL_EXPRESSION || parentType == PyElementTypes.SET_LITERAL_EXPRESSION) {
if (childType == PyTokenTypes.RBRACE) {
if (childType == PyTokenTypes.RBRACE || !hasLineBreaksBefore(child, 1)) {
childIndent = Indent.getNoneIndent();
}
else {
@@ -193,7 +198,7 @@ public class PyBlock implements ASTBlock {
childIndent = Indent.getNormalIndent();
}
return new PyBlock(child, childAlignment, childIndent, wrap, mySettings, mySpacingBuilder);
return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext);
}
private static boolean isEmptyList(PsiElement psi) {
@@ -224,29 +229,39 @@ public class PyBlock implements ASTBlock {
IElementType childType = child.getElementType();
ASTNode firstGrandchild = child.getFirstChildNode();
IElementType firstGrandchildType = firstGrandchild == null ? null : firstGrandchild.getElementType();
if (PyTokenTypes.OPEN_BRACES.contains(childType) || PyTokenTypes.OPEN_BRACES.contains(firstGrandchildType)) {
if (PyTokenTypes.OPEN_BRACES.contains(childType)) {
return false;
}
if (PyTokenTypes.OPEN_BRACES.contains(firstGrandchildType)) {
PsiElement psi = child.getPsi();
if (psi instanceof PySequenceExpression && ((PySequenceExpression)psi).getElements().length == 0) {
return false;
}
}
if (PyTokenTypes.CLOSE_BRACES.contains(childType)) {
ASTNode prevNonSpace = findPrevNonSpaceNode(child);
if (prevNonSpace != null && prevNonSpace.getElementType() == PyTokenTypes.COMMA) {
if (prevNonSpace != null && prevNonSpace.getElementType() == PyTokenTypes.COMMA && myContext.getMode() == FormattingMode.ADJUST_INDENT) {
return true;
}
return false;
}
if (_node.getElementType() == PyElementTypes.ARGUMENT_LIST) {
if (!mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS) {
if (!myContext.getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS) {
return false;
}
if (child.getElementType() == PyTokenTypes.COMMA) {
return false;
}
PyArgumentList argList = (PyArgumentList)_node.getPsi();
if (argList != null) {
PyExpression[] arguments = argList.getArguments();
return arguments.length > 1 || (arguments.length == 1 && PyPsiUtils.getNextComma(arguments[0].getNode()) != null);
return arguments.length > 1 || hasLineBreaksBefore(child, 1) || (
arguments.length == 1 && PyPsiUtils.getNextComma(arguments[0].getNode()) != null);
}
return false;
}
if (_node.getElementType() == PyElementTypes.PARAMETER_LIST) {
return mySettings.ALIGN_MULTILINE_PARAMETERS;
return myContext.getSettings().ALIGN_MULTILINE_PARAMETERS;
}
if (child.getElementType() == PyTokenTypes.COMMA) {
return false;
@@ -315,7 +330,7 @@ public class PyBlock implements ASTBlock {
@Nullable
public Spacing getSpacing(Block child1, Block child2) {
return mySpacingBuilder.getSpacing(this, child1, child2);
return myContext.getSpacingBuilder().getSpacing(this, child1, child2);
}
@NotNull
@@ -376,7 +391,7 @@ public class PyBlock implements ASTBlock {
// correct indent manually.
if (statementListsBelow > 0) { // was 1... strange
@SuppressWarnings("ConstantConditions")
int indent = mySettings.getIndentOptions().INDENT_SIZE;
int indent = myContext.getSettings().getIndentOptions().INDENT_SIZE;
return new ChildAttributes(Indent.getSpaceIndent(indent * statementListsBelow), null);
}
@@ -405,7 +420,7 @@ public class PyBlock implements ASTBlock {
@Nullable
private Alignment getChildAlignment() {
if (ourListElementTypes.contains(_node.getElementType())) {
if (_node.getPsi() instanceof PyParameterList && !mySettings.ALIGN_MULTILINE_PARAMETERS) {
if (_node.getPsi() instanceof PyParameterList && !myContext.getSettings().ALIGN_MULTILINE_PARAMETERS) {
return null;
}
if (_node.getPsi() instanceof PyDictLiteralExpression) {
@@ -0,0 +1,32 @@
package com.jetbrains.python.formatter;
import com.intellij.formatting.FormattingMode;
import com.intellij.formatting.SpacingBuilder;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
/**
* @author yole
*/
public class PyBlockContext {
private final CommonCodeStyleSettings mySettings;
private final SpacingBuilder mySpacingBuilder;
private final FormattingMode myMode;
public PyBlockContext(CommonCodeStyleSettings settings, SpacingBuilder builder, FormattingMode mode) {
mySettings = settings;
mySpacingBuilder = builder;
myMode = mode;
}
public CommonCodeStyleSettings getSettings() {
return mySettings;
}
public SpacingBuilder getSpacingBuilder() {
return mySpacingBuilder;
}
public FormattingMode getMode() {
return myMode;
}
}
@@ -20,26 +20,33 @@ import static com.jetbrains.python.PyTokenTypes.*;
/**
* @author yole
*/
public class PythonFormattingModelBuilder implements FormattingModelBuilder, CustomFormattingModelBuilder {
public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, CustomFormattingModelBuilder {
private static final boolean DUMP_FORMATTING_AST = false;
@NotNull
public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
@Override
public FormattingModel createModel(@NotNull PsiElement element,
@NotNull CodeStyleSettings settings,
@NotNull FormattingMode mode) {
if (DUMP_FORMATTING_AST) {
ASTNode fileNode = element.getContainingFile().getNode();
System.out.println("AST tree for " + element.getContainingFile().getName() + ":");
printAST(fileNode, 0);
}
final CommonCodeStyleSettings codeStyleSettings = settings.getCommonSettings(PythonLanguage.getInstance());
final PyBlock block =
new PyBlock(element.getNode(), null, Indent.getNoneIndent(), null, codeStyleSettings,
createSpacingBuilder(settings));
final PyBlockContext context = new PyBlockContext(codeStyleSettings, createSpacingBuilder(settings), mode);
final PyBlock block = new PyBlock(null, element.getNode(), null, Indent.getNoneIndent(), null, context);
if (DUMP_FORMATTING_AST) {
FormattingModelDumper.dumpFormattingModel(block, 2, System.out);
}
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings);
}
@NotNull
public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
return createModel(element, settings, FormattingMode.REFORMAT);
}
protected SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) {
final IFileElementType file = LanguageParserDefinitions.INSTANCE.forLanguage(PythonLanguage.getInstance()).getFileNodeType();
final PyCodeStyleSettings pySettings = settings.getCustomSettings(PyCodeStyleSettings.class);
@@ -281,9 +281,11 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
public static PyType getTypeFromTarget(@NotNull final PsiElement target,
final TypeEvalContext context,
PyReferenceExpression anchor) {
final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
if (pyType != null) {
return pyType;
if (!(target instanceof PyTargetExpression)) { // PyTargetExpression will ask about its type itself
final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
if (pyType != null) {
return pyType;
}
}
if (target instanceof PyTargetExpression) {
final String name = ((PyTargetExpression)target).getName();
@@ -310,9 +312,9 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
augAssignment != null ? augAssignment : anchor,
true);
if (!defs.isEmpty()) {
PyType type = defs.get(0).getType(context);
PyType type = defs.get(0).getType(context, anchor);
for (int i = 1; i < defs.size(); i++) {
type = PyUnionType.union(type, defs.get(i).getType(context));
type = PyUnionType.union(type, defs.get(i).getType(context, anchor));
}
return type;
}
@@ -329,7 +331,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
if (propertyDecorator != null) {
return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
}
for (PyDecorator decorator: decoratorList.getDecorators()) {
for (PyDecorator decorator : decoratorList.getDecorators()) {
final PyQualifiedName qName = decorator.getQualifiedName();
if (qName != null && (qName.endsWith(PyNames.SETTER) || qName.endsWith(PyNames.DELETER))) {
return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
@@ -342,7 +344,9 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
}
if (target instanceof PsiDirectory) {
PsiFile file = ((PsiDirectory)target).findFile(PyNames.INIT_DOT_PY);
if (file != null) return getTypeFromTarget(file, context, anchor);
if (file != null) {
return getTypeFromTarget(file, context, anchor);
}
}
return null;
}
@@ -98,6 +98,11 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
}
public PyType getType(@NotNull TypeEvalContext context) {
return getTypeWithAnchor(context, null);
}
@Nullable
public PyType getTypeWithAnchor(TypeEvalContext context, @Nullable PsiElement anchor) {
if (!TypeEvalStack.mayEvaluate(this)) {
return null;
}
@@ -107,6 +112,10 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
// imported via __all__
return null;
}
final PyType pyType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(this, context, anchor);
if (pyType != null) {
return pyType;
}
if (!context.maySwitchToAST(this)) {
final PsiElement value = getStub() != null ? findAssignedValueByStub() : findAssignedValue();
if (value instanceof PyTypedElement) {
@@ -13,8 +13,9 @@ import org.jetbrains.annotations.NotNull;
*/
public class PyRunConfigurationFactoryImpl extends PyRunConfigurationFactory {
@Override
public PythonRunConfigurationParams createPythonScriptRunConfiguration(Module module, String scriptName) {
public PythonRunConfigurationParams createPythonScriptRunConfiguration(Module module, String scriptName, boolean singleton) {
RunnerAndConfigurationSettings settings = createRunConfiguration(module, PythonConfigurationType.getInstance().getFactory());
settings.setSingleton(singleton);
PythonRunConfigurationParams configuration = (PythonRunConfigurationParams)settings.getConfiguration();
configuration.setScriptName(scriptName);
return configuration;
@@ -0,0 +1,3 @@
term1 = BNF.lpar + expr + BNF.rpar\
| if_expr\
| numeric_value
@@ -0,0 +1,3 @@
term1 = BNF.lpar + expr + BNF.rpar\
| if_expr\
| numeric_value
+7
View File
@@ -0,0 +1,7 @@
d = {
'success': 'OK',
'tag_count': 2,
'tags': [
{'name': 'tag1', 'uses': '1', 'display': '1', 'security': 'private'},
],
}
@@ -0,0 +1,7 @@
d = {
'success': 'OK',
'tag_count': 2,
'tags': [
{'name': 'tag1', 'uses': '1', 'display': '1', 'security': 'private'},
],
}
@@ -0,0 +1,3 @@
self.assertEqual(
{"000000000000", "111111111111"},
foo['bar']['baz'])
@@ -0,0 +1,3 @@
self.assertEqual(
{"000000000000", "111111111111"},
foo['bar']['baz'])
@@ -0,0 +1,4 @@
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
url(r'^', include('cms.urls')),
)
@@ -0,0 +1,4 @@
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
url(r'^', include('cms.urls')),
)
+8
View File
@@ -0,0 +1,8 @@
from datetime import timedelta
def foo(**kwargs):
pass
def bar():
foo(timedelta=timedelta)
# <ref>
@@ -111,6 +111,12 @@ public class PyEditingTest extends PyTestCase {
" r'string'");
}
public void testEnterInStringFormatting() { // PY-7039
doTestEnter("foo += \"fooba<caret>r\" % foo\n",
"foo += \"fooba\" \\\n" +
" \"r\" % foo\n");
}
public void testEnterInStatement() {
doTestEnter("if a <caret>and b: pass", "if a \\\nand b: pass");
}
@@ -4,6 +4,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
@@ -118,12 +119,12 @@ public class PyFormatterTest extends PyTestCase {
}
public void testSpaceInMethodDeclaration() { // PY-4241
CodeStyleSettingsManager.getInstance().getSettings(myFixture.getProject()).SPACE_BEFORE_METHOD_PARENTHESES = true;
settings().SPACE_BEFORE_METHOD_PARENTHESES = true;
doTest();
}
public void testOptionalAlignForMethodParameters() { // PY-3995
CodeStyleSettingsManager.getInstance().getSettings(myFixture.getProject()).ALIGN_MULTILINE_PARAMETERS = false;
settings().ALIGN_MULTILINE_PARAMETERS = false;
doTest();
}
@@ -132,7 +133,7 @@ public class PyFormatterTest extends PyTestCase {
}
public void testAlignForMethodArguments() { // PY-3995
CodeStyleSettingsManager.getInstance().getSettings(myFixture.getProject()).ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
settings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doTest();
}
@@ -152,6 +153,24 @@ public class PyFormatterTest extends PyTestCase {
doTest();
}
public void testSetLiteralInArgList() { // PY-6672
settings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doTest();
}
public void testLiterals() { // PY-6751
doTest();
}
public void testTupleInArgList() {
settings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doTest();
}
public void testAlignInBinaryExpressions() {
doTest();
}
public void testPsiFormatting() { // IDEA-69724
String initial =
"def method_name(\n" +
@@ -190,4 +209,8 @@ public class PyFormatterTest extends PyTestCase {
});
myFixture.checkResultByFile("formatter/" + getTestName(true) + "_after.py");
}
private CodeStyleSettings settings() {
return CodeStyleSettingsManager.getInstance().getSettings(myFixture.getProject());
}
}
@@ -472,4 +472,8 @@ public class PyResolveTest extends PyResolveTestCase {
public void testClassRedefinedField() {
assertResolvesTo(PyClass.class, "Foo");
}
public void testKWArg() {
assertResolvesTo(PyClass.class, "timedelta");
}
}