IDEA-121071 Annotation param: autocomplete inverse of default value for boolean

GitOrigin-RevId: e708f1345377d8803c9f300039b19dcf6715a138
This commit is contained in:
Peter Gromov
2020-06-09 11:53:38 +03:00
committed by intellij-monorepo-bot
parent 9a8e82e631
commit aa1fde421a
5 changed files with 70 additions and 26 deletions
@@ -1,6 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.completion;
import com.intellij.application.options.CodeStyle;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.TailType;
@@ -60,6 +61,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.codeInsight.completion.ReferenceExpressionCompletionContributor.getSpace;
import static com.intellij.patterns.PsiJavaPatterns.*;
/**
@@ -624,36 +626,50 @@ public class JavaCompletionContributor extends CompletionContributor {
if (Objects.equals(existingAttr.getName(), attrName) ||
PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(attrName) && existingAttr.getName() == null) continue methods;
}
LookupElementBuilder element = LookupElementBuilder.createWithIcon(method)
.withStrikeoutness(PsiImplUtil.isDeprecated(method))
.withInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
final Editor editor = context.getEditor();
EqTailType.INSTANCE.processTail(editor, editor.getCaretModel().getOffset());
context.setAddCompletionChar(false);
context.commitDocument();
PsiAnnotationParameterList paramList =
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiAnnotationParameterList.class, false);
if (paramList != null && paramList.getAttributes().length > 0 && paramList.getAttributes()[0].getName() == null) {
int valueOffset = paramList.getAttributes()[0].getTextRange().getStartOffset();
context.getDocument().insertString(valueOffset, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
EqTailType.INSTANCE.processTail(editor, valueOffset + PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.length());
}
}
});
PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)method).getDefaultValue();
if (defaultValue != null) {
element = element.withTailText(" default " + defaultValue.getText(), true);
String defText = defaultValue == null ? null : defaultValue.getText();
if (PsiKeyword.TRUE.equals(defText) || PsiKeyword.FALSE.equals(defText)) {
result.addElement(createAnnotationAttributeElement(method, PsiKeyword.TRUE.equals(defText) ? PsiKeyword.FALSE : PsiKeyword.TRUE));
result.addElement(PrioritizedLookupElement.withPriority(createAnnotationAttributeElement(method, defText).withTailText(" (default)", true), -1));
} else {
LookupElementBuilder element = createAnnotationAttributeElement(method, null);
if (defText != null) {
element = element.withTailText(" default " + defText, true);
}
result.addElement(element);
}
result.addElement(element);
}
}
}
@NotNull
private static LookupElementBuilder createAnnotationAttributeElement(PsiMethod annoMethod, @Nullable String value) {
String space = getSpace(CodeStyle.getLanguageSettings(annoMethod.getContainingFile()).SPACE_AROUND_ASSIGNMENT_OPERATORS);
String lookupString = annoMethod.getName() + (value == null ? "" : space + "=" + space + value);
return LookupElementBuilder.create(annoMethod, lookupString).withIcon(annoMethod.getIcon(0))
.withStrikeoutness(PsiImplUtil.isDeprecated(annoMethod))
.withInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
final Editor editor = context.getEditor();
if (value == null) {
EqTailType.INSTANCE.processTail(editor, editor.getCaretModel().getOffset());
}
context.setAddCompletionChar(false);
context.commitDocument();
PsiAnnotationParameterList paramList =
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiAnnotationParameterList.class, false);
if (paramList != null && paramList.getAttributes().length > 0 && paramList.getAttributes()[0].getName() == null) {
int valueOffset = paramList.getAttributes()[0].getTextRange().getStartOffset();
context.getDocument().insertString(valueOffset, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME);
EqTailType.INSTANCE.processTail(editor, valueOffset + PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.length());
}
}
});
}
@Override
public String advertise(@NotNull final CompletionParameters parameters) {
if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return null;
@@ -1,6 +1,6 @@
@interface Anno {
String myString() default "unknown";
boolean myBool() default false;
int myInt() default 42;
}
@Anno(<caret>)
@@ -0,0 +1,8 @@
@Anno(<caret>)
class C {
}
@interface Anno {
boolean value() default true;
boolean smth() default false;
}
@@ -0,0 +1,8 @@
@Anno(smth = true<caret>)
class C {
}
@interface Anno {
boolean value() default true;
boolean smth() default false;
}
@@ -103,8 +103,8 @@ class NormalCompletionTest extends NormalCompletionTestCase {
void testDisplayDefaultValueInAnnotationMethods() {
configure()
LookupElementPresentation presentation = renderElement(myItems[0])
assert "myBool" == presentation.itemText
assert presentation.tailText == " default false"
assert "myInt" == presentation.itemText
assert presentation.tailText == " default 42"
assert presentation.tailFragments[0].grayed
assert !presentation.typeText
assert !presentation.itemTextBold
@@ -1984,6 +1984,18 @@ class Abc {
checkGetClassPresent("class C implements Unresolved {{ getCl<caret>x }}")
checkGetClassPresent("class C extends Unresolved implements Runnable {{ getCl<caret>x }}")
checkGetClassPresent("class C extends Unresolved1 implements Unresolved2 {{ getCl<caret>x }}")
}
void testSuggestInverseOfDefaultAnnoParamValueForBoolean() {
configureByTestName()
myFixture.assertPreferredCompletionItems(0, 'smth = true', 'value = false')
def smthDefault = myItems.find { it.lookupString == 'smth = false' }
def presentation = LookupElementPresentation.renderElement(smthDefault)
assert presentation.tailText == ' (default)'
assert presentation.tailFragments[0].grayed
myFixture.type('\n')
checkResult()
}
}