diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index ccb551a65f62..f9220330514b 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -78,6 +78,9 @@ QFIX.unresolved.reference.replace.$0=Replace with {0}
#PyDefaultArgumentQuickFix
QFIX.default.argument=Replace mutable default argument
+#RemoveArgumentEqualDefaultQuickFix
+QFIX.remove.argument.equal.default=Remove argument equal to default
+
# 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'
@@ -360,6 +363,9 @@ INSP.NAME.augment.assignment=Assignment can be replaced with augmented assignmen
# PyChainedComparsonsInspection
INSP.NAME.chained.comparisons=Chained comparisons can be simplified
+# PyArgumentEqualDefaultInspection
+INSP.NAME.argument.equal.default=Argument passed to function is equal to default parameter value
+
# PyOldStyleClassesInspection
INSP.NAME.oldstyle.class=Old-style class contains new-style class features
diff --git a/python/src/com/jetbrains/python/actions/RemoveArgumentEqualDefaultQuickFix.java b/python/src/com/jetbrains/python/actions/RemoveArgumentEqualDefaultQuickFix.java
new file mode 100644
index 000000000000..a393d6df8c86
--- /dev/null
+++ b/python/src/com/jetbrains/python/actions/RemoveArgumentEqualDefaultQuickFix.java
@@ -0,0 +1,30 @@
+package com.jetbrains.python.actions;
+
+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.PyBundle;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ *
+ * QuickFix to remove redundant argument equal default
+ */
+public class RemoveArgumentEqualDefaultQuickFix implements LocalQuickFix {
+ @NotNull
+ public String getName() {
+ return PyBundle.message("QFIX.remove.argument.equal.default");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INSP.GROUP.python");
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ PsiElement element = descriptor.getPsiElement();
+ element.delete();
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java
new file mode 100644
index 000000000000..b9c0cf4a3cdd
--- /dev/null
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentEqualDefaultInspection.java
@@ -0,0 +1,77 @@
+package com.jetbrains.python.inspections;
+
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiReference;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.actions.RemoveArgumentEqualDefaultQuickFix;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ *
+ * Inspection to detect situations, where argument passed to function
+ * is equal to default parameter value
+ * for instance,
+ * dict().get(x, None) --> None is default value for second param in dict().get function
+ */
+public class PyArgumentEqualDefaultInspection extends PyInspection {
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return PyBundle.message("INSP.NAME.argument.equal.default");
+ }
+
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
+ return new Visitor(holder);
+ }
+
+ private static class Visitor extends PyInspectionVisitor {
+
+ public Visitor(final ProblemsHolder holder) {
+ super(holder);
+ }
+
+ @Override
+ public void visitPyCallExpression(final PyCallExpression node){
+ PyExpression[] arguments = node.getArguments();
+ PyExpression callee = node.getCallee();
+ if (callee != null) {
+ PsiReference ref = callee.getReference();
+ if (ref != null) {
+ PsiElement function = ref.resolve();
+ if (function instanceof PyFunction) {
+ checkArguments(function, arguments);
+ }
+ }
+ }
+ }
+
+ private void checkArguments(PsiElement function, PyExpression[] arguments) {
+ int argumentsSize = arguments.length;
+ PyClass containingClass = ((PyFunction)function).getContainingClass();
+ int adjust = 0;
+ if (containingClass != null)
+ adjust = 1;
+ PyParameter[] params = ((PyFunction)function).getParameterList().getParameters();
+ for (int i = 0; i != params.length - adjust; ++i) {
+ PyParameter p = params[i+adjust];
+ if (p instanceof PyNamedParameter) {
+ PyExpression defaultValue = p.getDefaultValue();
+ if (defaultValue != null && i < argumentsSize) {
+ if (arguments[i].getText().equals(defaultValue.getText())) {
+ registerProblem(arguments[i], "Argument equals to default parameter value",
+ new RemoveArgumentEqualDefaultQuickFix());
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/PythonInspectionToolProvider.java b/python/src/com/jetbrains/python/inspections/PythonInspectionToolProvider.java
index 7f619eb2d23c..e0b81516eea2 100644
--- a/python/src/com/jetbrains/python/inspections/PythonInspectionToolProvider.java
+++ b/python/src/com/jetbrains/python/inspections/PythonInspectionToolProvider.java
@@ -57,6 +57,7 @@ public class PythonInspectionToolProvider implements InspectionToolProvider {
PyUnnecessaryBackslashInspection.class,
PySingleQuotedDocstringInspection.class,
PyMissingConstructorInspection.class,
+ PyArgumentEqualDefaultInspection.class,
};
}
}
diff --git a/python/testData/inspections/ArgumentEqualDefault.py b/python/testData/inspections/ArgumentEqualDefault.py
new file mode 100644
index 000000000000..964d0bcb7ffd
--- /dev/null
+++ b/python/testData/inspections/ArgumentEqualDefault.py
@@ -0,0 +1,4 @@
+def foo(a, b = 345, c = 1):
+ pass
+
+foo(1, 345, 22)
\ No newline at end of file
diff --git a/python/testData/inspections/ArgumentEqualDefault_after.py b/python/testData/inspections/ArgumentEqualDefault_after.py
new file mode 100644
index 000000000000..00e31ef94b4c
--- /dev/null
+++ b/python/testData/inspections/ArgumentEqualDefault_after.py
@@ -0,0 +1,4 @@
+def foo(a, b = 345, c = 1):
+ pass
+
+foo(1, 22)
\ No newline at end of file
diff --git a/python/testData/inspections/PyArgumentEqualDefaultInspection/test.py b/python/testData/inspections/PyArgumentEqualDefaultInspection/test.py
new file mode 100644
index 000000000000..f802999c9021
--- /dev/null
+++ b/python/testData/inspections/PyArgumentEqualDefaultInspection/test.py
@@ -0,0 +1,7 @@
+def foo(a, b = 345, c = 1):
+ pass
+
+foo(1, 345, 22)
+
+a = dict()
+a.get(1, None)
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
index 652f5b5883bf..bb0c7c71c2c0 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
@@ -235,6 +235,11 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
PyBundle.message("QFIX.default.argument"), true, true);
}
+ public void testPyArgumentEqualDefault() { //PY-3125
+ doInspectionTest("ArgumentEqualDefault.py", PyArgumentEqualDefaultInspection.class,
+ PyBundle.message("QFIX.remove.argument.equal.default"), true, true);
+ }
+
public void testUnnecessaryBackslash() {
String[] testFiles = new String[]{"UnnecessaryBackslash.py"};
myFixture.enableInspections(PyUnnecessaryBackslashInspection.class);
diff --git a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
index 9810a9cd7f2a..004bc57a4634 100644
--- a/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonInspectionsTest.java
@@ -322,4 +322,8 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase {
setLanguageLevel(LanguageLevel.PYTHON30);
doHighlightingTest(PyMissingConstructorInspection.class);
}
+
+ public void testPyArgumentEqualDefaultInspection() { //PY-3125
+ doHighlightingTest(PyArgumentEqualDefaultInspection.class);
+ }
}