diff --git a/python/src/com/jetbrains/python/inspections/PyRedeclarationInspection.java b/python/src/com/jetbrains/python/inspections/PyRedeclarationInspection.java
index 22a653dd8f89..c4650af37439 100644
--- a/python/src/com/jetbrains/python/inspections/PyRedeclarationInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyRedeclarationInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -26,7 +26,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.Function;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
@@ -35,6 +34,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
import com.jetbrains.python.psi.*;
+import com.jetbrains.python.pyi.PyiTypeProvider;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,6 +49,7 @@ import java.util.List;
* @author vlan
*/
public class PyRedeclarationInspection extends PyInspection {
+ @Override
@Nls
@NotNull
public String getDisplayName() {
@@ -136,8 +137,11 @@ public class PyRedeclarationInspection extends PyInspection {
if (rwInstruction.getAccess().isReadAccess()) {
readElementRef.set(originalElement);
}
- if (rwInstruction.getAccess().isWriteAccess()) {
- if (originalElement != element) {
+ if (rwInstruction.getAccess().isWriteAccess() && originalElement != element) {
+ if (element instanceof PyCallable && isOverload(originalElement)) {
+ return ControlFlowUtil.Operation.NEXT;
+ }
+ else {
writeElementRef.set(originalElement);
}
}
@@ -163,6 +167,10 @@ public class PyRedeclarationInspection extends PyInspection {
}
}
+ private boolean isOverload(@NotNull PsiElement element) {
+ return element instanceof PyCallable && PyiTypeProvider.isOverload((PyCallable)element, myTypeEvalContext);
+ }
+
private static boolean suggestRename(@NotNull PsiNameIdentifierOwner element, @NotNull PsiElement originalElement) {
// Target expressions in the same scope are treated as the same variable
if ((element instanceof PyTargetExpression) && originalElement instanceof PyTargetExpression) {
diff --git a/python/testData/inspections/PyRedeclarationInspection/overloadImplementationOverloadImplementationInClass.py b/python/testData/inspections/PyRedeclarationInspection/overloadImplementationOverloadImplementationInClass.py
new file mode 100644
index 000000000000..a930f9c7efbd
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/overloadImplementationOverloadImplementationInClass.py
@@ -0,0 +1,17 @@
+from typing import overload
+
+
+class A:
+ @overload
+ def foo(self, value: int) -> str:
+ pass
+
+ def foo(self, value):
+ return None
+
+ @overload
+ def foo(self, value: str) -> str:
+ pass
+
+ def foo(self, value):
+ return None
\ No newline at end of file
diff --git a/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationInClass.py b/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationInClass.py
new file mode 100644
index 000000000000..4e3e398016c1
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationInClass.py
@@ -0,0 +1,18 @@
+from typing import overload
+
+
+class A:
+ @overload
+ def utf8(self, value: None) -> None:
+ pass
+
+ @overload
+ def utf8(self, value: bytes) -> bytes:
+ pass
+
+ @overload
+ def utf8(self, value: str) -> bytes:
+ pass
+
+ def utf8(self, value):
+ return None
\ No newline at end of file
diff --git a/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationsInClass.py b/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationsInClass.py
new file mode 100644
index 000000000000..8210d6e57385
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/overloadsAndImplementationsInClass.py
@@ -0,0 +1,21 @@
+from typing import overload
+
+
+class A:
+ @overload
+ def utf8(self, value: None) -> None:
+ pass
+
+ @overload
+ def utf8(self, value: bytes) -> bytes:
+ pass
+
+ @overload
+ def utf8(self, value: str) -> bytes:
+ pass
+
+ def utf8(self, value):
+ return None
+
+ def utf8(self, value):
+ return None
\ No newline at end of file
diff --git a/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadImplementationOverloadImplementation.py b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadImplementationOverloadImplementation.py
new file mode 100644
index 000000000000..004096927a4b
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadImplementationOverloadImplementation.py
@@ -0,0 +1,19 @@
+from typing import overload
+
+
+@overload
+def foo(value: int) -> str:
+ pass
+
+
+def foo(value):
+ return None
+
+
+@overload
+def foo(value: str) -> str:
+ pass
+
+
+def foo(value):
+ return None
\ No newline at end of file
diff --git a/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementation.py b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementation.py
new file mode 100644
index 000000000000..10828a5ac41d
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementation.py
@@ -0,0 +1,20 @@
+from typing import overload
+
+
+@overload
+def utf8(value: None) -> None:
+ pass
+
+
+@overload
+def utf8(value: bytes) -> bytes:
+ pass
+
+
+@overload
+def utf8(value: str) -> bytes:
+ pass
+
+
+def utf8(value):
+ return None
\ No newline at end of file
diff --git a/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementations.py b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementations.py
new file mode 100644
index 000000000000..24afb0ce8ec8
--- /dev/null
+++ b/python/testData/inspections/PyRedeclarationInspection/topLevelOverloadsAndImplementations.py
@@ -0,0 +1,24 @@
+from typing import overload
+
+
+@overload
+def utf8(value: None) -> None:
+ pass
+
+
+@overload
+def utf8(value: bytes) -> bytes:
+ pass
+
+
+@overload
+def utf8(value: str) -> bytes:
+ pass
+
+
+def utf8(value):
+ return None
+
+
+def utf8(value):
+ return None
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyRedeclarationInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyRedeclarationInspectionTest.java
index e8fee694c710..918151e9e6f4 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyRedeclarationInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyRedeclarationInspectionTest.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.LanguageLevel;
public class PyRedeclarationInspectionTest extends PyTestCase {
@@ -63,6 +64,36 @@ public class PyRedeclarationInspectionTest extends PyTestCase {
doTest();
}
+ // PY-22971
+ public void testTopLevelOverloadsAndImplementation() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
+ // PY-22971
+ public void testOverloadsAndImplementationInClass() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
+ // PY-22971
+ public void testTopLevelOverloadsAndImplementations() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
+ // PY-22971
+ public void testOverloadsAndImplementationsInClass() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
+ // PY-22971
+ public void testTopLevelOverloadImplementationOverloadImplementation() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
+ // PY-22971
+ public void testOverloadImplementationOverloadImplementationInClass() {
+ runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest);
+ }
+
private void doTest() {
final String path = "inspections/PyRedeclarationInspection/" + getTestName(true) + ".py";