Mark duplicated *args and **kwargs as not allowed (PY-26491)

This commit is contained in:
Semyon Proshev
2017-10-16 19:24:08 +03:00
parent b1bd6df96a
commit 44a9986bdb
8 changed files with 40 additions and 15 deletions

View File

@@ -755,8 +755,10 @@ ANN.starred.param.after.kwparam=* parameter after ** parameter
ANN.regular.param.after.vararg=regular parameter after * parameter
ANN.regular.param.after.keyword=regular parameter after ** parameter
ANN.non.default.param.after.default=non-default parameter follows default parameter
ANN.named.arguments.after.star=named arguments must follow bare *
ANN.named.parameters.after.star=named parameters must follow bare *
ANN.tuple.py3=tuple parameter unpacking is not supported in Python 3
ANN.multiple.args=multiple * parameters are not allowed
ANN.multiple.kwargs=multiple ** parameters are not allowed
ANN.star.import.at.top.only='import *' only allowed at module level

View File

@@ -149,7 +149,7 @@ public class PyChangeSignatureDialog extends
if (name.equals("*")) {
hadSingleStar = true;
if (index == parametersLength - 1) {
return PyBundle.message("ANN.named.arguments.after.star");
return PyBundle.message("ANN.named.parameters.after.star");
}
}
else if (name.startsWith("*") && !name.startsWith("**")) {
@@ -166,7 +166,7 @@ public class PyChangeSignatureDialog extends
}
else if (name.startsWith("**")) {
if (hadSingleStar && !hadParamsAfterSingleStar) {
return PyBundle.message("ANN.named.arguments.after.star");
return PyBundle.message("ANN.named.parameters.after.star");
}
if (hadKeywordContainer) {
return PyBundle.message("refactoring.change.signature.dialog.validation.multiple.double.star");

View File

@@ -28,11 +28,11 @@ import java.util.Set;
public class ParameterListAnnotator extends PyAnnotator {
@Override
public void visitPyParameterList(final PyParameterList paramlist) {
final LanguageLevel languageLevel = ((PyFile)paramlist.getContainingFile()).getLanguageLevel();
final LanguageLevel languageLevel = LanguageLevel.forElement(paramlist);
ParamHelper.walkDownParamArray(
paramlist.getParameters(),
new ParamHelper.ParamVisitor() {
Set<String> parameterNames = new HashSet<>();
final Set<String> parameterNames = new HashSet<>();
boolean hadPositionalContainer = false;
boolean hadKeywordContainer = false;
boolean hadDefaultValue = false;
@@ -50,14 +50,18 @@ public class ParameterListAnnotator extends PyAnnotator {
markError(parameter, PyBundle.message("ANN.starred.param.after.kwparam"));
}
if (hadSingleStar) {
markError(parameter, "Multiple * arguments are not allowed");
markError(parameter, PyBundle.message("ANN.multiple.args"));
}
if (hadPositionalContainer) markError(parameter, PyBundle.message("ANN.multiple.args"));
hadPositionalContainer = true;
}
else if (parameter.isKeywordContainer()) {
if (hadKeywordContainer) markError(parameter, PyBundle.message("ANN.multiple.kwargs"));
hadKeywordContainer = true;
if (hadSingleStar && !hadParamsAfterSingleStar) {
markError(parameter, PyBundle.message("ANN.named.arguments.after.star"));
markError(parameter, PyBundle.message("ANN.named.parameters.after.star"));
}
}
else {
@@ -100,11 +104,11 @@ public class ParameterListAnnotator extends PyAnnotator {
@Override
public void visitSingleStarParameter(PySingleStarParameter param, boolean first, boolean last) {
if (hadPositionalContainer || hadSingleStar) {
markError(param, "Multiple * arguments are not allowed");
markError(param, PyBundle.message("ANN.multiple.args"));
}
hadSingleStar = true;
if (last) {
markError(param, PyBundle.message("ANN.named.arguments.after.star"));
markError(param, PyBundle.message("ANN.named.parameters.after.star"));
}
}
}

View File

@@ -1,10 +1,10 @@
def keywordonly_sum(*, k1=0, k2):
return k1 + k2
def keywordonly_sum_bad1(p, <error descr="named arguments must follow bare *">*</error>):
def keywordonly_sum_bad1(p, <error descr="named parameters must follow bare *">*</error>):
pass
def keywordonly_sum_bad2(p1, *, <error descr="named arguments must follow bare *">**k1</error>):
def keywordonly_sum_bad2(p1, *, <error descr="named parameters must follow bare *">**k1</error>):
pass
def keywordonly_and_kwarg_sum(*, k1, k2, **kwarg):

View File

@@ -0,0 +1,5 @@
def handle(foo, **args, <error descr="multiple ** parameters are not allowed">**moreargs</error>):
print(foo, args, moreargs)
def handle(foo, **args: int, <error descr="multiple ** parameters are not allowed">**moreargs: int</error>):
print(foo, args, moreargs)

View File

@@ -0,0 +1,5 @@
def handle(foo, *args, <error descr="multiple * parameters are not allowed">*moreargs</error>):
print(foo, args, moreargs)
def handle(foo, *args: int, <error descr="multiple * parameters are not allowed">*moreargs: int</error>):
print(foo, args, moreargs)

View File

@@ -1,8 +1,8 @@
def f1(*args, <error descr="Multiple * arguments are not allowed">*</error>, a):
def f1(*args, <error descr="multiple * parameters are not allowed">*</error>, a):
pass
def f2(*, <error descr="Multiple * arguments are not allowed">*</error>, d):
def f2(*, <error descr="multiple * parameters are not allowed">*</error>, d):
pass
def f3(*, <error descr="Multiple * arguments are not allowed">*args</error>):
def f3(*, <error descr="multiple * parameters are not allowed">*args</error>):
pass

View File

@@ -20,7 +20,6 @@ import java.awt.*;
* @author yole
*/
public class PythonHighlightingTest extends PyTestCase {
private static final String TEST_PATH = "/highlighting/";
public void testBuiltins() {
EditorColorsScheme scheme = createTemporaryColorScheme();
@@ -362,6 +361,16 @@ public class PythonHighlightingTest extends PyTestCase {
runWithLanguageLevel(LanguageLevel.PYTHON30, this::doTest);
}
// PY-26491
public void testMultiplePositionalContainers() {
doTest(LanguageLevel.PYTHON35, true, false);
}
// PY-26491
public void testMultipleKeywordContainers() {
doTest(LanguageLevel.PYTHON35, true, false);
}
// PY-26510
public void testEmptyRaise() {
doTest(false, false);