diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 45be9da4c5ec..1a4e4a37a36f 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -179,6 +179,7 @@
+
@@ -318,13 +319,6 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/python/src/com/jetbrains/python/actions/AddFieldQuickFix.java b/python/src/com/jetbrains/python/actions/AddFieldQuickFix.java
index d03ccf784b27..573c3004a577 100644
--- a/python/src/com/jetbrains/python/actions/AddFieldQuickFix.java
+++ b/python/src/com/jetbrains/python/actions/AddFieldQuickFix.java
@@ -5,15 +5,14 @@ import com.intellij.codeInsight.template.TemplateBuilder;
import com.intellij.codeInsight.template.TemplateBuilderFactory;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.lang.Language;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -89,30 +88,27 @@ public class AddFieldQuickFix implements LocalQuickFix {
public static PsiElement addFieldToInit(Project project, PyClass cls, String item_name, Function callback) {
if (cls != null && item_name != null) {
PyFunction init = cls.findMethodByName(PyNames.INIT, false);
- Language language = cls.getLanguage();
- if (language instanceof PythonLanguage) {
- if (init != null) {
- return appendToInit(init, callback);
+ if (init != null) {
+ return appendToInit(init, callback);
+ }
+ else { // no init! boldly copy ancestor's.
+ for (PyClass ancestor : cls.iterateAncestors()) {
+ init = ancestor.findMethodByName(PyNames.INIT, false);
+ if (init != null) break;
}
- else { // no init! boldly copy ancestor's.
- for (PyClass ancestor : cls.iterateAncestors()) {
- init = ancestor.findMethodByName(PyNames.INIT, false);
- if (init != null) break;
- }
- PyFunction new_init = createInitMethod(project, cls, init);
+ PyFunction new_init = createInitMethod(project, cls, init);
- appendToInit(new_init, callback);
+ appendToInit(new_init, callback);
- PsiElement add_anchor = null;
- PyFunction[] meths = cls.getMethods();
- if (meths.length > 0) add_anchor = meths[0].getPrevSibling();
- PyStatementList cls_content = cls.getStatementList();
- new_init = (PyFunction) cls_content.addAfter(new_init, add_anchor);
+ PsiElement add_anchor = null;
+ PyFunction[] meths = cls.getMethods();
+ if (meths.length > 0) add_anchor = meths[0].getPrevSibling();
+ PyStatementList cls_content = cls.getStatementList();
+ new_init = (PyFunction) cls_content.addAfter(new_init, add_anchor);
- PyUtil.showBalloon(project, PyBundle.message("QFIX.added.constructor.$0.for.field.$1", cls.getName(), item_name), MessageType.INFO);
- return new_init.getStatementList().getStatements()[0];
- //else // well, that can't be
- }
+ PyUtil.showBalloon(project, PyBundle.message("QFIX.added.constructor.$0.for.field.$1", cls.getName(), item_name), MessageType.INFO);
+ return new_init.getStatementList().getStatements()[0];
+ //else // well, that can't be
}
}
return null;
@@ -124,7 +120,8 @@ public class AddFieldQuickFix implements LocalQuickFix {
String paramList = ancestorInit != null ? ancestorInit.getParameterList().getText() : "(self)";
String functionText = "def " + PyNames.INIT + paramList + ":\n";
- if (cls.isNewStyleClass() && ancestorInit != null) {
+ if (cls.isNewStyleClass() && ancestorInit != null &&
+ ancestorInit.getContainingClass() != PyBuiltinCache.getInstance(ancestorInit).getClass("object")) {
// form the super() call
StringBuffer sb = new StringBuffer("super(");
sb.append(cls.getName());
diff --git a/python/src/com/jetbrains/python/codeInsight/PyClassInsertHandler.java b/python/src/com/jetbrains/python/codeInsight/PyClassInsertHandler.java
index 8a6fa8fd4dd2..c679f7f0428a 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyClassInsertHandler.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyClassInsertHandler.java
@@ -1,8 +1,10 @@
package com.jetbrains.python.codeInsight;
import com.intellij.codeInsight.AutoPopupController;
+import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -36,5 +38,8 @@ public class PyClassInsertHandler implements InsertHandler {
editor.getCaretModel().moveToOffset(offset+2);
}
}
+ else if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
+ TailType.SMART_COMPLETION.processTail(editor, context.getTailOffset());
+ }
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java b/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java
index 8a6f6a387c8b..6f2849b5ef8c 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyLineMarkerProvider.java
@@ -12,6 +12,7 @@ import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
@@ -136,6 +137,9 @@ public class PyLineMarkerProvider implements LineMarkerProvider, PyLineSeparator
@Nullable
private static LineMarkerInfo getMethodMarker(final PsiElement element, final PyFunction function) {
+ if (PyNames.INIT.equals(function.getName())) {
+ return null;
+ }
final PsiElement superMethod = PySuperMethodsSearch.search(function).findFirst();
if (superMethod != null) {
PyClass superClass = null;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
index 07ae89a8e1db..e4c48842e628 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyQualifiedReferenceImpl.java
@@ -100,7 +100,7 @@ public class PyQualifiedReferenceImpl extends PyReferenceImpl {
PyExpression qualifier = myElement.getQualifier();
assert qualifier != null;
- PyType qualifierType = qualifier.getType(TypeEvalContext.fast());
+ PyType qualifierType = qualifier.getType(TypeEvalContext.slow());
ProcessingContext ctx = new ProcessingContext();
final Set names_already = new HashSet();
ctx.put(PyType.CTX_NAMES, names_already);
diff --git a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
index 7f2108804c43..0a573d939b92 100644
--- a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
@@ -10,13 +10,16 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.refactoring.IntroduceTargetChooser;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
@@ -28,6 +31,7 @@ import com.jetbrains.python.refactoring.PyRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -106,6 +110,11 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
element1 = file.findElementAt(document.getLineStartOffset(lineNumber));
element2 = file.findElementAt(document.getLineEndOffset(lineNumber) - 1);
}
+ if (element1 == null || element2 == null || PyRefactoringUtil.getSelectedExpression(project, file, element1, element2) == null) {
+ if (smartIntroduce(file, editor, name, replaceAll, hasConstructor)) {
+ return;
+ }
+ }
}
if (element1 == null || element2 == null) {
CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.introduce.selection.error"), myDialogTitle,
@@ -120,11 +129,53 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
return;
}
- if (!checkEnabled(project, editor, element1, myDialogTitle)) {
+ performActionOnElement(editor, element1, name, replaceAll, hasConstructor);
+ }
+
+ private boolean smartIntroduce(final PsiFile file, final Editor editor, final String name, final boolean replaceAll, final boolean hasConstructor) {
+ int offset = editor.getCaretModel().getOffset();
+ PsiElement elementAtCaret = file.findElementAt(offset);
+ final List expressions = new ArrayList();
+ while (elementAtCaret != null) {
+ if (elementAtCaret instanceof PyStatement) {
+ break;
+ }
+ if (elementAtCaret instanceof PyExpression) {
+ expressions.add((PyExpression)elementAtCaret);
+ }
+ elementAtCaret = elementAtCaret.getParent();
+ }
+ if (expressions.size() == 1) {
+ performActionOnElement(editor, expressions.get(0), name, replaceAll, hasConstructor);
+ return true;
+ }
+ else if (expressions.size() > 1) {
+ IntroduceTargetChooser.showChooser(editor, expressions, new Pass() {
+ @Override
+ public void pass(PyExpression pyExpression) {
+ performActionOnElement(editor, pyExpression, name, replaceAll, hasConstructor);
+ }
+ }, new Function() {
+ public String fun(PyExpression pyExpression) {
+ return pyExpression.getText();
+ }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ private void performActionOnElement(Editor editor,
+ PsiElement element,
+ String name,
+ boolean replaceAll,
+ boolean hasConstructor) {
+ final Project project = element.getProject();
+ if (!checkEnabled(project, editor, element, myDialogTitle)) {
return;
}
- final PyExpression expression = (PyExpression)element1;
+ final PyExpression expression = (PyExpression)element;
final List occurrences;
if (expression.getUserData(PyPsiUtils.SELECTION_BREAKS_AST_NODE) == null && !(expression instanceof PyCallExpression)) {
diff --git a/python/testData/optimizeImports/importStarOneOfMultiple.after.py b/python/testData/optimizeImports/importStarOneOfMultiple.after.py
index 1e6589a19e4c..d98696221063 100644
--- a/python/testData/optimizeImports/importStarOneOfMultiple.after.py
+++ b/python/testData/optimizeImports/importStarOneOfMultiple.after.py
@@ -1,2 +1,3 @@
from re import compile
+
compile
\ No newline at end of file
diff --git a/python/testData/optimizeImports/oneOfMultiple.after.py b/python/testData/optimizeImports/oneOfMultiple.after.py
index 24d13554fc54..db49e72a894d 100644
--- a/python/testData/optimizeImports/oneOfMultiple.after.py
+++ b/python/testData/optimizeImports/oneOfMultiple.after.py
@@ -1,2 +1,3 @@
import sys
+
print sys.argv