mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-105093 Eclipse-way getter/setter completion
This commit is contained in:
+70
-26
@@ -22,14 +22,19 @@ import com.intellij.codeInsight.generation.PsiGenerationInfo;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
@@ -51,6 +56,7 @@ public class JavaGenerateMemberCompletionContributor {
|
||||
andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
|
||||
final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
|
||||
if (parent != null) {
|
||||
addGetterSetterElements(result, parent);
|
||||
addSuperSignatureElements(parent, true, result);
|
||||
addSuperSignatureElements(parent, false, result);
|
||||
}
|
||||
@@ -58,9 +64,38 @@ public class JavaGenerateMemberCompletionContributor {
|
||||
|
||||
}
|
||||
|
||||
private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent) {
|
||||
List<PsiMethod> prototypes = ContainerUtil.newArrayList();
|
||||
for (PsiField field : parent.getFields()) {
|
||||
if (!(field instanceof PsiEnumConstant)) {
|
||||
prototypes.add(PropertyUtil.generateGetterPrototype(field));
|
||||
prototypes.add(PropertyUtil.generateSetterPrototype(field));
|
||||
}
|
||||
}
|
||||
for (final PsiMethod prototype : prototypes) {
|
||||
if (parent.findMethodBySignature(prototype, false) == null) {
|
||||
Icon icon = prototype.getIcon(Iconable.ICON_FLAG_VISIBILITY);
|
||||
result.addElement(createGenerateMethodElement(prototype, PsiSubstitutor.EMPTY, icon, "", new InsertHandler<LookupElement>() {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
removeLookupString(context);
|
||||
|
||||
insertGenerationInfos(context, Arrays.asList(new PsiGenerationInfo<PsiMethod>(prototype)));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeLookupString(InsertionContext context) {
|
||||
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
|
||||
context.commitDocument();
|
||||
}
|
||||
|
||||
private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
|
||||
for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
|
||||
PsiMethod baseMethod = (PsiMethod)candidate.getElement();
|
||||
assert baseMethod != null;
|
||||
PsiClass baseClass = baseMethod.getContainingClass();
|
||||
if (!baseMethod.isConstructor() && baseClass != null) {
|
||||
result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor()));
|
||||
@@ -72,38 +107,47 @@ public class JavaGenerateMemberCompletionContributor {
|
||||
boolean implemented,
|
||||
final PsiMethod baseMethod,
|
||||
PsiClass baseClass, PsiSubstitutor substitutor) {
|
||||
String methodName = baseMethod.getName();
|
||||
|
||||
String visibility = VisibilityUtil.getVisibilityModifier(baseMethod.getModifierList());
|
||||
String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
|
||||
|
||||
PsiType type = substitutor.substitute(baseMethod.getReturnType());
|
||||
String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
|
||||
|
||||
String parameters = PsiFormatUtil.formatMethod(baseMethod, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
|
||||
|
||||
InsertHandler<LookupElement> insertHandler = new InsertHandler<LookupElement>() {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
|
||||
context.commitDocument();
|
||||
|
||||
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
|
||||
List<PsiGenerationInfo<PsiMethod>> infos = OverrideImplementUtil.convert2GenerationInfos(prototypes);
|
||||
List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
|
||||
if (!newInfos.isEmpty()) {
|
||||
newInfos.get(0).positionCaret(context.getEditor(), true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RowIcon icon = new RowIcon(2);
|
||||
icon.setIcon(baseMethod.getIcon(0), 0);
|
||||
icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
|
||||
|
||||
LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(methodName).
|
||||
return createGenerateMethodElement(baseMethod, substitutor, icon, baseClass.getName(), new InsertHandler<LookupElement>() {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
removeLookupString(context);
|
||||
|
||||
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
|
||||
insertGenerationInfos(context, OverrideImplementUtil.convert2GenerationInfos(prototypes));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void insertGenerationInfos(InsertionContext context, List<PsiGenerationInfo<PsiMethod>> infos) {
|
||||
List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil
|
||||
.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
|
||||
if (!newInfos.isEmpty()) {
|
||||
newInfos.get(0).positionCaret(context.getEditor(), true);
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupElementBuilder createGenerateMethodElement(PsiMethod prototype,
|
||||
PsiSubstitutor substitutor,
|
||||
Icon icon,
|
||||
String typeText, InsertHandler<LookupElement> insertHandler) {
|
||||
String methodName = prototype.getName();
|
||||
|
||||
String visibility = VisibilityUtil.getVisibilityModifier(prototype.getModifierList());
|
||||
String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
|
||||
|
||||
PsiType type = substitutor.substitute(prototype.getReturnType());
|
||||
String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
|
||||
|
||||
String parameters = PsiFormatUtil.formatMethod(prototype, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
|
||||
|
||||
LookupElementBuilder element = LookupElementBuilder.create(prototype, signature).withLookupString(methodName).
|
||||
withLookupString(signature).withInsertHandler(insertHandler).
|
||||
appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon);
|
||||
appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(typeText).withIcon(icon);
|
||||
element.putUserData(GENERATE_ELEMENT, true);
|
||||
return element;
|
||||
}
|
||||
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateMembersUtil;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
import com.intellij.codeInsight.generation.PsiGenerationInfo;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.ui.RowIcon;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaOverrideCompletionContributor {
|
||||
static final Key<Boolean> OVERRIDE_ELEMENT = Key.create("OVERRIDE_ELEMENT");
|
||||
|
||||
public static void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiElement position = parameters.getPosition();
|
||||
if (psiElement(PsiIdentifier.class).withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class).
|
||||
andNot(JavaCompletionData.AFTER_DOT).
|
||||
andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
|
||||
final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
|
||||
if (parent != null) {
|
||||
addSuperSignatureElements(parent, true, result);
|
||||
addSuperSignatureElements(parent, false, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
|
||||
for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
|
||||
PsiMethod baseMethod = (PsiMethod)candidate.getElement();
|
||||
PsiClass baseClass = baseMethod.getContainingClass();
|
||||
if (!baseMethod.isConstructor() && baseClass != null) {
|
||||
result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, candidate.getSubstitutor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupElementBuilder createOverridingLookupElement(final PsiClass parent,
|
||||
boolean implemented,
|
||||
final PsiMethod baseMethod,
|
||||
PsiClass baseClass, PsiSubstitutor substitutor) {
|
||||
String methodName = baseMethod.getName();
|
||||
|
||||
String visibility = VisibilityUtil.getVisibilityModifier(baseMethod.getModifierList());
|
||||
String modifiers = (visibility == PsiModifier.PACKAGE_LOCAL ? "" : visibility + " ");
|
||||
|
||||
PsiType type = substitutor.substitute(baseMethod.getReturnType());
|
||||
String signature = modifiers + (type == null ? "" : type.getPresentableText() + " ") + methodName;
|
||||
|
||||
String parameters = PsiFormatUtil.formatMethod(baseMethod, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
|
||||
|
||||
InsertHandler<LookupElement> insertHandler = new InsertHandler<LookupElement>() {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
|
||||
context.commitDocument();
|
||||
|
||||
List<PsiMethod> prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
|
||||
List<PsiGenerationInfo<PsiMethod>> infos = OverrideImplementUtil.convert2GenerationInfos(prototypes);
|
||||
List<PsiGenerationInfo<PsiMethod>> newInfos = GenerateMembersUtil.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
|
||||
if (!newInfos.isEmpty()) {
|
||||
newInfos.get(0).positionCaret(context.getEditor(), true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RowIcon icon = new RowIcon(2);
|
||||
icon.setIcon(baseMethod.getIcon(0), 0);
|
||||
icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
|
||||
|
||||
LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(methodName).
|
||||
withLookupString(signature).withInsertHandler(insertHandler).
|
||||
appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon);
|
||||
element.putUserData(OVERRIDE_ELEMENT, true);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class A {
|
||||
int field;
|
||||
|
||||
publ<caret>
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
public class A {
|
||||
int field;
|
||||
|
||||
public int getField() {
|
||||
<caret><selection>return field;</selection>
|
||||
}
|
||||
}
|
||||
+23
@@ -1325,6 +1325,29 @@ class XInternalError {}
|
||||
checkResult()
|
||||
}
|
||||
|
||||
public void testAccessorViaCompletion() {
|
||||
configure()
|
||||
|
||||
def getter = myFixture.lookupElements.find { it.lookupString == 'public int getField' }
|
||||
def setter = myFixture.lookupElements.find { it.lookupString == 'public void setField' }
|
||||
assert getter : myFixture.lookupElementStrings
|
||||
assert setter : myFixture.lookupElementStrings
|
||||
|
||||
def p = LookupElementPresentation.renderElement(getter)
|
||||
assert p.itemText == getter.lookupString
|
||||
assert p.tailText == '() {...}'
|
||||
assert !p.typeText
|
||||
|
||||
p = LookupElementPresentation.renderElement(setter)
|
||||
assert p.itemText == setter.lookupString
|
||||
assert p.tailText == '(field) {...}'
|
||||
assert !p.typeText
|
||||
|
||||
lookup.currentItem = getter
|
||||
myFixture.type('\n')
|
||||
checkResult()
|
||||
}
|
||||
|
||||
public void testBraceOnNextLine() {
|
||||
codeStyleSettings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE
|
||||
doTest()
|
||||
|
||||
Reference in New Issue
Block a user