IDEA-75072 "import statically" option not provided for smart completion variants, java

This commit is contained in:
peter
2011-10-06 17:24:40 +02:00
parent 971c21fa86
commit e15e871848
11 changed files with 128 additions and 90 deletions

View File

@@ -82,8 +82,8 @@ class CollectionsUtilityMethodsProvider {
}
final PsiMethod method = methods[0];
final JavaMethodCallElement item = new JavaMethodCallElement(method);
JavaCompletionUtil.qualify(item).setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
final JavaMethodCallElement item = new JavaMethodCallElement(method, false, false);
item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType));
result.consume(item);
}

View File

@@ -143,7 +143,7 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone
}
}
private static void removeEndOfIdentifier(InsertionContext context){
public static void removeEndOfIdentifier(InsertionContext context){
final Document document = context.getEditor().getDocument();
JavaCompletionUtil.initOffsets(context.getFile(), context.getProject(), context.getOffsetMap());
document.deleteString(context.getSelectionEndOffset(), context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));

View File

@@ -16,12 +16,8 @@ import javax.swing.*;
public class ImportStaticLookupActionProvider implements LookupActionProvider {
@Override
public void fillActions(final LookupElement element, Lookup lookup, Consumer<LookupElementAction> consumer) {
if (!(element instanceof StaticallyImportable)) {
return;
}
final StaticallyImportable item = (StaticallyImportable)element;
if (!item.canBeImported()) {
final StaticallyImportable item = element.as(StaticallyImportable.CLASS_CONDITION_KEY);
if (item == null || !item.canBeImported()) {
return;
}

View File

@@ -1,10 +1,8 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.lookup.VariableLookupItem;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
@@ -48,11 +46,9 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib
shouldImport |= originalPosition != null && PsiTreeUtil.isAncestor(containingClass, originalPosition, false);
if (member instanceof PsiMethod) {
final JavaMethodCallElement element = new JavaMethodCallElement((PsiMethod)member, true, false);
element.setShouldBeImported(shouldImport);
return element;
return new JavaMethodCallElement((PsiMethod)member, shouldImport, false);
}
return new StaticFieldLookupItem((PsiField)member, shouldImport, containingClass);
return new VariableLookupItem((PsiField)member, shouldImport);
}
@Override
@@ -61,9 +57,8 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib
boolean shouldImport) {
shouldImport |= originalPosition != null && PsiTreeUtil.isAncestor(containingClass, originalPosition, false);
final JavaMethodCallElement element = new JavaMethodCallElement(overloads.get(0), true, true);
final JavaMethodCallElement element = new JavaMethodCallElement(overloads.get(0), shouldImport, true);
element.putUserData(JavaCompletionUtil.ALL_METHODS_ATTRIBUTE, overloads);
element.setShouldBeImported(shouldImport);
return element;
}
};
@@ -79,54 +74,4 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib
return processor;
}
private static class StaticFieldLookupItem extends VariableLookupItem implements StaticallyImportable {
private final MemberLookupHelper myHelper;
private final PsiClass myContainingClass;
public StaticFieldLookupItem(PsiField field, boolean shouldImport, PsiClass containingClass) {
super(field);
myContainingClass = containingClass;
myHelper = new MemberLookupHelper(field, containingClass, shouldImport, false);
}
@Override
public void setShouldBeImported(boolean shouldImportStatic) {
myHelper.setShouldBeImported(shouldImportStatic);
}
@Override
public boolean canBeImported() {
return true;
}
@Override
public boolean willBeImported() {
return myHelper.willBeImported();
}
@Override
public void renderElement(LookupElementPresentation presentation) {
super.renderElement(presentation);
myHelper.renderElement(presentation, getAttribute(FORCE_QUALIFY) != null ? Boolean.TRUE : null, PsiSubstitutor.EMPTY);
}
@Override
public void handleInsert(InsertionContext context) {
if (willBeImported()) {
context.commitDocument();
final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false);
if (ref != null) {
ref.bindToElementViaStaticImport(myContainingClass);
PostprocessReformattingAspect.getInstance(ref.getProject()).doPostponedFormatting();
}
}
super.handleInsert(context);
}
@Override
protected boolean shouldQualify(PsiField field, InsertionContext context) {
return !willBeImported() || super.shouldQualify(field, context);
}
}
}

View File

@@ -39,14 +39,20 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
private final MemberLookupHelper myHelper;
public JavaMethodCallElement(@NotNull PsiMethod method) {
this(method, false, false);
super(method, method.getName());
myMethod = method;
myHelper = null;
myContainingClass = method.getContainingClass();
}
public JavaMethodCallElement(PsiMethod method, boolean canImportStatic, boolean mergedOverloads) {
public JavaMethodCallElement(PsiMethod method, boolean shouldImportStatic, boolean mergedOverloads) {
super(method, method.getName());
myMethod = method;
myContainingClass = method.getContainingClass();
myHelper = canImportStatic ? new MemberLookupHelper(method, myContainingClass, false, mergedOverloads) : null;
myHelper = new MemberLookupHelper(method, myContainingClass, shouldImportStatic, mergedOverloads);
if (!shouldImportStatic) {
forceQualify();
}
}
public PsiType getType() {
@@ -132,7 +138,7 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
return !getInferenceSubstitutor().equals(PsiSubstitutor.EMPTY) && myMethod.getParameterList().getParametersCount() == 0;
}
private boolean mayNeedTypeParameters(InsertionContext context) {
private static boolean mayNeedTypeParameters(InsertionContext context) {
final PsiElement leaf = context.getFile().findElementAt(context.getStartOffset());
if (PsiTreeUtil.getParentOfType(leaf, PsiExpressionList.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) {
if (PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) {

View File

@@ -1,9 +1,13 @@
package com.intellij.codeInsight.completion;
import com.intellij.openapi.util.ClassConditionKey;
/**
* @author peter
*/
public interface StaticallyImportable {
ClassConditionKey<StaticallyImportable> CLASS_CONDITION_KEY = ClassConditionKey.create(StaticallyImportable.class);
void setShouldBeImported(boolean shouldImportStatic);
boolean canBeImported();

View File

@@ -2,22 +2,32 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class VariableLookupItem extends LookupItem<PsiVariable> implements TypedLookupItem {
public class VariableLookupItem extends LookupItem<PsiVariable> implements TypedLookupItem, StaticallyImportable {
@Nullable private final MemberLookupHelper myHelper;
public VariableLookupItem(PsiVariable object) {
super(object, object.getName());
myHelper = null;
}
public VariableLookupItem(PsiField field, boolean shouldImport) {
super(field, field.getName());
myHelper = new MemberLookupHelper(field, field.getContainingClass(), shouldImport, false);
if (!shouldImport) {
forceQualify();
}
}
public PsiType getType() {
@@ -33,6 +43,30 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
public void setSubstitutor(@NotNull PsiSubstitutor substitutor) {
setAttribute(SUBSTITUTOR, substitutor);
}
@Override
public void setShouldBeImported(boolean shouldImportStatic) {
assert myHelper != null;
myHelper.setShouldBeImported(shouldImportStatic);
}
@Override
public boolean canBeImported() {
return myHelper != null;
}
@Override
public boolean willBeImported() {
return myHelper != null && myHelper.willBeImported();
}
@Override
public void renderElement(LookupElementPresentation presentation) {
super.renderElement(presentation);
if (myHelper != null) {
myHelper.renderElement(presentation, getAttribute(FORCE_QUALIFY) != null ? Boolean.TRUE : null, PsiSubstitutor.EMPTY);
}
}
@Override
public LookupItem<PsiVariable> forceQualify() {
@@ -47,14 +81,27 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
@Override
public void handleInsert(InsertionContext context) {
super.handleInsert(context);
PsiVariable variable = getObject();
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), variable.getName());
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
if (variable instanceof PsiField && shouldQualify((PsiField)variable, context)) {
qualifyFieldReference(context, (PsiField)variable);
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), variable.getName());
context.commitDocument();
if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
DefaultInsertHandler.removeEndOfIdentifier(context);
context.commitDocument();
}
if (variable instanceof PsiField) {
if (willBeImported()) {
final PsiReferenceExpression
ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false);
if (ref != null) {
ref.bindToElementViaStaticImport(((PsiField)variable).getContainingClass());
PostprocessReformattingAspect.getInstance(ref.getProject()).doPostponedFormatting();
}
}
else if (shouldQualify((PsiField)variable, context)) {
qualifyFieldReference(context, (PsiField)variable);
}
}
PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
@@ -88,14 +135,19 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
}
}
protected boolean shouldQualify(PsiField field, InsertionContext context) {
private boolean shouldQualify(PsiField field, InsertionContext context) {
if (myHelper != null && !myHelper.willBeImported()) {
return true;
}
if (getAttribute(FORCE_QUALIFY) != null) {
return true;
}
PsiReference reference = context.getFile().findReferenceAt(context.getStartOffset());
if (reference instanceof PsiReferenceExpression && !((PsiReferenceExpression) reference).isQualified()) {
final PsiVariable target = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper().resolveReferencedVariable(field.getName(), (PsiElement)reference);
if (reference instanceof PsiReferenceExpression && !((PsiReferenceExpression)reference).isQualified()) {
final PsiVariable target = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper()
.resolveReferencedVariable(field.getName(), (PsiElement)reference);
return !field.getManager().areElementsEquivalent(target, CompletionUtil.getOriginalOrSelf(field));
}
return false;

View File

@@ -105,7 +105,7 @@ public class JavaMembersGetter extends MembersGetter {
return null;
}
return JavaCompletionUtil.qualify(new VariableLookupItem(field));
return new VariableLookupItem(field, false);
}
@Nullable
@@ -117,8 +117,8 @@ public class JavaMembersGetter extends MembersGetter {
}
JavaMethodCallElement item = new JavaMethodCallElement(method);
JavaMethodCallElement item = new JavaMethodCallElement(method, false, false);
item.setInferenceSubstitutor(substitutor);
return JavaCompletionUtil.qualify(item);
return item;
}
}

View File

@@ -0,0 +1,13 @@
import static Super.FOO;
class Super {
public static final Super FOO = null;
public static Super FOO2() {};
}
class Intermediate {
Super s = FOO;<caret>
}

View File

@@ -0,0 +1,11 @@
class Super {
public static final Super FOO = null;
public static Super FOO2() {};
}
class Intermediate {
Super s = F<caret>
}

View File

@@ -910,7 +910,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testConstructorArgsSmartEnter() throws Exception { doTest(Lookup.COMPLETE_STATEMENT_SELECT_CHAR); }
private void configureByTestName() throws Exception {
private void configureByTestName() {
configureByFile("/" + getTestName(false) + ".java");
}
@@ -1030,6 +1030,17 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testInheritorEnumMembers() throws Throwable { doTest(); }
public void testDuplicateMembersFromSuperClass() throws Throwable { doTest(); }
public void testMemberImportStatically() {
configureByTestName();
StaticallyImportable item = myItems[0].as(StaticallyImportable.CLASS_CONDITION_KEY);
assertNotNull(item);
assertTrue(item.canBeImported());
assertTrue(myItems[1].as(StaticallyImportable.CLASS_CONDITION_KEY).canBeImported());
item.setShouldBeImported(true);
type('\n');
checkResultByTestName();
}
public void testNoNewEnum() throws Throwable {
configureByTestName();
assertStringItems("Foo");
@@ -1127,7 +1138,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
}
private void checkResultByTestName() throws Exception {
private void checkResultByTestName() {
checkResultByFile("/" + getTestName(false) + "-out.java");
}