diff --git a/python/pluginSrc/com/jetbrains/python/psi/impl/PyConstructorArgumentCompletionContributor.java b/python/pluginSrc/com/jetbrains/python/psi/impl/PyConstructorArgumentCompletionContributor.java index 5aed65d844a1..d3b28a436649 100644 --- a/python/pluginSrc/com/jetbrains/python/psi/impl/PyConstructorArgumentCompletionContributor.java +++ b/python/pluginSrc/com/jetbrains/python/psi/impl/PyConstructorArgumentCompletionContributor.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.codeInsight.completion.*; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PropertyUtil; @@ -60,9 +61,10 @@ public class PyConstructorArgumentCompletionContributor extends CompletionContri private static void addSettersAndListeners(CompletionResultSet result, PsiClass containingClass) { // see PyJavaType.init() in Jython source code for matching logic for (PsiMethod method : containingClass.getAllMethods()) { + final Project project = containingClass.getProject(); if (PropertyUtil.isSimplePropertySetter(method)) { final String propName = PropertyUtil.getPropertyName(method); - result.addElement(PyUtil.createNamedParameterLookup(propName)); + result.addElement(PyUtil.createNamedParameterLookup(propName, project)); } else if (method.getName().startsWith("add") && method.getName().endsWith("Listener") && PsiType.VOID.equals(method.getReturnType())) { final PsiParameter[] parameters = method.getParameterList().getParameters(); @@ -71,9 +73,9 @@ public class PyConstructorArgumentCompletionContributor extends CompletionContri if (type instanceof PsiClassType) { final PsiClass parameterClass = ((PsiClassType)type).resolve(); if (parameterClass != null) { - result.addElement(PyUtil.createNamedParameterLookup(StringUtil.decapitalize(parameterClass.getName()))); - for (PsiMethod parameterMethod: parameterClass.getMethods()) { - result.addElement(PyUtil.createNamedParameterLookup(parameterMethod.getName())); + result.addElement(PyUtil.createNamedParameterLookup(StringUtil.decapitalize(parameterClass.getName()), project)); + for (PsiMethod parameterMethod : parameterClass.getMethods()) { + result.addElement(PyUtil.createNamedParameterLookup(parameterMethod.getName(), project)); } } } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 3db3263f6f5a..f6c54feac066 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -64,6 +64,7 @@ import com.jetbrains.python.codeInsight.completion.OverwriteEqualsInsertHandler; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.codeInsight.stdlib.PyNamedTupleType; +import com.jetbrains.python.formatter.PyCodeStyleSettings; import com.jetbrains.python.magicLiteral.PyMagicLiteralTools; import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PyPsiUtils; @@ -1085,8 +1086,23 @@ public class PyUtil { return PyNames.isIdentifier(name); } - public static LookupElement createNamedParameterLookup(String name) { - LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name + "=").withIcon(PlatformIcons.PARAMETER_ICON); + /** + * Constructs new lookup element for completion of keyword argument with equals sign appended. + * + * @param name name of the parameter + * @param project project instance to check code style settings and surround equals sign with spaces if necessary + * @return lookup element + */ + @NotNull + public static LookupElement createNamedParameterLookup(@NotNull String name, @Nullable Project project) { + final String suffix; + if (CodeStyleSettingsManager.getSettings(project).getCustomSettings(PyCodeStyleSettings.class).SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT) { + suffix = " = "; + } + else { + suffix = "="; + } + LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name + suffix).withIcon(PlatformIcons.PARAMETER_ICON); lookupElementBuilder = lookupElementBuilder.withInsertHandler(OverwriteEqualsInsertHandler.INSTANCE); return PrioritizedLookupElement.withGrouping(lookupElementBuilder, 1); } diff --git a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java index 8736e54766ac..772c69e796f2 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java +++ b/python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java @@ -75,7 +75,7 @@ public class KeywordArgumentCompletionUtil { for (PyKeywordArgumentProvider provider : Extensions.getExtensions(PyKeywordArgumentProvider.EP_NAME)) { final List arguments = provider.getKeywordArguments(def, callExpr); for (String argument : arguments) { - ret.add(PyUtil.createNamedParameterLookup(argument)); + ret.add(PyUtil.createNamedParameterLookup(argument, callExpr.getProject())); } } KwArgFromStatementCallCollector fromStatementCallCollector = new KwArgFromStatementCallCollector(ret, collector.getKwArgs()); @@ -119,7 +119,7 @@ public class KeywordArgumentCompletionUtil { PyNamedParameter namedParam = par.getAsNamed(); if (namedParam != null) { if (!namedParam.isKeywordContainer() && !namedParam.isPositionalContainer()) { - final LookupElement item = PyUtil.createNamedParameterLookup(namedParam.getName()); + final LookupElement item = PyUtil.createNamedParameterLookup(namedParam.getName(), par.getProject()); myRet.add(item); } else if (namedParam.isKeywordContainer()) { @@ -202,7 +202,7 @@ public class KeywordArgumentCompletionUtil { argument instanceof PyStringLiteralExpression) { String name = ((PyStringLiteralExpression)argument).getStringValue(); if (PyUtil.isPythonIdentifier(name)) { - myRet.add(PyUtil.createNamedParameterLookup(name)); + myRet.add(PyUtil.createNamedParameterLookup(name, argument.getProject())); } } } diff --git a/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.after.py b/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.after.py new file mode 100644 index 000000000000..b232446d6f72 --- /dev/null +++ b/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.after.py @@ -0,0 +1,4 @@ +def func(foo): + pass + +func(foo = ) \ No newline at end of file diff --git a/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.py b/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.py new file mode 100644 index 000000000000..51a3dabd5a9a --- /dev/null +++ b/python/testData/completion/keywordArgumentEqualsSignSurroundedWithSpaces.py @@ -0,0 +1,4 @@ +def func(foo): + pass + +func(foo) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index a7e1a643f72d..13529efbc11e 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -771,6 +771,12 @@ public class PythonCompletionTest extends PyTestCase { assertSameElements(myFixture.getLookupElementStrings(), "import", "subpkg1", "subpkg2", "m"); } + // PY-15197 + public void testKeywordArgumentEqualsSignSurroundedWithSpaces() { + getPythonCodeStyle().SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT = true; + doTest(); + } + public void testStructuralType() { doTest(); }