mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Change completion lookup policy to always autocomplete
This commit is contained in:
+54
-60
@@ -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<CompletionParameters> {
|
||||
@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<PyStringFormatParser.SubstitutionChunk> substitutions = PyStringFormatParser.filterSubstitutions(
|
||||
final List<PyStringFormatParser.SubstitutionChunk> 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<LookupElementBuilder> keys = getLookupBuilders(formattedString);
|
||||
result.addAllElements(keys);
|
||||
if (keyword!= null) {
|
||||
result.addElement(createLookUpElement(keyword));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<LookupElementBuilder> getLookupBuilders(PyStringLiteralExpression literalExpression) {
|
||||
Map<String, PyStringFormatParser.SubstitutionChunk> 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<LookupElement> getLookupBuilders(@NotNull final PyStringLiteralExpression literalExpression) {
|
||||
final Map<String, PyStringFormatParser.SubstitutionChunk> chunks = PyStringFormatParser.getKeywordSubstitutions(
|
||||
PyStringFormatParser.filterSubstitutions(PyStringFormatParser.parseNewStyleFormat(literalExpression.getStringValue())));
|
||||
List<LookupElementBuilder> keys = new ArrayList<LookupElementBuilder>();
|
||||
final List<LookupElement> keys = new ArrayList<LookupElement>();
|
||||
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--;
|
||||
|
||||
Reference in New Issue
Block a user