diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 3f73c06ccebf..1549b9600ba1 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -129,6 +129,8 @@ QFIX.NAME.remove.dict.key=Remove this key
QFIX.NAME.add.specifier=Add format specifier character
+QFIX.NAME.add.exception.base=Add Exception base class
+
# Intentions: INTN
INTN.Family.convert.import.unqualify=Convert 'import module' to 'from module import'
INTN.Family.convert.import.qualify=Convert 'from module import' to 'import module'
diff --git a/python/src/com/jetbrains/python/inspections/PyExceptionInheritInspection.java b/python/src/com/jetbrains/python/inspections/PyExceptionInheritInspection.java
index 6ece46395030..b659cb8b0caf 100644
--- a/python/src/com/jetbrains/python/inspections/PyExceptionInheritInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyExceptionInheritInspection.java
@@ -19,7 +19,9 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiPolyVariantReference;
import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.inspections.quickfix.PyAddExceptionSuperClassQuickFix;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyClassLikeType;
import org.jetbrains.annotations.Nls;
@@ -60,7 +62,9 @@ public class PyExceptionInheritInspection extends PyInspection {
if (expression instanceof PyCallExpression) {
PyExpression callee = ((PyCallExpression)expression).getCallee();
if (callee instanceof PyReferenceExpression) {
- PsiElement psiElement = ((PyReferenceExpression)callee).getReference(getResolveContext()).resolve();
+ final PsiPolyVariantReference reference = ((PyReferenceExpression)callee).getReference(getResolveContext());
+ if (reference == null) return;
+ PsiElement psiElement = reference.resolve();
if (psiElement instanceof PyClass) {
PyClass aClass = (PyClass) psiElement;
for (PyClassLikeType type : aClass.getAncestorTypes(myTypeEvalContext)) {
@@ -72,7 +76,7 @@ public class PyExceptionInheritInspection extends PyInspection {
return;
}
}
- registerProblem(expression, "Exception doesn't inherit from base \'Exception\' class");
+ registerProblem(expression, "Exception doesn't inherit from base \'Exception\' class", new PyAddExceptionSuperClassQuickFix());
}
}
}
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java
new file mode 100644
index 000000000000..00d1f6d4611b
--- /dev/null
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyAddExceptionSuperClassQuickFix.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2013 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.inspections.quickfix;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiPolyVariantReference;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+public class PyAddExceptionSuperClassQuickFix implements LocalQuickFix {
+
+ @NotNull
+ public String getName() {
+ return PyBundle.message("QFIX.NAME.add.exception.base");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return getName();
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ if (element instanceof PyCallExpression) {
+ PyExpression callee = ((PyCallExpression)element).getCallee();
+ if (callee instanceof PyReferenceExpression) {
+ final PsiPolyVariantReference reference = ((PyReferenceExpression)callee).getReference();
+ PsiElement psiElement = reference.resolve();
+ if (psiElement instanceof PyClass) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+ final PyArgumentList list = ((PyClass)psiElement).getSuperClassExpressionList();
+ if (list != null) {
+ final PyExpression exception =
+ generator.createExpressionFromText(LanguageLevel.forElement(element), "Exception");
+ list.addArgument(exception);
+ }
+ else {
+ final PyArgumentList expressionList = generator.createFromText(
+ LanguageLevel.forElement(element), PyClass.class, "class A(Exception): pass").getSuperClassExpressionList();
+ assert expressionList != null;
+ final ASTNode nameNode = ((PyClass)psiElement).getNameNode();
+ assert nameNode != null;
+ psiElement.addAfter(expressionList, nameNode.getPsi());
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList.py b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList.py
new file mode 100644
index 000000000000..1d4b461388dc
--- /dev/null
+++ b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList.py
@@ -0,0 +1,9 @@
+
+class MyException:
+ def __new__(cls, x):
+ pass
+
+
+def foo():
+ raise MyException()
+
diff --git a/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList_after.py b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList_after.py
new file mode 100644
index 000000000000..3804bf9461f2
--- /dev/null
+++ b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/emptySuperList_after.py
@@ -0,0 +1,9 @@
+
+class MyException(Exception):
+ def __new__(cls, x):
+ pass
+
+
+def foo():
+ raise MyException()
+
diff --git a/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList.py b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList.py
new file mode 100644
index 000000000000..81c7263ede1f
--- /dev/null
+++ b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList.py
@@ -0,0 +1,12 @@
+
+class A:
+ pass
+
+class MyException(A):
+ def __new__(cls, x):
+ pass
+
+
+def foo():
+ raise MyException()
+
diff --git a/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList_after.py b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList_after.py
new file mode 100644
index 000000000000..c92e761d5234
--- /dev/null
+++ b/python/testData/quickFixes/PyAddExceptionSuperClassQuickFixTest/nonEmptySuperList_after.py
@@ -0,0 +1,12 @@
+
+class A:
+ pass
+
+class MyException(A, Exception):
+ def __new__(cls, x):
+ pass
+
+
+def foo():
+ raise MyException()
+
diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyAddExceptionSuperClassQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyAddExceptionSuperClassQuickFixTest.java
new file mode 100644
index 000000000000..b8a432da36d4
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/quickFixes/PyAddExceptionSuperClassQuickFixTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2013 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.quickFixes;
+
+import com.intellij.testFramework.TestDataPath;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.PyQuickFixTestCase;
+import com.jetbrains.python.inspections.PyExceptionInheritInspection;
+
+/**
+ * User: ktisha
+ */
+@TestDataPath("$CONTENT_ROOT/../testData//quickFixes/PyAddExceptionSuperClassQuickFixTest/")
+public class PyAddExceptionSuperClassQuickFixTest extends PyQuickFixTestCase {
+
+ public void testEmptySuperList() {
+ doQuickFixTest(PyExceptionInheritInspection.class, PyBundle.message("QFIX.NAME.add.exception.base"));
+ }
+
+ public void testNonEmptySuperList() {
+ doQuickFixTest(PyExceptionInheritInspection.class, PyBundle.message("QFIX.NAME.add.exception.base"));
+ }
+
+}