diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml index 35a7e0b37775..5cfefea9c684 100644 --- a/python/src/META-INF/python-core.xml +++ b/python/src/META-INF/python-core.xml @@ -331,7 +331,7 @@ - + diff --git a/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java b/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java index 374f9712789e..3bd8ac175ede 100644 --- a/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java @@ -16,7 +16,6 @@ package com.jetbrains.python.inspections; import com.intellij.codeInspection.LocalInspectionToolSession; -import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; @@ -63,14 +62,16 @@ public class PyAbstractClassInspection extends PyInspection { Set toBeImplemented = new HashSet(); final Collection functions = PyOverrideImplementUtil.getAllSuperFunctions(node); for (PyFunction method : functions) { - if (node.findMethodByName(method.getName(), false) == null && PyUtil.isDecoratedAsAbstract(method)) { + final String methodName = method.getName(); + if (methodName != null && PyUtil.isDecoratedAsAbstract(method) && + node.findMethodByName(methodName, false) == null && node.findClassAttribute(methodName, false) == null) { toBeImplemented.add(method); } } final ASTNode nameNode = node.getNameNode(); if (!toBeImplemented.isEmpty() && nameNode != null) { registerProblem(nameNode.getPsi(), PyBundle.message("INSP.NAME.abstract.class.$0.must.implement", node.getName()), - ProblemHighlightType.INFO, null, new PyImplementMethodsQuickFix(node, toBeImplemented)); + new PyImplementMethodsQuickFix(node, toBeImplemented)); } } } diff --git a/python/testData/inspections/PyAbstractClassInspection/abstract.py b/python/testData/inspections/PyAbstractClassInspection/abstract.py new file mode 100644 index 000000000000..17ceac089023 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/abstract.py @@ -0,0 +1,14 @@ +import abc + + +class A(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def foo(self): + pass + + +class C(A): + def bar(self): + pass diff --git a/python/testData/inspections/PyAbstractClassInspection/overriddenAsField.py b/python/testData/inspections/PyAbstractClassInspection/overriddenAsField.py new file mode 100644 index 000000000000..5d79ab73af50 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/overriddenAsField.py @@ -0,0 +1,13 @@ +import abc + + +class A(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def foo(self): + pass + + +class C(A): + foo = 'bar' \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java new file mode 100644 index 000000000000..99da99befb55 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java @@ -0,0 +1,36 @@ +/* + * 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; + +import com.jetbrains.python.fixtures.PyInspectionTestCase; +import org.jetbrains.annotations.NotNull; + +public class PyAbstractClassInspectionTest extends PyInspectionTestCase { + + public void testAbstract() { + doTest(); + } + + public void testOverriddenAsField() { + doTest(); + } + + @NotNull + @Override + protected Class getInspectionClass() { + return PyAbstractClassInspection.class; + } +}