diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
index 919831c7591c..a7fb5e1a12db 100644
--- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java
@@ -6,6 +6,7 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyParameter;
@@ -24,13 +25,13 @@ public class PyArgumentListInspection extends LocalInspectionTool {
@Nls
@NotNull
public String getGroupDisplayName() {
- return "Python"; // TODO: propertize
+ return PyBundle.message("INSP.GROUP.python");
}
@Nls
@NotNull
public String getDisplayName() {
- return "Incorrect call arguments"; // TODO: propertize
+ return PyBundle.message("INSP.NAME.incorrect.call.arguments");
}
@NotNull
@@ -110,19 +111,19 @@ public class PyArgumentListInspection extends LocalInspectionTool {
if (!flags.isEmpty()) { // something's wrong
PyExpression arg = arg_entry.getKey();
if (flags.contains(PyArgumentList.ArgFlag.IS_DUP)) {
- registerProblem(arg, "Duplicate argument");
+ registerProblem(arg, PyBundle.message("INSP.duplicate.argument"));
}
if (flags.contains(PyArgumentList.ArgFlag.IS_DUP_KWD)) {
- registerProblem(arg, "Duplicate **arg");
+ registerProblem(arg, PyBundle.message("INSP.duplicate.doublestar.arg"));
}
if (flags.contains(PyArgumentList.ArgFlag.IS_DUP_TUPLE)) {
- registerProblem(arg, "Duplicate *arg");
+ registerProblem(arg, PyBundle.message("INSP.duplicate.star.arg"));
}
if (flags.contains(PyArgumentList.ArgFlag.IS_POS_PAST_KWD)) {
- registerProblem(arg, "Cannot appear past keyword arguments");
+ registerProblem(arg, PyBundle.message("INSP.cannot.appear.past.keyword.arg"));
}
if (flags.contains(PyArgumentList.ArgFlag.IS_UNMAPPED)) {
- registerProblem(arg, "Unexpected argument");
+ registerProblem(arg, PyBundle.message("INSP.unexpected.arg"));
}
}
}
@@ -132,7 +133,7 @@ public class PyArgumentListInspection extends LocalInspectionTool {
ASTNode close_paren = our_node.findChildByType(PyTokenTypes.RPAR);
if (close_paren != null) {
for (PyParameter param : result.getUnmappedParams()) {
- registerProblem(close_paren.getPsi(), "Parameter '" + param.getName() + "' unfilled");
+ registerProblem(close_paren.getPsi(), PyBundle.message("INSP.parameter.$0.unfilled", param.getName()));
}
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
index d88d63f6ca07..ca2a963fdff6 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
@@ -468,8 +468,16 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList
}
}
// any args left?
+ boolean tuple_arg_consumed_some = false;
+ for (PyExpression arg : param_slots.values()) { // any(\x: x == tuple_arg)
+ if (arg != null && arg == tuple_arg) {
+ tuple_arg_consumed_some = true;
+ break;
+ }
+ }
for (PyExpression arg : unmatched_args) {
//getHolder().createErrorAnnotation(arg, "unexpected arg");
+ if (arg == kwd_arg && tuple_arg_consumed_some) continue; // *arg consumed anything that **arg might equally consume.
ret.markArgument(arg, ArgFlag.IS_UNMAPPED);
}
// any params still unfilled?
diff --git a/python/testData/inspections/PyArgumentListInspection/expected.xml b/python/testData/inspections/PyArgumentListInspection/expected.xml
index 161e37f31c2a..32c2dd139fc1 100644
--- a/python/testData/inspections/PyArgumentListInspection/expected.xml
+++ b/python/testData/inspections/PyArgumentListInspection/expected.xml
@@ -70,4 +70,14 @@
55
Cannot appear past keyword arguments
+
+ badarglist.py
+ 65
+ Unexpected argument
+
+
+ badarglist.py
+ 66
+ Unexpected argument
+