From edbd5121590c8a13a8e14668b503234e80fcaeab Mon Sep 17 00:00:00 2001 From: "andrey.matveev" Date: Wed, 3 Jun 2020 19:14:09 +0700 Subject: [PATCH] PY-42772 Impl filtering positional only arguments GitOrigin-RevId: 978dd1f4970d5b1aaa94e251cbf81dee51f2f36c --- .../python/PythonCommonCompletionTest.java | 15 +++++++++++++++ .../references/KeywordArgumentCompletionUtil.java | 13 +++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/python/python-common-tests/com/jetbrains/python/PythonCommonCompletionTest.java b/python/python-common-tests/com/jetbrains/python/PythonCommonCompletionTest.java index e5473d96c9fc..a3dc89dc6bdf 100644 --- a/python/python-common-tests/com/jetbrains/python/PythonCommonCompletionTest.java +++ b/python/python-common-tests/com/jetbrains/python/PythonCommonCompletionTest.java @@ -1841,6 +1841,21 @@ public abstract class PythonCommonCompletionTest extends PythonCommonTestCase { ); } + // PY-42772 + public void testNoPositionalOnlyArgumentsSuggestion() { + runWithLanguageLevel( + LanguageLevel.getLatest(), + () -> { + List suggested = doTestByText("def foo(argument_1, /, argument_2):\n" + + " pass\n" + + "\n" + + "foo()"); + assertContainsElements(suggested, "argument_2="); + assertDoesntContain(suggested, "argument_1="); + } + ); + } + private void doTestHasattrContributor(String[] inList, String[] notInList) { doTestHasattrContributor("hasattrCompletion/" + getTestName(true) + ".py", inList, notInList); } diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java index 1e203084b531..3e30d688ed08 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java @@ -59,7 +59,8 @@ public class KeywordArgumentCompletionUtil { if (type.isCallable()) { final List parameters = type.getParameters(context); if (parameters != null) { - for (PyCallableParameter parameter : parameters) { + int indexOfPySlashParameter = getIndexOfPySlashParameter(parameters); + for (PyCallableParameter parameter : parameters.subList(indexOfPySlashParameter + 1, parameters.size())) { if (parameter.isKeywordContainer() || parameter.isPositionalContainer()) { continue; } @@ -86,6 +87,10 @@ public class KeywordArgumentCompletionUtil { return result.getElement(); } + private static int getIndexOfPySlashParameter(@NotNull List parameters) { + return ContainerUtil.indexOf(parameters, parameter -> parameter.getParameter() instanceof PySlashParameter); + } + private static void addKeywordArgumentVariantsForFunction(@NotNull final PyCallExpression callExpr, @NotNull final PyFunction function, @NotNull final List ret, @@ -98,8 +103,12 @@ public class KeywordArgumentCompletionUtil { boolean needSelf = function.getContainingClass() != null && function.getModifier() != PyFunction.Modifier.STATICMETHOD; final KwArgParameterCollector collector = new KwArgParameterCollector(needSelf, ret); + List parameters = function.getParameters(context); + int indexOfPySlashParameter = getIndexOfPySlashParameter(parameters); + StreamEx - .of(function.getParameters(context)) + .of(parameters) + .skip(indexOfPySlashParameter + 1) .map(PyCallableParameter::getParameter) .nonNull() .forEach(parameter -> parameter.accept(collector));