From f3d77749baa90561e683970e7a4446376bc459fb Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Thu, 26 Nov 2015 14:57:01 +0300 Subject: [PATCH] Change completion lookup policy to always autocomplete --- .../PyStringFormatCompletionContributor.java | 114 +++++++++--------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyStringFormatCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyStringFormatCompletionContributor.java index f821609fb663..90f1d46de05d 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyStringFormatCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PyStringFormatCompletionContributor.java @@ -17,12 +17,13 @@ package com.jetbrains.python.codeInsight.completion; import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ObjectUtils; -import com.intellij.util.PlatformIcons; import com.intellij.util.ProcessingContext; import com.jetbrains.python.inspections.PyStringFormatParser; import com.jetbrains.python.psi.*; @@ -49,37 +50,35 @@ public class PyStringFormatCompletionContributor extends CompletionContributor { private static class FormattedStringCompletionProvider extends CompletionProvider { @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, + protected void addCompletions(@NotNull final CompletionParameters parameters, + final ProcessingContext context, @NotNull CompletionResultSet result) { - PsiElement original = parameters.getOriginalPosition(); + final PsiElement original = parameters.getOriginalPosition(); if (original != null) { - PsiElement parent = original.getParent(); + final PsiElement parent = original.getParent(); if (parent instanceof PyStringLiteralExpression) { - int stringOffset = parameters.getOffset() - parameters.getPosition().getTextRange().getStartOffset(); + final int stringOffset = parameters.getOffset() - parameters.getPosition().getTextRange().getStartOffset(); if (isInsideSubstitutionChunk((PyStringLiteralExpression)parent, stringOffset)) { - PyExpression[] arguments = getFormatFunctionKeyWordArguments(original); - for (PyExpression argument : arguments) { - result = result.withPrefixMatcher(getPrefix(parameters.getOffset(), argument.getContainingFile())); - tryToAddKeysFromStarArgument(result, argument); - tryToAddKeyWordArgument(result, argument); - } + final PyExpression[] arguments = getFormatFunctionKeyWordArguments(original); + for (PyExpression argument : arguments) { + result = result.withPrefixMatcher(getPrefix(parameters.getOffset(), argument.getContainingFile())); + tryToAddKeysFromStarArgument(result, argument); + tryToAddKeyWordArgument(result, argument); + } } } else if (PyUtil.instanceOf(parent, PyKeywordArgument.class, PyReferenceExpression.class)) { - PyArgumentList argumentList = PsiTreeUtil.getParentOfType(original, PyArgumentList.class); + final PyArgumentList argumentList = PsiTreeUtil.getParentOfType(original, PyArgumentList.class); result = result.withPrefixMatcher(getPrefix(parameters.getOffset(), parent.getContainingFile())); tryToAddElementsFromFormattedString(result, argumentList); } } - - } private static boolean isInsideSubstitutionChunk(@NotNull final PyStringLiteralExpression expression, final int offset) { - List substitutions = PyStringFormatParser.filterSubstitutions( + final List substitutions = PyStringFormatParser.filterSubstitutions( PyStringFormatParser.parseNewStyleFormat(expression.getStringValue())); for (PyStringFormatParser.SubstitutionChunk substitution: substitutions) { if (offset >= substitution.getStartIndex() && offset <= substitution.getEndIndex()) { @@ -90,40 +89,36 @@ public class PyStringFormatCompletionContributor extends CompletionContributor { } @NotNull - private static PyExpression[] getFormatFunctionKeyWordArguments(PsiElement original) { - PsiElement pyReferenceExpression = PsiTreeUtil.getParentOfType(original, PyReferenceExpression.class); - PyArgumentList argumentList = PsiTreeUtil.getNextSiblingOfType(pyReferenceExpression, PyArgumentList.class); + private static PyExpression[] getFormatFunctionKeyWordArguments(final PsiElement original) { + final PsiElement pyReferenceExpression = PsiTreeUtil.getParentOfType(original, PyReferenceExpression.class); + final PyArgumentList argumentList = PsiTreeUtil.getNextSiblingOfType(pyReferenceExpression, PyArgumentList.class); if (argumentList != null) { return argumentList.getArguments(); } return PyExpression.EMPTY_ARRAY; } - private static void tryToAddKeysFromStarArgument(@NotNull CompletionResultSet result, @NotNull final PyExpression arg) { + private static void tryToAddKeysFromStarArgument(@NotNull final CompletionResultSet result, @NotNull final PyExpression arg) { if (arg instanceof PyStarArgument) { - PyDictLiteralExpression dict = ObjectUtils.chooseNotNull(PsiTreeUtil.getChildOfType(arg, PyDictLiteralExpression.class), - getDictFromReference(arg)); + final PyDictLiteralExpression dict = ObjectUtils.chooseNotNull(PsiTreeUtil.getChildOfType(arg, PyDictLiteralExpression.class), + getDictFromReference(arg)); if (dict != null) { for (PyKeyValueExpression keyValue: dict.getElements()) { if (keyValue.getKey() instanceof PyStringLiteralExpression) { - String key = ((PyStringLiteralExpression) keyValue.getKey()).getStringValue(); - addElementToResult(result, key); + final String key = ((PyStringLiteralExpression) keyValue.getKey()).getStringValue(); + result.addElement(createLookUpElement(key)); } } } - else { - getDictFromReference(arg); - - } } } - private static PyDictLiteralExpression getDictFromReference(@NotNull PyExpression arg) { - PyReferenceExpression referenceExpression = PsiTreeUtil.getChildOfType(arg, PyReferenceExpression.class); + private static PyDictLiteralExpression getDictFromReference(@NotNull final PyExpression arg) { + final PyReferenceExpression referenceExpression = PsiTreeUtil.getChildOfType(arg, PyReferenceExpression.class); if (referenceExpression != null) { - PsiElement resolveResult = referenceExpression.getReference().resolve(); + final PsiElement resolveResult = referenceExpression.getReference().resolve(); if (resolveResult instanceof PyTargetExpression) { - PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(resolveResult, PyAssignmentStatement.class); + final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(resolveResult, PyAssignmentStatement.class); return PsiTreeUtil.getChildOfType(assignmentStatement, PyDictLiteralExpression.class); } } @@ -133,51 +128,50 @@ public class PyStringFormatCompletionContributor extends CompletionContributor { private static void tryToAddKeyWordArgument(@NotNull final CompletionResultSet result, @NotNull final PyExpression arg) { if (arg instanceof PyKeywordArgument) { final String keyword = ((PyKeywordArgument)arg).getKeyword(); - addElementToResult(result, keyword); - result.stopHere(); - } - } - - @NotNull - private static CompletionResultSet addElementToResult(@NotNull CompletionResultSet result,String element) { - result.addElement(LookupElementBuilder - .create(element) - .withTypeText("arg") - .withIcon(PlatformIcons.VARIABLE_ICON)); - return result; - } - - private static void tryToAddElementsFromFormattedString(@NotNull final CompletionResultSet result, - @Nullable final PyArgumentList argumentList) { - if (argumentList != null) { - PyReferenceExpression pyReferenceExpression = PsiTreeUtil.getPrevSiblingOfType(argumentList, PyReferenceExpression.class); - PyStringLiteralExpression formattedString = PsiTreeUtil.getChildOfType(pyReferenceExpression, PyStringLiteralExpression.class); - if (formattedString != null) { - List keys = getLookupBuilders(formattedString); - result.addAllElements(keys); + if (keyword!= null) { + result.addElement(createLookUpElement(keyword)); } } } @NotNull - private static List getLookupBuilders(PyStringLiteralExpression literalExpression) { - Map chunks = PyStringFormatParser.getKeywordSubstitutions( + private static LookupElement createLookUpElement(@NotNull final String element) { + return LookupElementBuilder + .create(element) + .withTypeText("arg") + .withAutoCompletionPolicy(AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE); + } + + private static void tryToAddElementsFromFormattedString(@NotNull final CompletionResultSet result, + @Nullable final PyArgumentList argumentList) { + if (argumentList != null) { + final PyReferenceExpression pyReferenceExpression = PsiTreeUtil.getPrevSiblingOfType(argumentList, PyReferenceExpression.class); + final PyStringLiteralExpression formattedString = PsiTreeUtil.getChildOfType(pyReferenceExpression, PyStringLiteralExpression.class); + if (formattedString != null) { + result.addAllElements(getLookupBuilders(formattedString)); + } + } + } + + @NotNull + private static List getLookupBuilders(@NotNull final PyStringLiteralExpression literalExpression) { + final Map chunks = PyStringFormatParser.getKeywordSubstitutions( PyStringFormatParser.filterSubstitutions(PyStringFormatParser.parseNewStyleFormat(literalExpression.getStringValue()))); - List keys = new ArrayList(); + final List keys = new ArrayList(); for (String chunk: chunks.keySet()) { - keys.add(LookupElementBuilder.create(chunk).withTypeText("arg").withIcon(PlatformIcons.VARIABLE_ICON)); + keys.add(createLookUpElement(chunk)); } return keys; } } - private static String getPrefix(int offset, PsiFile file) { + private static String getPrefix(int offset, @NotNull final PsiFile file) { if (offset > 0) { offset--; } final String text = file.getText(); - StringBuilder prefixBuilder = new StringBuilder(); + final StringBuilder prefixBuilder = new StringBuilder(); while(offset > 0 && Character.isLetterOrDigit(text.charAt(offset))) { prefixBuilder.insert(0, text.charAt(offset)); offset--;