summaryrefslogtreecommitdiff
path: root/python/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'python/src/com')
-rw-r--r--python/src/com/jetbrains/python/PyAddImportFix.java55
-rw-r--r--python/src/com/jetbrains/python/PyBundle.properties2
-rw-r--r--python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java3
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java2
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java17
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java34
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java33
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java53
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java40
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java20
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java66
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java25
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java15
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java30
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java19
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java50
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java28
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java74
-rw-r--r--python/src/com/jetbrains/python/console/PydevConsoleRunner.java116
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java127
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java33
-rw-r--r--python/src/com/jetbrains/python/console/RunPythonConsoleAction.java8
-rw-r--r--python/src/com/jetbrains/python/documentation/EpydocString.java7
-rw-r--r--python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java11
-rw-r--r--python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java24
-rw-r--r--python/src/com/jetbrains/python/documentation/SphinxDocString.java9
-rw-r--r--python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java26
-rw-r--r--python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java4
-rw-r--r--python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java2
-rw-r--r--python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java1
-rw-r--r--python/src/com/jetbrains/python/psi/PyUtil.java19
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java22
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java14
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyFileImpl.java5
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java30
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java21
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java14
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java10
-rw-r--r--python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java38
-rw-r--r--python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java57
-rw-r--r--python/src/com/jetbrains/python/run/PythonCommandLineState.java26
-rw-r--r--python/src/com/jetbrains/python/run/PythonRunConfiguration.java8
-rw-r--r--python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java7
-rw-r--r--python/src/com/jetbrains/python/run/PythonTracebackFilter.java14
-rw-r--r--python/src/com/jetbrains/python/sdk/PyDetectedSdk.java4
-rw-r--r--python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java8
-rw-r--r--python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java2
47 files changed, 880 insertions, 353 deletions
diff --git a/python/src/com/jetbrains/python/PyAddImportFix.java b/python/src/com/jetbrains/python/PyAddImportFix.java
new file mode 100644
index 000000000000..c13fed13fdcb
--- /dev/null
+++ b/python/src/com/jetbrains/python/PyAddImportFix.java
@@ -0,0 +1,55 @@
+package com.jetbrains.python;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.psi.PyImportStatementBase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Quick fix that adds import to file
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyAddImportFix implements LocalQuickFix {
+ @NotNull
+ private final String myImportToAdd;
+ @NotNull
+ private final PyFile myFile;
+
+ /**
+ * @param importToAdd string representing what to add (i.e. "from foo import bar")
+ * @param file where to add
+ */
+ public PyAddImportFix(@NotNull final String importToAdd, @NotNull final PyFile file) {
+ myImportToAdd = importToAdd;
+ myFile = file;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return PyBundle.message("QFIX.add.import", myImportToAdd);
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+ final PyImportStatementBase statement =
+ generator.createFromText(LanguageLevel.forElement(myFile), PyImportStatementBase.class, myImportToAdd);
+ final PsiElement recommendedPosition = AddImportHelper.getFileInsertPosition(myFile);
+ myFile.addAfter(statement, recommendedPosition);
+ }
+}
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 5d29d3f79d50..482daa88b66c 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -32,6 +32,8 @@ QFIX.create.property=Create property
QFIX.add.encoding=Add encoding declaration
+QFIX.add.import=Add "''{0}''"
+
QFIX.NAME.parameters=Parameters of functions and methods
QFIX.rename.parameter.to.$0=Rename to ''{0}''
diff --git a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
index 58b35fe5f591..cb90d498e663 100644
--- a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
+++ b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
@@ -17,7 +17,6 @@ package com.jetbrains.python.actions;
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.*;
@@ -215,7 +214,7 @@ public class ExecuteInConsoleAction extends AnAction {
private static void startConsole(final Project project,
final Consumer<PyCodeExecutor> consumer,
Module context) {
- PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context);
+ PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context, null);
runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
@Override
public void handleConsoleInitialized(LanguageConsoleView consoleView) {
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
index e27f2a638899..2785b23afc56 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
@@ -79,7 +79,7 @@ public class PySmartEnterProcessor extends SmartEnterProcessor {
}
final PsiElement[] children = element.getChildren();
- for (PsiElement child : children) {
+ for (final PsiElement child : children) {
if (element instanceof PyStatement && child instanceof PyStatement) {
continue;
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
index ac2e31252dcf..ccdcf1b93f2a 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
@@ -20,7 +20,9 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil;
-import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementListContainer;
+import com.jetbrains.python.psi.PyStatementPart;
import org.jetbrains.annotations.Nullable;
/**
@@ -32,17 +34,8 @@ import org.jetbrains.annotations.Nullable;
public class PyPlainEnterProcessor implements EnterProcessor {
@Nullable
private static PyStatementList getStatementList(PsiElement psiElement, Editor editor) {
- if (psiElement instanceof PyStatementPart) {
- return ((PyStatementPart)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyFunction) {
- return ((PyFunction)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyClass) {
- return ((PyClass)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyWithStatement) {
- return PsiTreeUtil.getChildOfType(psiElement, PyStatementList.class);
+ if (psiElement instanceof PyStatementListContainer) {
+ return ((PyStatementListContainer)psiElement).getStatementList();
}
else {
final CaretModel caretModel = editor.getCaretModel();
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
index f7d877e5bb5b..de90fa158bab 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
@@ -25,26 +25,30 @@ import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* @author Alexey.Ivanov
*/
-public class PyArgumentListFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyArgumentList) {
- final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
- if (psiElement.getParent() instanceof PyClass || psiElement.getParent() instanceof PyDecorator) {
- final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
- if (lBrace != null && rBrace == null) {
- final Document document = editor.getDocument();
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyArgumentListFixer extends PyFixer<PyArgumentList> {
+ public PyArgumentListFixer() {
+ super(PyArgumentList.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyArgumentList arguments) throws IncorrectOperationException {
+ final PsiElement rBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0);
+ if (arguments.getParent() instanceof PyClass || arguments.getParent() instanceof PyDecorator) {
+ final PsiElement lBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0);
+ if (lBrace != null && rBrace == null) {
+ final Document document = editor.getDocument();
+ document.insertString(arguments.getTextRange().getEndOffset(), ")");
}
- else {
- if (rBrace == null) {
- final Document document = editor.getDocument();
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+ }
+ else {
+ if (rBrace == null) {
+ final Document document = editor.getDocument();
+ document.insertString(arguments.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
index b9846e1cb894..ce51d6d46824 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
@@ -17,7 +17,6 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
@@ -25,6 +24,9 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,21 +34,22 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 18:41:08
*/
-public class PyClassFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyClass) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- final PyClass aClass = (PyClass)psiElement;
- final PyArgumentList argList = PsiTreeUtil.getChildOfType(aClass, PyArgumentList.class);
- int offset = argList.getTextRange().getEndOffset();
- String textToInsert = ":";
- if (aClass.getNameNode() == null) {
- processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
- textToInsert = " :";
- }
- editor.getDocument().insertString(offset, textToInsert);
+public class PyClassFixer extends PyFixer<PyClass> {
+ public PyClassFixer() {
+ super(PyClass.class);
+ }
+
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyClass pyClass) throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(pyClass, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class);
+ final int offset = sure(argList).getTextRange().getEndOffset();
+ String textToInsert = ":";
+ if (pyClass.getNameNode() == null) {
+ processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
+ textToInsert = " :";
}
+ editor.getDocument().insertString(offset, textToInsert);
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
index 2885c63f6345..f71c61261103 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
@@ -25,6 +25,9 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
import com.jetbrains.python.psi.PyConditionalStatementPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,31 +35,35 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 15.04.2010
* Time: 19:33:14
*/
-public class PyConditionalStatementPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyConditionalStatementPart) {
- final PyConditionalStatementPart conditionalStatementPart = (PyConditionalStatementPart)psiElement;
- final PyExpression condition = conditionalStatementPart.getCondition();
- final Document document = editor.getDocument();
- final PsiElement colon = PyUtil.getChildByFilter(conditionalStatementPart, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- if (condition != null) {
- final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
- if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
- document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
- }
- }
- else {
- final PsiElement keywordToken = PyUtil.getChildByFilter(conditionalStatementPart,
- TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD,
- PyTokenTypes.WHILE_KEYWORD), 0);
- final int offset = keywordToken.getTextRange().getEndOffset();
- document.insertString(offset, " :");
- processor.registerUnresolvedError(offset + 1);
+public class PyConditionalStatementPartFixer extends PyFixer<PyConditionalStatementPart> {
+ public PyConditionalStatementPartFixer() {
+ super(PyConditionalStatementPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyConditionalStatementPart statementPart)
+ throws IncorrectOperationException {
+ final PyExpression condition = statementPart.getCondition();
+ final Document document = editor.getDocument();
+ final PsiElement colon = PyUtil.getFirstChildOfType(statementPart, PyTokenTypes.COLON);
+ if (colon == null) {
+ if (condition != null) {
+ final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
+ if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
+ document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
}
- } else if (condition == null) {
- processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
}
+ else {
+ final TokenSet keywords = TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD, PyTokenTypes.WHILE_KEYWORD);
+ final PsiElement keywordToken = PyUtil.getChildByFilter(statementPart,
+ keywords, 0);
+ final int offset = sure(keywordToken).getTextRange().getEndOffset();
+ document.insertString(offset, " :");
+ processor.registerUnresolvedError(offset + 1);
+ }
+ }
+ else if (condition == null) {
+ processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
index 8e3532cb49b3..67d5ff5c9ee5 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
@@ -17,13 +17,15 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyExceptPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -31,24 +33,26 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 22.04.2010
* Time: 18:13:34
*/
-public class PyExceptFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyExceptPart) {
- PyExceptPart exceptPart = (PyExceptPart)psiElement;
- final PsiElement colon = PyUtil.getChildByFilter(exceptPart, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- int offset = PyUtil.getChildByFilter(exceptPart,
- TokenSet.create(PyTokenTypes.EXCEPT_KEYWORD), 0).getTextRange().getEndOffset();
- final PyExpression exceptClass = exceptPart.getExceptClass();
- if (exceptClass != null) {
- offset = exceptClass.getTextRange().getEndOffset();
- }
- final PyExpression target = exceptPart.getTarget();
- if (target != null) {
- offset = target.getTextRange().getEndOffset();
- }
- editor.getDocument().insertString(offset, ":");
+public class PyExceptFixer extends PyFixer<PyExceptPart> {
+ public PyExceptFixer() {
+ super(PyExceptPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyExceptPart exceptPart) throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PsiElement exceptToken = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD);
+ int offset = sure(exceptToken).getTextRange().getEndOffset();
+ final PyExpression exceptClass = exceptPart.getExceptClass();
+ if (exceptClass != null) {
+ offset = exceptClass.getTextRange().getEndOffset();
+ }
+ final PyExpression target = exceptPart.getTarget();
+ if (target != null) {
+ offset = target.getTextRange().getEndOffset();
}
+ editor.getDocument().insertString(offset, ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
index f02831d92d36..0ebdceb20e37 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
@@ -19,6 +19,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -26,6 +28,20 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
* Date: 15.04.2010
* Time: 17:10:33
*/
-public interface PyFixer {
- void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException;
+public abstract class PyFixer<T extends PyElement> {
+ private final Class<T> myClass;
+
+ public PyFixer(@NotNull Class<T> aClass) {
+ myClass = aClass;
+ }
+
+ public final void apply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PsiElement element)
+ throws IncorrectOperationException {
+ if (myClass.isInstance(element)) {
+ //noinspection unchecked
+ doApply(editor, processor, (T)element);
+ }
+ }
+
+ public abstract void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull T element);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
index 1b8b438c68fd..eefe5cd1fc3e 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
@@ -18,12 +18,13 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyForPart;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -31,41 +32,42 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 16:03:43
*/
-public class PyForPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyForPart) {
- final PyForPart forPart = (PyForPart)psiElement;
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- final Document document = editor.getDocument();
- final PsiElement forToken = PyUtil.getChildByFilter(forPart,
- TokenSet.create(PyTokenTypes.FOR_KEYWORD), 0);
- if (colon == null) {
- String textToInsert = ":";
- PsiElement sourceOrTarget = forPart.getSource();
- PsiElement positionToInsert = sourceOrTarget;
- if (sourceOrTarget == null) {
- sourceOrTarget = forPart.getTarget();
- final PsiElement inToken = PyUtil.getChildByFilter(forPart, TokenSet.create(PyTokenTypes.IN_KEYWORD), 0);
- if (inToken == null) {
- if (sourceOrTarget == null) {
- positionToInsert = forToken;
- textToInsert = " in :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
- }
- else {
- positionToInsert = sourceOrTarget;
- textToInsert = " in :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
- }
+public class PyForPartFixer extends PyFixer<PyForPart> {
+ public PyForPartFixer() {
+ super(PyForPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyForPart forPart) {
+ final PsiElement colon = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.COLON);
+ final Document document = editor.getDocument();
+ final PsiElement forToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD);
+ if (colon == null) {
+ String textToInsert = ":";
+ PsiElement sourceOrTarget = forPart.getSource();
+ PsiElement positionToInsert = sourceOrTarget;
+ if (sourceOrTarget == null) {
+ sourceOrTarget = forPart.getTarget();
+ final PsiElement inToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD);
+ if (inToken == null) {
+ if (sourceOrTarget == null) {
+ positionToInsert = sure(forToken);
+ textToInsert = " in :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
}
else {
- positionToInsert = inToken;
- textToInsert = " :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
+ positionToInsert = sourceOrTarget;
+ textToInsert = " in :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
}
}
- document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
+ else {
+ positionToInsert = inToken;
+ textToInsert = " :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
+ }
}
+ document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
index f1988e13f57a..ad959f80ccae 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
@@ -18,13 +18,13 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -32,16 +32,19 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 16:59:07
*/
-public class PyFunctionFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyFunction) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- final PyFunction function = (PyFunction)psiElement;
- final PyParameterList parameterList = function.getParameterList();
- final Document document = editor.getDocument();
- document.insertString(parameterList.getTextRange().getEndOffset(), ":");
- }
+public class PyFunctionFixer extends PyFixer<PyFunction> {
+ public PyFunctionFixer() {
+ super(PyFunction.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyFunction function)
+ throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(function, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PyParameterList parameterList = function.getParameterList();
+ final Document document = editor.getDocument();
+ document.insertString(parameterList.getTextRange().getEndOffset(), ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
index 0d8565d6960d..eb97d2bdb372 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -27,10 +28,16 @@ import com.jetbrains.python.psi.*;
* Date: 15.04.2010
* Time: 17:55:46
*/
-public class PyMissingBracesFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyMissingBracesFixer extends PyFixer<PyElement> {
+ public PyMissingBracesFixer() {
+ super(PyElement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+ throws IncorrectOperationException {
if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) {
- PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+ final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
if (lastChild != null && !"}".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}");
}
@@ -38,7 +45,7 @@ public class PyMissingBracesFixer implements PyFixer {
else if (psiElement instanceof PyListLiteralExpression ||
psiElement instanceof PySliceExpression ||
psiElement instanceof PySubscriptionExpression) {
- PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+ final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
if (lastChild != null && !"]".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]");
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
index 7b5970d7baf2..69a06b8b7c48 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
@@ -23,6 +23,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -30,19 +31,22 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 17:25:46
*/
-public class PyParameterListFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyParameterList) {
- final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
- final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
- if (lBrace == null || rBrace == null) {
- final Document document = editor.getDocument();
- if (lBrace == null) {
- document.insertString(psiElement.getTextRange().getStartOffset(), "(");
- }
- else {
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyParameterListFixer extends PyFixer<PyParameterList> {
+ public PyParameterListFixer() {
+ super(PyParameterList.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParameterList psiElement) throws IncorrectOperationException {
+ final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
+ final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
+ if (lBrace == null || rBrace == null) {
+ final Document document = editor.getDocument();
+ if (lBrace == null) {
+ document.insertString(psiElement.getTextRange().getStartOffset(), "(");
+ }
+ else {
+ document.insertString(psiElement.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
index a055375bc040..582e034c5603 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyParenthesizedExpression;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -27,13 +28,17 @@ import com.jetbrains.python.psi.PyParenthesizedExpression;
* Date: 15.04.2010
* Time: 17:42:08
*/
-public class PyParenthesizedFixer implements PyFixer {
- public void apply(final Editor editor, final PySmartEnterProcessor processor, final PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyParenthesizedExpression) {
- final PsiElement lastChild = psiElement.getLastChild();
- if (lastChild != null && !")".equals(lastChild.getText())) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyParenthesizedFixer extends PyFixer<PyParenthesizedExpression> {
+ public PyParenthesizedFixer() {
+ super(PyParenthesizedExpression.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParenthesizedExpression expression)
+ throws IncorrectOperationException {
+ final PsiElement lastChild = expression.getLastChild();
+ if (lastChild != null && !")".equals(lastChild.getText())) {
+ editor.getDocument().insertString(expression.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
index 906aecd9c757..3e9925a86131 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
@@ -17,10 +17,10 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyStringLiteralExpression;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -28,31 +28,35 @@ import com.jetbrains.python.psi.PyStringLiteralExpression;
* Date: 15.04.2010
* Time: 17:17:14
*/
-public class PyStringLiteralFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyStringLiteralExpression) {
- final String text = psiElement.getText();
- if (StringUtil.startsWith(text, "\"\"\"")) {
- final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
- if (suffixLength != 3) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
- }
+public class PyStringLiteralFixer extends PyFixer<PyStringLiteralExpression> {
+ public PyStringLiteralFixer() {
+ super(PyStringLiteralExpression.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyStringLiteralExpression psiElement)
+ throws IncorrectOperationException {
+ final String text = psiElement.getText();
+ if (StringUtil.startsWith(text, "\"\"\"")) {
+ final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
+ if (suffixLength != 3) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
}
- else if (StringUtil.startsWith(text, "\'\'\'")) {
- final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
- if (suffixLength != 3) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
- }
+ }
+ else if (StringUtil.startsWith(text, "\'\'\'")) {
+ final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
+ if (suffixLength != 3) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
}
- else if (StringUtil.startsWith(text, "\"")) {
- if (!StringUtil.endsWith(text, "\"")) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
- }
+ }
+ else if (StringUtil.startsWith(text, "\"")) {
+ if (!StringUtil.endsWith(text, "\"")) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
}
- else if (StringUtil.startsWith(text, "\'")) {
- if (!StringUtil.endsWith(text, "\'")) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
- }
+ }
+ else if (StringUtil.startsWith(text, "\'")) {
+ if (!StringUtil.endsWith(text, "\'")) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
index 57bfd39f4f85..6aace3972a1b 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
@@ -21,10 +21,10 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyFinallyPart;
-import com.jetbrains.python.psi.PyTryPart;
-import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,16 +32,20 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 14:25:20
*/
-public class PyUnconditionalStatementPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyUnconditionalStatementPartFixer extends PyFixer<PyElement> {
+ public PyUnconditionalStatementPartFixer() {
+ super(PyElement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+ throws IncorrectOperationException {
if (PyUtil.instanceOf(psiElement, PyElsePart.class, PyTryPart.class, PyFinallyPart.class)) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
+ final PsiElement colon = PyUtil.getFirstChildOfType(psiElement, PyTokenTypes.COLON);
if (colon == null) {
- final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement,
- TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD,
- PyTokenTypes.FINALLY_KEYWORD),
- 0);
- editor.getDocument().insertString(keywordToken.getTextRange().getEndOffset(), ":");
+ final TokenSet keywords = TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD, PyTokenTypes.FINALLY_KEYWORD);
+ final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement, keywords, 0);
+ editor.getDocument().insertString(sure(keywordToken).getTextRange().getEndOffset(), ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
index b6d099ef7cb5..ec236d9242f5 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
@@ -15,65 +15,59 @@
*/
package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
-import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElementType;
import com.jetbrains.python.psi.PyExpression;
+import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.PyWithItem;
import com.jetbrains.python.psi.PyWithStatement;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import static com.jetbrains.python.psi.PyUtil.sure;
/**
* @author Mikhail Golubev
*/
-public class PyWithFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyWithStatement) {
- final PyWithStatement withStatement = (PyWithStatement)psiElement;
- final PsiElement colonToken = getFirstChildOfType(psiElement, PyTokenTypes.COLON);
- final PsiElement withToken = getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
- final Document document = editor.getDocument();
- if (colonToken == null) {
- int insertAt = sure(withToken).getTextRange().getEndOffset();
- String textToInsert = ":";
- final PyWithItem[] withItems = withStatement.getWithItems();
- final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
- if (lastItem == null || lastItem.getExpression() == null) {
- textToInsert = " :";
- processor.registerUnresolvedError(insertAt + 1);
- }
- else {
- final PyExpression expression = lastItem.getExpression();
- insertAt = expression.getTextRange().getEndOffset();
- final PsiElement asToken = getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
- if (asToken != null) {
- insertAt = asToken.getTextRange().getEndOffset();
- final PyExpression target = lastItem.getTarget();
- if (target != null) {
- insertAt = target.getTextRange().getEndOffset();
- }
- else {
- textToInsert = " :";
- processor.registerUnresolvedError(insertAt + 1);
- }
+public class PyWithFixer extends PyFixer<PyWithStatement> {
+ public PyWithFixer() {
+ super(PyWithStatement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException {
+ final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
+ final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
+ final Document document = editor.getDocument();
+ if (colonToken == null) {
+ int insertAt = sure(withToken).getTextRange().getEndOffset();
+ String textToInsert = ":";
+ final PyWithItem[] withItems = withStatement.getWithItems();
+ final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
+ if (lastItem == null || lastItem.getExpression() == null) {
+ textToInsert = " :";
+ processor.registerUnresolvedError(insertAt + 1);
+ }
+ else {
+ final PyExpression expression = lastItem.getExpression();
+ insertAt = expression.getTextRange().getEndOffset();
+ final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
+ if (asToken != null) {
+ insertAt = asToken.getTextRange().getEndOffset();
+ final PyExpression target = lastItem.getTarget();
+ if (target != null) {
+ insertAt = target.getTextRange().getEndOffset();
+ }
+ else {
+ textToInsert = " :";
+ processor.registerUnresolvedError(insertAt + 1);
}
}
- document.insertString(insertAt, textToInsert);
}
+ document.insertString(insertAt, textToInsert);
}
}
-
- @Nullable
- private static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
- final ASTNode child = element.getNode().findChildByType(type);
- return child != null ? child.getPsi() : null;
- }
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 3d77ac4f62b1..848818b95e27 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -16,6 +16,10 @@
package com.jetbrains.python.console;
import com.google.common.base.CharMatcher;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionHelper;
@@ -59,11 +63,14 @@ import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.remote.RemoteSshProcess;
import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.ui.content.Content;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.PathMappingSettings;
@@ -132,6 +139,9 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
private static final long APPROPRIATE_TO_WAIT = 60000;
private PyRemoteSdkCredentials myRemoteCredentials;
+ private ToolWindow myToolWindow;
+
+ private String myConsoleTitle = null;
protected PydevConsoleRunner(@NotNull final Project project,
@NotNull Sdk sdk, @NotNull final PyConsoleType consoleType,
@@ -192,8 +202,10 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
@NotNull final PyConsoleType consoleType,
@Nullable final String workingDirectory,
@NotNull final Map<String, String> environmentVariables,
+ @Nullable final ToolWindow toolWindow,
final String... statements2execute) {
final PydevConsoleRunner consoleRunner = create(project, sdk, consoleType, workingDirectory, environmentVariables);
+ consoleRunner.setToolWindow(toolWindow);
consoleRunner.setStatementsToExecute(statements2execute);
consoleRunner.run();
return consoleRunner;
@@ -481,6 +493,20 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
}
+ @Override
+ protected String constructConsoleTitle(@NotNull String consoleTitle) {
+ if (myConsoleTitle == null) {
+ myConsoleTitle = super.constructConsoleTitle(consoleTitle);
+ }
+ return myConsoleTitle;
+ }
+
+ @Override
+ protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
+ PythonConsoleToolWindow terminalView = PythonConsoleToolWindow.getInstance(getProject());
+ terminalView.init(getToolWindow(), contentDescriptor);
+ }
+
protected AnAction createRerunAction() {
return new RestartAction(this);
}
@@ -583,9 +609,32 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
@Override
- protected AnAction createCloseAction(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
- final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, myDescriptor);
- return createConsoleStoppingAction(generalCloseAction);
+ protected AnAction createCloseAction(Executor defaultExecutor, final RunContentDescriptor descriptor) {
+ final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, descriptor);
+
+ final AnAction stopAction = new DumbAwareAction() {
+ @Override
+ public void update(AnActionEvent e) {
+ generalCloseAction.update(e);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ e = stopConsole(e);
+
+ clearContent(descriptor);
+
+ generalCloseAction.actionPerformed(e);
+ }
+ };
+ stopAction.copyFrom(generalCloseAction);
+ return stopAction;
+ }
+
+ private void clearContent(RunContentDescriptor descriptor) {
+ Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName());
+ assert content != null;
+ getToolWindow().getContentManager().removeContent(content, true);
}
private AnAction createConsoleStoppingAction(final AnAction generalStopAction) {
@@ -597,26 +646,31 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
@Override
public void actionPerformed(AnActionEvent e) {
- if (myPydevConsoleCommunication != null) {
- final AnActionEvent furtherActionEvent =
- new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
- e.getPresentation(), e.getActionManager(), e.getModifiers());
- try {
- closeCommunication();
- // waiting for REPL communication before destroying process handler
- Thread.sleep(300);
- }
- catch (Exception ignored) {
- // Ignore
- }
- generalStopAction.actionPerformed(furtherActionEvent);
- }
+ e = stopConsole(e);
+
+ generalStopAction.actionPerformed(e);
}
};
stopAction.copyFrom(generalStopAction);
return stopAction;
}
+ private AnActionEvent stopConsole(AnActionEvent e) {
+ if (myPydevConsoleCommunication != null) {
+ e = new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
+ e.getPresentation(), e.getActionManager(), e.getModifiers());
+ try {
+ closeCommunication();
+ // waiting for REPL communication before destroying process handler
+ Thread.sleep(300);
+ }
+ catch (Exception ignored) {
+ // Ignore
+ }
+ }
+ return e;
+ }
+
protected AnAction createSplitLineAction() {
class ConsoleSplitLineAction extends EditorAction {
@@ -738,6 +792,17 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
}
+ public ToolWindow getToolWindow() {
+ if (myToolWindow == null) {
+ myToolWindow = ToolWindowManager.getInstance(getProject()).getToolWindow(PythonConsoleToolWindowFactory.ID);
+ }
+ return myToolWindow;
+ }
+
+ public void setToolWindow(ToolWindow toolWindow) {
+ myToolWindow = toolWindow;
+ }
+
public interface ConsoleListener {
void handleConsoleInitialized(LanguageConsoleView consoleView);
}
@@ -889,4 +954,21 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
return session;
}
+
+ @Override
+ protected List<String> getActiveConsoleNames(final String consoleTitle) {
+ return FluentIterable.from(
+ Lists.newArrayList(PythonConsoleToolWindow.getInstance(getProject()).getToolWindow().getContentManager().getContents())).transform(
+ new Function<Content, String>() {
+ @Override
+ public String apply(Content input) {
+ return input.getDisplayName();
+ }
+ }).filter(new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return input.contains(consoleTitle);
+ }
+ }).toList();
+ }
}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
new file mode 100644
index 000000000000..e8c50e49280a
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
@@ -0,0 +1,127 @@
+package com.jetbrains.python.console;
+
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.SimpleToolWindowPanel;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
+import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
+import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindow {
+
+ private final Project myProject;
+
+ private boolean myInitialized = false;
+
+ public PythonConsoleToolWindow(Project project) {
+ myProject = project;
+ }
+
+ public static PythonConsoleToolWindow getInstance(@NotNull Project project) {
+ return project.getComponent(PythonConsoleToolWindow.class);
+ }
+
+
+ public void init(final @NotNull ToolWindow toolWindow, final @NotNull RunContentDescriptor contentDescriptor) {
+ addContent(toolWindow, contentDescriptor);
+
+ if (!myInitialized) {
+ doInit(toolWindow);
+ }
+ }
+
+ private void doInit(final ToolWindow toolWindow) {
+ myInitialized = true;
+
+ toolWindow.setToHideOnEmptyContent(true);
+
+ ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerListener() {
+ @Override
+ public void toolWindowRegistered(@NotNull String id) {
+ }
+
+ @Override
+ public void stateChanged() {
+ ToolWindow window = getToolWindow();
+ if (window != null) {
+ boolean visible = window.isVisible();
+ if (visible && toolWindow.getContentManager().getContentCount() == 0) {
+ RunPythonConsoleAction.runPythonConsole(myProject, null, toolWindow);
+ }
+ }
+ }
+ });
+ }
+
+ private static void addContent(ToolWindow toolWindow, RunContentDescriptor contentDescriptor) {
+ toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
+
+ Content content = toolWindow.getContentManager().findContent(contentDescriptor.getDisplayName());
+ if (content == null) {
+ content = createContent(contentDescriptor);
+ toolWindow.getContentManager().addContent(content);
+ }
+ else {
+ SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+ resetContent(contentDescriptor, panel, content);
+ }
+
+ toolWindow.getContentManager().setSelectedContent(content);
+ }
+
+ public ToolWindow getToolWindow() {
+ return ToolWindowManager.getInstance(myProject).getToolWindow(PythonConsoleToolWindowFactory.ID);
+ }
+
+ private static Content createContent(final @NotNull RunContentDescriptor contentDescriptor) {
+ SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+
+ final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, contentDescriptor.getDisplayName(), false);
+ content.setCloseable(true);
+
+ resetContent(contentDescriptor, panel, content);
+
+ return content;
+ }
+
+ private static void resetContent(RunContentDescriptor contentDescriptor, SimpleToolWindowPanel panel, Content content) {
+ panel.setContent(contentDescriptor.getComponent());
+ //panel.addFocusListener(createFocusListener(toolWindow));
+
+ content.setComponent(panel);
+ content.setPreferredFocusableComponent(contentDescriptor.getComponent());
+ }
+
+ private static FocusListener createFocusListener(final ToolWindow toolWindow) {
+ return new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ JComponent component = getComponentToFocus(toolWindow);
+ if (component != null) {
+ component.requestFocusInWindow();
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ }
+ };
+ }
+
+ private static JComponent getComponentToFocus(ToolWindow window) {
+ return window.getContentManager().getComponent();
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
new file mode 100644
index 000000000000..f042a539bc22
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.console;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowFactory;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindowFactory implements ToolWindowFactory, DumbAware {
+ public static final String ID = "Python Console";
+
+ @Override
+ public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ RunPythonConsoleAction.runPythonConsole(project, null, toolWindow);
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
index 02a153f7a016..566adea43c87 100644
--- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
+++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
@@ -32,6 +32,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
import com.intellij.util.PathMappingSettings;
import com.jetbrains.python.buildout.BuildoutFacet;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
@@ -42,6 +43,7 @@ import com.jetbrains.python.sdk.PythonEnvUtil;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
@@ -77,11 +79,11 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware {
public void actionPerformed(final AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
- runPythonConsole(project, e.getData(LangDataKeys.MODULE));
+ runPythonConsole(project, e.getData(LangDataKeys.MODULE), null);
}
@NotNull
- public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule) {
+ public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule, @Nullable ToolWindow toolWindow) {
assert project != null : "Project is null";
Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule);
@@ -152,7 +154,7 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware {
envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
return PydevConsoleRunner
- .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, setupFragment);
+ .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, toolWindow, setupFragment);
}
public static PathMappingSettings getMappings(Project project, Sdk sdk) {
diff --git a/python/src/com/jetbrains/python/documentation/EpydocString.java b/python/src/com/jetbrains/python/documentation/EpydocString.java
index 132ef4924b5c..3d0fc3e89d9e 100644
--- a/python/src/com/jetbrains/python/documentation/EpydocString.java
+++ b/python/src/com/jetbrains/python/documentation/EpydocString.java
@@ -44,6 +44,13 @@ public class EpydocString extends StructuredDocStringBase {
"precondition", "postcondition", "invariant", "author", "organization", "copyright", "license", "contact", "summary", "see"
};
+ /**
+ * Empty doc (for {@link #createParameterType(String, String)} probably)
+ */
+ public EpydocString() {
+ this("");
+ }
+
public EpydocString(@NotNull String docstringText) {
super(docstringText, "@");
}
diff --git a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
index d09af58f4fc3..c05069098ea6 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
@@ -87,8 +87,6 @@ public class PyDocstringGenerator {
for (PyParameter functionParam : function.getParameterList().getParameters()) {
String paramName = functionParam.getName();
if (!functionParam.isSelf() && !StringUtil.isEmpty(paramName)) {
- assert paramName != null;
-
String type = signature != null ? signature.getArgTypeQualifiedName(paramName) : null;
if (type != null) {
@@ -140,12 +138,9 @@ public class PyDocstringGenerator {
final VirtualFile virtualFile = myFile.getVirtualFile();
if (virtualFile == null) return;
- OpenFileDescriptor descriptor = new OpenFileDescriptor(
- myProject, virtualFile, myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
- );
+ OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, virtualFile, myDocStringExpression.getTextOffset());
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
if (targetEditor != null) {
- targetEditor.getCaretModel().moveToOffset(myDocStringExpression.getTextOffset());
TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
}
}
@@ -298,7 +293,7 @@ public class PyDocstringGenerator {
if (myDocStringOwner instanceof PyFunction) {
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
- if (document != null && statementList != null && myFunction != null && statementList.getStatements().length != 0
+ if (document != null && myFunction != null && statementList.getStatements().length != 0
&& document.getLineNumber(statementList.getTextOffset()) != document.getLineNumber(myFunction.getTextOffset())) {
whitespace = PsiTreeUtil.getPrevSiblingOfType(statementList, PsiWhiteSpace.class);
}
@@ -411,7 +406,7 @@ public class PyDocstringGenerator {
final PyStatementList list = myFunction.getStatementList();
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
- if (document != null && list != null) {
+ if (document != null) {
if (document.getLineNumber(list.getTextOffset()) == document.getLineNumber(myFunction.getTextOffset()) ||
list.getStatements().length == 0) {
PyFunction func = elementGenerator.createFromText(LanguageLevel.forElement(myFunction),
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
index 6ea65405ba1a..49a17efd28a6 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
@@ -15,7 +15,9 @@
*/
package com.jetbrains.python.documentation;
-import com.intellij.openapi.components.*;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.openapi.util.text.StringUtil;
@@ -27,6 +29,7 @@ import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -54,7 +57,7 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
private boolean isFormat(PsiFile file, final String format) {
if (file instanceof PyFile) {
- PyTargetExpression expr = ((PyFile) file).findTopLevelAttribute(PyNames.DOCFORMAT);
+ PyTargetExpression expr = ((PyFile)file).findTopLevelAttribute(PyNames.DOCFORMAT);
if (expr != null) {
String docformat = PyPsiUtils.strValue(expr.findAssignedValue());
if (docformat != null) {
@@ -88,4 +91,21 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
public void loadState(PyDocumentationSettings state) {
XmlSerializerUtil.copyBean(state, this);
}
+
+ /**
+ * TODO: Use this factory for the whole document infrastructure to simplify new documentation engine support
+ * Factory that returns appropriate instance of {@link StructuredDocStringBase} if specificed
+ *
+ * @return instance or null if no doctype os set
+ */
+ @Nullable
+ public StructuredDocStringBase getDocString() {
+ if (myDocStringFormat.equals(DocStringFormat.EPYTEXT)) {
+ return new EpydocString();
+ }
+ if (myDocStringFormat.equals(DocStringFormat.REST)) {
+ return new SphinxDocString();
+ }
+ return null;
+ }
}
diff --git a/python/src/com/jetbrains/python/documentation/SphinxDocString.java b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
index ae5c7056a90b..c04e1c9471cf 100644
--- a/python/src/com/jetbrains/python/documentation/SphinxDocString.java
+++ b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
@@ -31,7 +31,14 @@ public class SphinxDocString extends StructuredDocStringBase {
":type", ":raise", ":raises", ":var", ":cvar", ":ivar",
":return", ":returns", ":rtype", ":except", ":exception" };
- public SphinxDocString(@NotNull String docstringText) {
+ /**
+ * Empty doc (for {@link #createParameterType(String, String)} probably)
+ */
+ public SphinxDocString() {
+ this("");
+ }
+
+ public SphinxDocString(@NotNull final String docstringText) {
super(docstringText, ":");
}
diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
index 9f6cecba7a84..36b70ec0f76a 100644
--- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
+++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
@@ -43,18 +43,21 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
private static final Pattern RE_LOOSE_TAG_LINE = Pattern.compile("([a-z]+) ([a-zA-Z_0-9]*):?([^:]*)");
private static final Pattern RE_ARG_TYPE = Pattern.compile("(.*) ([a-zA-Z_0-9]+)");
- public static String[] PARAM_TAGS = new String[] { "param", "parameter", "arg", "argument" };
- public static String[] PARAM_TYPE_TAGS = new String[] { "type" };
- public static String[] VARIABLE_TAGS = new String[] { "ivar", "cvar", "var" };
+ public static String[] PARAM_TAGS = new String[]{"param", "parameter", "arg", "argument"};
+ public static String[] PARAM_TYPE_TAGS = new String[]{"type"};
+ public static String[] VARIABLE_TAGS = new String[]{"ivar", "cvar", "var"};
- public static String[] RAISES_TAGS = new String[] { "raises", "raise", "except", "exception" };
- public static String[] RETURN_TAGS = new String[] { "return", "returns" };
+ public static String[] RAISES_TAGS = new String[]{"raises", "raise", "except", "exception"};
+ public static String[] RETURN_TAGS = new String[]{"return", "returns"};
+ @NotNull
+ private final String myTagPrefix;
public enum ReferenceType {PARAMETER, PARAMETER_TYPE, KEYWORD, VARIABLE, CLASS_VARIABLE, INSTANCE_VARIABLE}
public static String TYPE = "type";
protected StructuredDocStringBase(@NotNull String docStringText, String tagPrefix) {
+ myTagPrefix = tagPrefix;
final Substring docString = new Substring(docStringText);
final List<Substring> lines = docString.splitLines();
final int nlines = lines.size();
@@ -74,6 +77,12 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
}
@Override
+ @NotNull
+ public String createParameterType(@NotNull final String name, @NotNull final String type) {
+ return myTagPrefix + TYPE + String.format(" %s %s", name, type);
+ }
+
+ @Override
public String getDescription() {
return myDescription;
}
@@ -82,8 +91,9 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
public String getSummary() {
final List<String> strings = StringUtil.split(StringUtil.trimLeading(myDescription), "\n", true, false);
if (strings.size() > 1) {
- if (strings.get(1).isEmpty())
+ if (strings.get(1).isEmpty()) {
return strings.get(0);
+ }
}
return "";
}
@@ -216,8 +226,8 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
@Override
@Nullable
- public Substring getParamByNameAndKind(@NotNull String name, String kind) {
- for (Substring s: getTagArguments(kind)) {
+ public Substring getParamByNameAndKind(@NotNull String name, String kind) {
+ for (Substring s : getTagArguments(kind)) {
if (name.equals(s.getValue())) {
return s;
}
diff --git a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
index 4584f06ae8d9..6c86e72b1bcd 100644
--- a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
+++ b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
@@ -78,12 +78,12 @@ public abstract class PyInspectionVisitor extends PyElementVisitor {
protected final void registerProblem(@Nullable final PsiElement element,
@NotNull final String message,
- @NotNull final LocalQuickFix quickFix) {
+ @NotNull final LocalQuickFix... quickFixes) {
if (element == null || element.getTextLength() == 0) {
return;
}
if (myHolder != null) {
- myHolder.registerProblem(element, message, quickFix);
+ myHolder.registerProblem(element, message, quickFixes);
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
index 8b6143ffe092..b2ad485c24f8 100644
--- a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
@@ -99,7 +99,7 @@ public class PyShadowingNamesInspection extends PyInspection {
final ScopeOwner nextOwner = ScopeUtil.getScopeOwner(owner);
if (nextOwner != null) {
final ResolveProcessor processor = new ResolveProcessor(name);
- PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null);
+ PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null, null);
final PsiElement resolved = processor.getResult();
if (resolved != null) {
final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(resolved, PyComprehensionElement.class);
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
index 0ae7ac1c7812..708e91743730 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
@@ -27,6 +27,7 @@ import com.jetbrains.python.psi.PyExpression;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+//TODO: Remove pydoc aswell
public class PyRemoveArgumentQuickFix implements LocalQuickFix {
@NotNull
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 877da8df6dd9..cd4e582bb6f2 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -901,6 +901,20 @@ public class PyUtil {
}
/**
+ * Returns first child psi element with specified element type or {@code null} if no such element exists.
+ * Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
+ *
+ * @param element tree parent node
+ * @param type element type expected
+ * @return child element described
+ */
+ @Nullable
+ public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
+ final ASTNode child = element.getNode().findChildByType(type);
+ return child != null ? child.getPsi() : null;
+ }
+
+ /**
* If argument is a PsiDirectory, turn it into a PsiFile that points to __init__.py in that directory.
* If there's no __init__.py there, null is returned, there's no point to resolve to a dir which is not a package.
* Alas, resolve() and multiResolve() can't return anything but a PyFile or PsiFileImpl.isPsiUpToDate() would fail.
@@ -1645,6 +1659,11 @@ public class PyUtil {
return Collections2.filter(pyMemberInfos, new ObjectPredicate(false));
}
+ public static boolean isStarImportableFrom(@NotNull String name, @NotNull PyFile file) {
+ final List<String> dunderAll = file.getDunderAll();
+ return dunderAll != null ? dunderAll.contains(name) : !name.startsWith("_");
+ }
+
/**
* Filters only pyclass object (new class)
*/
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
index 744dc9731b41..bb0e29f800a7 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.TokenSet;
@@ -86,8 +87,9 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
}
+ @Override
public PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped) {
- return createStringLiteralFromString(null, unescaped);
+ return createStringLiteralFromString(null, unescaped, true);
}
public PyStringLiteralExpression createStringLiteral(@NotNull PyStringLiteralExpression oldElement, @NotNull String unescaped) {
@@ -100,7 +102,11 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
}
}
- public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, @NotNull String unescaped) {
+
+ @Override
+ public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination,
+ @NotNull String unescaped,
+ final boolean preferUTF8) {
boolean useDouble = !unescaped.contains("\"");
boolean useMulti = unescaped.matches(".*(\r|\n).*");
String quotes;
@@ -115,7 +121,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
VirtualFile vfile = destination == null ? null : destination.getVirtualFile();
Charset charset;
if (vfile == null) {
- charset = Charset.forName("US-ASCII");
+ charset = (preferUTF8 ? Charset.forName("UTF-8") : Charset.forName("US-ASCII"));
}
else {
charset = vfile.getCharset();
@@ -191,7 +197,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
final LeafPsiElement[] leafs = PsiTreeUtil.getChildrenOfType(list, LeafPsiElement.class);
if (leafs != null) {
final Deque<LeafPsiElement> commas = Queues.newArrayDeque(Collections2.filter(Arrays.asList(leafs), COMMAS_ONLY));
- if (! commas.isEmpty()) {
+ if (!commas.isEmpty()) {
final LeafPsiElement lastComma = commas.getLast();
if (PsiTreeUtil.getNextSiblingOfType(lastComma, PyExpression.class) == null) { //Comma has no expression after it
lastComma.delete();
@@ -297,7 +303,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
AccessDirection accessDirection) {
String propertyText;
if (accessDirection == AccessDirection.DELETE) {
- propertyText = "@" + propertyName +".deleter\ndef " + propertyName + "(self):\n del self." + fieldName;
+ propertyText = "@" + propertyName + ".deleter\ndef " + propertyName + "(self):\n del self." + fieldName;
}
else if (accessDirection == AccessDirection.WRITE) {
propertyText = "@" + propertyName + ".setter\ndef " + propertyName + "(self, value):\n self." + fieldName + " = value";
@@ -415,6 +421,12 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
PyExpressionStatement.class, content + "\n");
}
+ @NotNull
+ @Override
+ public PsiElement createNewLine() {
+ return createFromText(LanguageLevel.getDefault(), PsiWhiteSpace.class, " \n\n ");
+ }
+
private static class CommasOnly extends NotNullPredicate<LeafPsiElement> {
@Override
protected boolean applyNotNull(@NotNull final LeafPsiElement input) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
index ddd02d5310a3..8c69893c62a8 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
@@ -15,26 +15,16 @@
*/
package com.jetbrains.python.psi.impl;
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
import com.intellij.lang.ASTNode;
+import com.jetbrains.python.psi.PyElsePart;
/**
* User: dcheryasov
* Date: Mar 15, 2009 9:40:35 PM
*/
-public class PyElsePartImpl extends PyElementImpl implements PyElsePart {
+public class PyElsePartImpl extends PyStatementPartImpl implements PyElsePart {
public PyElsePartImpl(ASTNode astNode) {
super(astNode);
}
-
- public PyStatementList getStatementList() {
- ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
- if (n != null) {
- return (PyStatementList)n.getPsi();
- }
- return null;
- }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
index 030fcfe3d7e5..02b790622fe7 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
@@ -477,8 +477,9 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
if (starImportSource != null) {
starImportSource = PyUtil.turnDirIntoInit(starImportSource);
if (starImportSource instanceof PyFile) {
- final PsiElement result = ((PyFile)starImportSource).getElementNamed(name);
- if (result != null) {
+ final PyFile file = (PyFile)starImportSource;
+ final PsiElement result = file.getElementNamed(name);
+ if (result != null && PyUtil.isStarImportableFrom(name, file)) {
return result;
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
index e0cdf87b2aab..9d2be0f62205 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
@@ -23,6 +23,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.documentation.StructuredDocStringBase;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -82,14 +83,21 @@ public class PyFunctionBuilder {
/**
* Adds docstring to function. Provide doc with out of comment blocks.
*
+ *
* @param docString doc
*/
public void docString(@NotNull final String docString) {
- myDocStringLines = StringUtil.splitByLines(removeIndent(docString));
+ final String[] stringsToAdd = StringUtil.splitByLines(removeIndent(docString));
+ if (myDocStringLines == null) {
+ myDocStringLines = stringsToAdd;
+ }
+ else {
+ myDocStringLines = ArrayUtil.mergeArrays(myDocStringLines, stringsToAdd);
+ }
}
@NotNull
- private String removeIndent(@NotNull final String string) {
+ private static String removeIndent(@NotNull final String string) {
return INDENT_REMOVE_PATTERN.matcher(string).replaceAll("");
}
@@ -97,6 +105,21 @@ public class PyFunctionBuilder {
myName = name;
}
+ /**
+ * Adds param and its type to doc
+ * @param name param name
+ * @param type param type
+ * @param docStyle what docstyle to use to doc param type
+ */
+ @NotNull
+ public PyFunctionBuilder parameterWithType(@NotNull final String name,
+ @NotNull final String type,
+ @NotNull final StructuredDocStringBase docStyle) {
+ parameter(name);
+ docString(docStyle.createParameterType(name, type));
+ return this;
+ }
+
public PyFunctionBuilder parameter(String baseName) {
String name = baseName;
int uniqueIndex = 0;
@@ -173,8 +196,9 @@ public class PyFunctionBuilder {
/**
* Adds decorator with argument
+ *
* @param decoratorName decorator name
- * @param value its argument
+ * @param value its argument
*/
public void decorate(@NotNull final String decoratorName, @NotNull final String value) {
decorate(decoratorName);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
index 4011c233e38d..88c3134481a8 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
@@ -52,11 +52,8 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
for (PsiElement importedFile : new HashSet<PsiElement>(importedFiles)) { // resolver gives lots of duplicates
final PsiElement source = PyUtil.turnDirIntoInit(importedFile);
if (source instanceof PyFile) {
- Iterable<PyElement> declaredNames = ((PyFile)source).iterateNames();
- if (((PyFile)source).getDunderAll() == null) {
- declaredNames = excludeUnderscoredNames(declaredNames);
- }
- chain.add(declaredNames);
+ final PyFile sourceFile = (PyFile)source;
+ chain.add(filterStarImportableNames(sourceFile.iterateNames(), sourceFile));
}
}
return chain;
@@ -64,15 +61,13 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
return Collections.emptyList();
}
- private static Iterable<PyElement> excludeUnderscoredNames(Iterable<PyElement> declaredNames) {
+ @NotNull
+ private static Iterable<PyElement> filterStarImportableNames(@NotNull Iterable<PyElement> declaredNames, @NotNull final PyFile file) {
return Iterables.filter(declaredNames, new Predicate<PyElement>() {
@Override
public boolean apply(@Nullable PyElement input) {
final String name = input != null ? input.getName() : null;
- if (name != null && name.startsWith("_")) {
- return false;
- }
- return true;
+ return name != null && PyUtil.isStarImportableFrom(name, file);
}
});
}
@@ -93,11 +88,7 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
final List<? extends RatedResolveResult> results = moduleType.resolveMember(name, null, AccessDirection.READ,
PyResolveContext.defaultContext());
final PsiElement result = results != null && !results.isEmpty() ? results.get(0).getElement() : null;
- if (result != null) {
- final List<String> all = sourceFile.getDunderAll();
- if (all != null ? !all.contains(name) : name.startsWith("_")) {
- continue;
- }
+ if (result != null && PyUtil.isStarImportableFrom(name, sourceFile) ) {
return result;
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
index 46e9a785a9d4..7454d6741382 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
@@ -15,10 +15,11 @@
*/
package com.jetbrains.python.psi.impl;
-import com.jetbrains.python.psi.PyStatementPart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
import com.intellij.lang.ASTNode;
+import com.jetbrains.python.PyElementTypes;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementPart;
+import org.jetbrains.annotations.NotNull;
/**
* Abstract statement part implementation; extracts the statements list.
@@ -30,11 +31,8 @@ public abstract class PyStatementPartImpl extends PyElementImpl implements PySta
super(astNode);
}
+ @NotNull
public PyStatementList getStatementList() {
- ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
- if (n != null) {
- return (PyStatementList)n.getPsi();
- }
- return null;
+ return childToPsiNotNull(PyElementTypes.STATEMENT_LIST);
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
index 98cd8e5703d5..3af3771e8ecd 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
@@ -63,6 +63,14 @@ public class PyWithStatementImpl extends PyElementImpl implements PyWithStatemen
}
public PyWithItem[] getWithItems() {
- return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY);
+ return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY);
+ }
+
+ @Override
+ @NotNull
+ public PyStatementList getStatementList() {
+ final PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST);
+ assert statementList != null : "Statement list missing for with statement " + getText();
+ return statementList;
}
}
diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
index da8c0d618a8b..838a4dbcc75a 100644
--- a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
+++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
@@ -38,6 +38,11 @@ import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
/**
* Ref resolution routines.
* User: dcheryasov
@@ -106,16 +111,17 @@ public class PyResolveUtil {
owner = outerScopeOwner;
}
}
- scopeCrawlUp(processor, owner, originalOwner, name, roof);
+ scopeCrawlUp(processor, owner, originalOwner, name, roof, realContext);
}
public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @NotNull ScopeOwner scopeOwner, @Nullable String name,
@Nullable PsiElement roof) {
- scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof);
+ scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof, null);
}
public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @Nullable ScopeOwner scopeOwner,
- @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof) {
+ @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof,
+ @Nullable final PsiElement anchor) {
while (scopeOwner != null) {
if (!(scopeOwner instanceof PyClass) || scopeOwner == originalScopeOwner) {
final Scope scope = ControlFlowCache.getScope(scopeOwner);
@@ -136,7 +142,31 @@ public class PyResolveUtil {
}
}
}
- for (NameDefiner definer : scope.getImportedNameDefiners()) {
+ List<NameDefiner> definers = new ArrayList<NameDefiner>(scope.getImportedNameDefiners());
+ if (anchor != null && ScopeUtil.getScopeOwner(anchor) == scopeOwner) {
+ final Comparator<NameDefiner> nearestDefinerComparator = new Comparator<NameDefiner>() {
+ @Override
+ public int compare(NameDefiner a, NameDefiner b) {
+ final boolean aIsBefore = PyPsiUtils.isBefore(a, anchor);
+ final boolean bIsBefore = PyPsiUtils.isBefore(b, anchor);
+ final int diff = a.getTextOffset() - b.getTextOffset();
+ if (aIsBefore && bIsBefore) {
+ return -diff;
+ }
+ else if (aIsBefore) {
+ return -1;
+ }
+ else if (bIsBefore) {
+ return 1;
+ }
+ else {
+ return diff;
+ }
+ }
+ };
+ Collections.sort(definers, nearestDefinerComparator);
+ }
+ for (NameDefiner definer : definers) {
if (!processor.execute(definer, ResolveState.initial())) {
found = true;
break;
diff --git a/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
new file mode 100644
index 000000000000..2af1a641de83
--- /dev/null
+++ b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.run;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
+import com.intellij.util.PathMappingSettings;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public class PyRemoteTracebackFilter extends PythonTracebackFilter {
+ private final RemoteProcessHandlerBase myHandler;
+
+ public PyRemoteTracebackFilter(Project project, String workingDirectory, RemoteProcessHandlerBase remoteProcessHandler) {
+ super(project, workingDirectory);
+
+ myHandler = remoteProcessHandler;
+ }
+
+ @Override
+ @Nullable
+ protected VirtualFile findFileByName(String fileName) {
+ VirtualFile vFile = super.findFileByName(fileName);
+ if (vFile != null) {
+ return vFile;
+ }
+ for (PathMappingSettings.PathMapping m : myHandler.getMappingSettings().getPathMappings()) {
+ if (m.canReplaceRemote(fileName)) {
+ VirtualFile file = LocalFileSystem.getInstance().findFileByPath(m.mapToLocal(fileName));
+ if (file != null && file.exists()) {
+ return file;
+ }
+ }
+ }
+
+
+
+ return null;
+ }
+}
diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
index 216e68c58e1d..a4d1718bb006 100644
--- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
@@ -47,6 +47,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.HashMap;
import com.jetbrains.python.PythonHelpersLocator;
@@ -80,7 +81,9 @@ public abstract class PythonCommandLineState extends CommandLineState {
public static final String GROUP_DEBUGGER = "Debugger";
public static final String GROUP_SCRIPT = "Script";
private final AbstractPythonRunConfiguration myConfig;
- private final List<Filter> myFilters;
+
+ private final List<Filter> myFilters = Lists.<Filter>newArrayList(new UrlFilter());
+
private Boolean myMultiprocessDebug = null;
public boolean isDebug() {
@@ -99,15 +102,9 @@ public abstract class PythonCommandLineState extends CommandLineState {
return serverSocket;
}
- public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
+ public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
super(env);
myConfig = runConfiguration;
- myFilters = Lists.newArrayList(filters);
- addDefaultFilters();
- }
-
- protected void addDefaultFilters() {
- myFilters.add(new UrlFilter());
}
@Nullable
@@ -134,10 +131,23 @@ public abstract class PythonCommandLineState extends CommandLineState {
protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
throws ExecutionException {
final ConsoleView consoleView = createConsoleBuilder(project).filters(myFilters).getConsole();
+
+ addTracebackFilter(project, consoleView, processHandler);
+
consoleView.attachToProcess(processHandler);
return consoleView;
}
+ protected void addTracebackFilter(Project project, ConsoleView consoleView, ProcessHandler processHandler) {
+ if (PySdkUtil.isRemote(myConfig.getSdk())) {
+ assert processHandler instanceof RemoteProcessHandlerBase;
+ consoleView.addMessageFilter(new PyRemoteTracebackFilter(project, myConfig.getWorkingDirectory(), (RemoteProcessHandlerBase) processHandler));
+ }
+ else {
+ consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfig.getWorkingDirectory()));
+ }
+ }
+
private TextConsoleBuilder createConsoleBuilder(Project project) {
if (isDebug()) {
return new PyDebugConsoleBuilder(project, PythonSdkType.findSdkByPath(myConfig.getInterpreterPath()));
diff --git a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
index bbba44441227..118c27beb548 100644
--- a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
+++ b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
@@ -15,11 +15,9 @@
*/
package com.jetbrains.python.run;
-import com.google.common.collect.Lists;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.options.SettingsEditor;
@@ -40,7 +38,6 @@ import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.List;
/**
* @author yole
@@ -64,10 +61,7 @@ public class PythonRunConfiguration extends AbstractPythonRunConfiguration
}
public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
- List<Filter> filters = Lists.newArrayList();
- filters.add(new PythonTracebackFilter(getProject(), getWorkingDirectory()));
-
- return new PythonScriptCommandLineState(this, env, filters);
+ return new PythonScriptCommandLineState(this, env);
}
public void checkConfiguration() throws RuntimeConfigurationException {
diff --git a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
index 53ef554838ae..81d2daaee3d0 100644
--- a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
@@ -18,20 +18,17 @@ package com.jetbrains.python.run;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.util.text.StringUtil;
-import java.util.List;
-
/**
* @author yole
*/
public class PythonScriptCommandLineState extends PythonCommandLineState {
private final PythonRunConfiguration myConfig;
- public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
- super(runConfiguration, env, filters);
+ public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
+ super(runConfiguration, env);
myConfig = runConfiguration;
}
diff --git a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
index e3bd879cfe81..73a3abd222b1 100644
--- a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
+++ b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
@@ -51,10 +51,7 @@ public class PythonTracebackFilter implements Filter {
if (matcher.find()) {
String fileName = matcher.group(1).replace('\\', '/');
int lineNumber = Integer.parseInt(matcher.group(2));
- VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
- if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
- vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName));
- }
+ VirtualFile vFile = findFileByName(fileName);
if (vFile != null) {
OpenFileHyperlinkInfo hyperlink = new OpenFileHyperlinkInfo(myProject, vFile, lineNumber - 1);
@@ -66,4 +63,13 @@ public class PythonTracebackFilter implements Filter {
}
return null;
}
+
+ @Nullable
+ protected VirtualFile findFileByName(String fileName) {
+ VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
+ if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
+ vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName));
+ }
+ return vFile;
+ }
}
diff --git a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
index 098462ef44fb..f288bd99ce3b 100644
--- a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
+++ b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
@@ -8,4 +8,8 @@ public class PyDetectedSdk extends ProjectJdkImpl {
setHomePath(name);
}
+ @Override
+ public String getVersionString() {
+ return "";
+ }
}
diff --git a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
index 39e4e96b836b..1a5aafe59051 100644
--- a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
+++ b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
@@ -22,7 +22,6 @@ import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.TestFrameworkRunningModel;
@@ -42,12 +41,10 @@ import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import com.jetbrains.python.run.CommandLinePatcher;
import com.jetbrains.python.run.PythonCommandLineState;
-import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -62,7 +59,7 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
}
public PythonTestCommandLineStateBase(AbstractPythonRunConfiguration configuration, ExecutionEnvironment env) {
- super(configuration, env, Collections.<Filter>emptyList());
+ super(configuration, env);
myConfiguration = configuration;
}
@@ -77,7 +74,6 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
consoleProperties,
getEnvironment());
final ConsoleView consoleView = new PythonDebugLanguageConsoleView(project, PythonSdkType.findSdkByPath(myConfiguration.getInterpreterPath()), testsOutputConsoleView);
- consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
consoleView.attachToProcess(processHandler);
return consoleView;
}
@@ -85,7 +81,7 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
processHandler,
consoleProperties,
getEnvironment());
- consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+ addTracebackFilter(project, consoleView, processHandler);
return consoleView;
}
diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
index 3637f37ca91c..581e688de1d5 100644
--- a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
+++ b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
@@ -81,7 +81,7 @@ public class PyTestCommandLineState extends PythonTestCommandLineStateBase {
protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
throws ExecutionException {
final ConsoleView consoleView = super.createAndAttachConsole(project, processHandler, executor);
- consoleView.addMessageFilter(new PyTestTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+ addTracebackFilter(project, consoleView, processHandler);
return consoleView;
}
}