Skip to content

Commit 9bb52f0

Browse files
committed
[GR-23242] Make test_keywordonlyarg.
PullRequest: graalpython/1218
2 parents 311568b + e0c21f5 commit 9bb52f0

File tree

7 files changed

+57
-8
lines changed

7 files changed

+57
-8
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/BasicTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@ public void call20() throws Exception {
365365
checkScopeAndTree("def fn(name): \"in\".format(name=name)");
366366
}
367367

368+
@Test
369+
public void call21() throws Exception {
370+
checkSyntaxErrorMessage("f(p, k1=50, *(1,2), k1=100)", "SyntaxError: keyword argument repeated");
371+
}
372+
368373
@Test
369374
public void del01() throws Exception {
370375
checkTreeResult("del x");

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/FuncDefTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,16 @@ public void positionalOnlyArg47() throws Exception {
487487
checkSyntaxError("async def f(a, *, c, /, d, e): pass");
488488
}
489489

490+
@Test
491+
public void positionalOnlyArg48() throws Exception {
492+
checkSyntaxErrorMessage("def f(p1, *k1, k1=100): pass ", "SyntaxError: duplicate argument 'k1' in function definition");
493+
}
494+
495+
@Test
496+
public void positionalOnlyArg49() throws Exception {
497+
checkSyntaxErrorMessage("def f(p1, *, k1, **k1): pass ", "SyntaxError: duplicate argument 'k1' in function definition");
498+
}
499+
490500
@Test
491501
public void issue21351() throws Exception {
492502
// parser test for GR-21351

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_keywordonlyarg.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testFunctionCall
22
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testKwDefaults
33
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testRaiseErrorFuncallWithUnexpectedKeywordArgument
4+
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testSyntaxErrorForFunctionCall
5+
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testSyntaxErrorForFunctionDefinition
46
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testSyntaxForManyArguments
57
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.testTooManyPositionalErrorMessage
68
*graalpython.lib-python.3.test.test_keywordonlyarg.KeywordOnlyArgTestCase.test_default_evaluation_order

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3.g4

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,11 @@ kwargsparameter [ArgDefListBuilder args]
632632
'**' NAME
633633
{ SSTNode type = null; }
634634
( ':' test { type = $test.result; } )?
635-
{ args.addKwargs($NAME.text, type); }
635+
{
636+
if (args.addKwargs($NAME.text, type) == ArgDefListBuilder.AddParamResult.DUPLICATED_ARGUMENT) {
637+
throw new PythonRecognitionException("duplicate argument '" + $NAME.text + "' in function definition", this, _input, $ctx, getCurrentToken());
638+
}
639+
}
636640
;
637641

638642
varargslist returns [ArgDefListBuilder result]
@@ -697,7 +701,11 @@ vsplatparameter [ArgDefListBuilder args]
697701
vkwargsparameter [ArgDefListBuilder args]
698702
:
699703
'**' NAME
700-
{args.addKwargs($NAME.text, null);}
704+
{
705+
if (args.addKwargs($NAME.text, null) == ArgDefListBuilder.AddParamResult.DUPLICATED_ARGUMENT) {
706+
throw new PythonRecognitionException("duplicate argument '" + $NAME.text + "' in function definition", this, _input, $ctx, getCurrentToken());
707+
}
708+
}
701709
;
702710

703711
stmt
@@ -1691,7 +1699,11 @@ argument [ArgListBuilder args] returns [SSTNode result]
16911699
}
16921700
'=' test
16931701
{
1694-
args.addNamedArg(name, $test.result);
1702+
if (!args.hasNameArg(name)) {
1703+
args.addNamedArg(name, $test.result);
1704+
} else {
1705+
throw new PythonRecognitionException("keyword argument repeated", this, _input, _localctx, getCurrentToken());
1706+
}
16951707
}
16961708
|
16971709
test {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/Python3Parser.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,11 @@ public final KwargsparameterContext kwargsparameter(ArgDefListBuilder args) thro
17871787
}
17881788
}
17891789

1790-
args.addKwargs((_localctx.NAME!=null?_localctx.NAME.getText():null), type);
1790+
1791+
if (args.addKwargs((_localctx.NAME!=null?_localctx.NAME.getText():null), type) == ArgDefListBuilder.AddParamResult.DUPLICATED_ARGUMENT) {
1792+
throw new PythonRecognitionException("duplicate argument '" + (_localctx.NAME!=null?_localctx.NAME.getText():null) + "' in function definition", this, _input, _localctx, getCurrentToken());
1793+
}
1794+
17911795
}
17921796
}
17931797
catch (RecognitionException re) {
@@ -2321,7 +2325,11 @@ public final VkwargsparameterContext vkwargsparameter(ArgDefListBuilder args) th
23212325
match(POWER);
23222326
setState(565);
23232327
_localctx.NAME = match(NAME);
2324-
args.addKwargs((_localctx.NAME!=null?_localctx.NAME.getText():null), null);
2328+
2329+
if (args.addKwargs((_localctx.NAME!=null?_localctx.NAME.getText():null), null) == ArgDefListBuilder.AddParamResult.DUPLICATED_ARGUMENT) {
2330+
throw new PythonRecognitionException("duplicate argument '" + (_localctx.NAME!=null?_localctx.NAME.getText():null) + "' in function definition", this, _input, _localctx, getCurrentToken());
2331+
}
2332+
23252333
}
23262334
}
23272335
catch (RecognitionException re) {
@@ -8267,7 +8275,11 @@ public final ArgumentContext argument(ArgListBuilder args) throws RecognitionExc
82678275
setState(1595);
82688276
_localctx.test = test();
82698277

8270-
args.addNamedArg(name, _localctx.test.result);
8278+
if (!args.hasNameArg(name)) {
8279+
args.addNamedArg(name, _localctx.test.result);
8280+
} else {
8281+
throw new PythonRecognitionException("keyword argument repeated", this, _input, _localctx, getCurrentToken());
8282+
}
82718283

82728284
}
82738285
break;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/sst/ArgDefListBuilder.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public static enum AddParamResult {
129129
}
130130

131131
public AddParamResult addParam(String name, SSTNode type, SSTNode defValue) {
132-
if (paramNames.contains(name)) {
132+
if (paramNames.contains(name) || (splatIndex != -1 && name.equals(args.get(splatIndex).name))) {
133133
return AddParamResult.DUPLICATED_ARGUMENT;
134134
}
135135
if (defValue == null && hasDefaultParameter() && !hasSplat()) {
@@ -175,13 +175,17 @@ public void addSplat(String name, SSTNode type) {
175175
splatIndex = args.size() - 1;
176176
}
177177

178-
public void addKwargs(String name, SSTNode type) {
178+
public AddParamResult addKwargs(String name, SSTNode type) {
179179
// System.out.println("KwArg: " + name);
180+
if (paramNames.contains(name) || (splatIndex != -1 && name.equals(args.get(splatIndex).name))) {
181+
return AddParamResult.DUPLICATED_ARGUMENT;
182+
}
180183
if (kwargs == null) {
181184
kwargs = new ArrayList<>();
182185
}
183186
kwargs.add(new Parameter(name, type));
184187
kwargIndex = kwargs.size() - 1;
188+
return AddParamResult.OK;
185189
}
186190

187191
public boolean hasDefaultParameter() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/sst/ArgListBuilder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ public boolean hasNameArg() {
143143
return !(nameArgNodes == null || nameArgNodes.isEmpty());
144144
}
145145

146+
public boolean hasNameArg(String name) {
147+
return nameArgNames != null && nameArgNames.contains(name);
148+
}
149+
146150
public void addKwArg(SSTNode value) {
147151
if (kwArg == null) {
148152
kwArg = new ArrayList<>();

0 commit comments

Comments
 (0)