mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ public class ExcludeFromCompletionLookupActionProvider implements LookupActionPr
|
||||
} else if (o instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)o;
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
addExcludes(consumer, method, StaticImportMethodFix.getMethodQualifiedName(method));
|
||||
addExcludes(consumer, method, StaticImportMethodFix.getMemberQualifiedName(method));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-51
@@ -3,9 +3,10 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -16,92 +17,54 @@ import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaGlobalMemberLookupElement extends LookupElement implements StaticallyImportable {
|
||||
private final PsiMember myMember;
|
||||
private final boolean myMergedOverloads;
|
||||
private final PsiClass myContainingClass;
|
||||
private final MemberLookupHelper myHelper;
|
||||
private final InsertHandler<JavaGlobalMemberLookupElement> myQualifiedInsertion;
|
||||
private final InsertHandler<JavaGlobalMemberLookupElement> myImportInsertion;
|
||||
private boolean myShouldImport = false;
|
||||
|
||||
public JavaGlobalMemberLookupElement(List<PsiMethod> overloads,
|
||||
PsiClass containingClass,
|
||||
InsertHandler<JavaGlobalMemberLookupElement> qualifiedInsertion,
|
||||
InsertHandler<JavaGlobalMemberLookupElement> importInsertion, boolean shouldImport) {
|
||||
myMember = overloads.get(0);
|
||||
myContainingClass = containingClass;
|
||||
myHelper = new MemberLookupHelper(overloads, containingClass, shouldImport);
|
||||
myQualifiedInsertion = qualifiedInsertion;
|
||||
myImportInsertion = importInsertion;
|
||||
myShouldImport = shouldImport;
|
||||
myMergedOverloads = true;
|
||||
}
|
||||
|
||||
public JavaGlobalMemberLookupElement(PsiMember member,
|
||||
PsiClass containingClass,
|
||||
InsertHandler<JavaGlobalMemberLookupElement> qualifiedInsertion,
|
||||
InsertHandler<JavaGlobalMemberLookupElement> importInsertion, boolean shouldImport) {
|
||||
myMember = member;
|
||||
myContainingClass = containingClass;
|
||||
myHelper = new MemberLookupHelper(member, containingClass, shouldImport, false);
|
||||
myQualifiedInsertion = qualifiedInsertion;
|
||||
myImportInsertion = importInsertion;
|
||||
myShouldImport = shouldImport;
|
||||
myMergedOverloads = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMember getObject() {
|
||||
return myMember;
|
||||
return myHelper.getMember();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiClass getContainingClass() {
|
||||
return myContainingClass;
|
||||
return assertNotNull(myHelper.getContainingClass());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getLookupString() {
|
||||
return assertNotNull(myMember.getName());
|
||||
return assertNotNull(getObject().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderElement(LookupElementPresentation presentation) {
|
||||
final String className = myContainingClass.getName();
|
||||
|
||||
presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(this, presentation.isReal()));
|
||||
|
||||
final String methodName = myMember.getName();
|
||||
if (Boolean.FALSE.equals(myShouldImport) && StringUtil.isNotEmpty(className)) {
|
||||
presentation.setItemText(className + "." + methodName);
|
||||
} else {
|
||||
presentation.setItemText(methodName);
|
||||
}
|
||||
|
||||
final String qname = myContainingClass.getQualifiedName();
|
||||
String location = StringUtil.isEmpty(qname) ? "" : " (" + StringUtil.getPackageName(qname) + ")";
|
||||
|
||||
final String params = myMergedOverloads
|
||||
? "(...)"
|
||||
: myMember instanceof PsiMethod
|
||||
? PsiFormatUtil.formatMethod((PsiMethod)myMember, PsiSubstitutor.EMPTY,
|
||||
PsiFormatUtil.SHOW_PARAMETERS,
|
||||
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE)
|
||||
: "";
|
||||
if (Boolean.TRUE.equals(myShouldImport) && StringUtil.isNotEmpty(className)) {
|
||||
presentation.setTailText(params + " in " + className + location);
|
||||
} else {
|
||||
presentation.setTailText(params + location);
|
||||
}
|
||||
|
||||
final PsiType type = myMember instanceof PsiMethod ? ((PsiMethod)myMember).getReturnType() : ((PsiField) myMember).getType();
|
||||
if (type != null) {
|
||||
presentation.setTypeText(type.getPresentableText());
|
||||
}
|
||||
myHelper.renderElement(presentation, false, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShouldBeImported(boolean shouldImportStatic) {
|
||||
myShouldImport = shouldImportStatic;
|
||||
myHelper.setShouldBeImported(shouldImportStatic);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,11 +74,12 @@ public class JavaGlobalMemberLookupElement extends LookupElement implements Stat
|
||||
|
||||
@Override
|
||||
public boolean willBeImported() {
|
||||
return myShouldImport;
|
||||
return myHelper.willBeImported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context) {
|
||||
(myShouldImport ? myImportInsertion : myQualifiedInsertion).handleInsert(context, this);
|
||||
(willBeImported() ? myImportInsertion : myQualifiedInsertion).handleInsert(context, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+51
-16
@@ -1,6 +1,7 @@
|
||||
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;
|
||||
@@ -20,9 +21,7 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib
|
||||
return;
|
||||
}
|
||||
|
||||
final PrefixMatcher matcher = result.getPrefixMatcher();
|
||||
final String prefix = matcher.getPrefix();
|
||||
if (prefix.length() == 0 || !Character.isLowerCase(prefix.charAt(0))) {
|
||||
if (result.getPrefixMatcher().getPrefix().length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,24 +42,13 @@ public class JavaGlobalMemberNameCompletionContributor extends CompletionContrib
|
||||
final StaticMemberProcessor processor = new StaticMemberProcessor(position) {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LookupElement createLookupElement(@NotNull PsiMember member, @NotNull final PsiClass containingClass, boolean shouldImport) {
|
||||
protected LookupElement createLookupElement(@NotNull PsiMember member, @NotNull final PsiClass containingClass, final boolean shouldImport) {
|
||||
if (member instanceof PsiMethod) {
|
||||
final JavaMethodCallElement element = new JavaMethodCallElement((PsiMethod)member, true, false);
|
||||
element.setShouldBeImported(shouldImport);
|
||||
return element;
|
||||
}
|
||||
return new VariableLookupItem((PsiVariable)member) {
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context) {
|
||||
context.commitDocument();
|
||||
final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false);
|
||||
if (ref != null) {
|
||||
ref.bindToElementViaStaticImport(containingClass);
|
||||
PostprocessReformattingAspect.getInstance(ref.getProject()).doPostponedFormatting();
|
||||
}
|
||||
super.handleInsert(context);
|
||||
}
|
||||
};
|
||||
return new StaticFieldLookupItem((PsiField)member, shouldImport, containingClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,4 +74,51 @@ 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, 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();
|
||||
}
|
||||
} else {
|
||||
context.getDocument().insertString(context.getStartOffset(), ".");
|
||||
JavaCompletionUtil.insertClassReference(myContainingClass, context.getFile(), context.getStartOffset());
|
||||
}
|
||||
super.handleInsert(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.ClassConditionKey;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,9 +37,7 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
|
||||
private static final Key<PsiSubstitutor> INFERENCE_SUBSTITUTOR = Key.create("INFERENCE_SUBSTITUTOR");
|
||||
@Nullable private final PsiClass myContainingClass;
|
||||
private final PsiMethod myMethod;
|
||||
private final boolean myCanImportStatic;
|
||||
private boolean myShouldImportStatic;
|
||||
private final boolean myMergedOverloads;
|
||||
private final MemberLookupHelper myHelper;
|
||||
|
||||
public JavaMethodCallElement(@NotNull PsiMethod method) {
|
||||
this(method, false, false);
|
||||
@@ -50,9 +46,8 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
|
||||
public JavaMethodCallElement(PsiMethod method, boolean canImportStatic, boolean mergedOverloads) {
|
||||
super(method, method.getName());
|
||||
myMethod = method;
|
||||
myMergedOverloads = mergedOverloads;
|
||||
myContainingClass = method.getContainingClass();
|
||||
myCanImportStatic = canImportStatic;
|
||||
myHelper = canImportStatic ? new MemberLookupHelper(method, myContainingClass, false, mergedOverloads) : null;
|
||||
}
|
||||
|
||||
public PsiType getType() {
|
||||
@@ -77,18 +72,17 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
|
||||
|
||||
@Override
|
||||
public void setShouldBeImported(boolean shouldImportStatic) {
|
||||
assert myCanImportStatic;
|
||||
myShouldImportStatic = shouldImportStatic;
|
||||
myHelper.setShouldBeImported(shouldImportStatic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeImported() {
|
||||
return myCanImportStatic;
|
||||
return myHelper != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean willBeImported() {
|
||||
return myShouldImportStatic;
|
||||
return canBeImported() && myHelper.willBeImported();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,9 +102,9 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
|
||||
qualifyMethodCall(file, startOffset, document);
|
||||
insertExplicitTypeParameters(context, refStart);
|
||||
}
|
||||
else if (myCanImportStatic || getAttribute(FORCE_QUALIFY) != null) {
|
||||
else if (myHelper != null || getAttribute(FORCE_QUALIFY) != null) {
|
||||
context.commitDocument();
|
||||
if (myCanImportStatic && myShouldImportStatic) {
|
||||
if (myHelper != null && willBeImported()) {
|
||||
final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(file, startOffset, PsiReferenceExpression.class, false);
|
||||
if (ref != null && myContainingClass != null) {
|
||||
ref.bindToElementViaStaticImport(myContainingClass);
|
||||
@@ -234,38 +228,12 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
|
||||
|
||||
@Override
|
||||
public void renderElement(LookupElementPresentation presentation) {
|
||||
final String className = myContainingClass == null ? "???" : myContainingClass.getName();
|
||||
|
||||
presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(this, presentation.isReal()));
|
||||
|
||||
final String methodName = myMethod.getName();
|
||||
final boolean qualify = myCanImportStatic && !myShouldImportStatic || getAttribute(FORCE_QUALIFY) != null;
|
||||
if (qualify && StringUtil.isNotEmpty(className)) {
|
||||
presentation.setItemText(className + "." + methodName);
|
||||
} else {
|
||||
presentation.setItemText(methodName);
|
||||
}
|
||||
|
||||
final String qname = myContainingClass == null ? "" : myContainingClass.getQualifiedName();
|
||||
String location = !myCanImportStatic || StringUtil.isEmpty(qname) ? "" : " (" + StringUtil.getPackageName(qname) + ")";
|
||||
|
||||
presentation.setStrikeout(JavaElementLookupRenderer.isToStrikeout(this));
|
||||
presentation.setItemTextBold(getAttribute(HIGHLIGHTED_ATTR) != null);
|
||||
|
||||
final String params = myMergedOverloads
|
||||
? "(...)"
|
||||
: PsiFormatUtil.formatMethod(myMethod, PsiSubstitutor.EMPTY,
|
||||
PsiFormatUtil.SHOW_PARAMETERS,
|
||||
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE);
|
||||
if (myShouldImportStatic && StringUtil.isNotEmpty(className)) {
|
||||
presentation.setTailText(params + " in " + className + location);
|
||||
} else {
|
||||
presentation.setTailText(params + location);
|
||||
}
|
||||
|
||||
final PsiType type = myMethod.getReturnType();
|
||||
if (type != null) {
|
||||
presentation.setTypeText(getSubstitutor().substitute(type).getPresentableText());
|
||||
}
|
||||
MemberLookupHelper helper = myHelper != null ? myHelper : new MemberLookupHelper(myMethod, myContainingClass, false, false);
|
||||
helper.renderElement(presentation, getAttribute(FORCE_QUALIFY) != null, getSubstitutor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class MemberLookupHelper {
|
||||
private final PsiMember myMember;
|
||||
private final boolean myMergedOverloads;
|
||||
@Nullable private final PsiClass myContainingClass;
|
||||
private boolean myShouldImport = false;
|
||||
|
||||
public MemberLookupHelper(List<PsiMethod> overloads, PsiClass containingClass, boolean shouldImport) {
|
||||
this(overloads.get(0), containingClass, shouldImport, true);
|
||||
}
|
||||
|
||||
public MemberLookupHelper(PsiMember member, PsiClass containingClass, boolean shouldImport, final boolean mergedOverloads) {
|
||||
myMember = member;
|
||||
myContainingClass = containingClass;
|
||||
myShouldImport = shouldImport;
|
||||
myMergedOverloads = mergedOverloads;
|
||||
}
|
||||
|
||||
public PsiMember getMember() {
|
||||
return myMember;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiClass getContainingClass() {
|
||||
return myContainingClass;
|
||||
}
|
||||
|
||||
public void setShouldBeImported(boolean shouldImportStatic) {
|
||||
myShouldImport = shouldImportStatic;
|
||||
}
|
||||
|
||||
public boolean willBeImported() {
|
||||
return myShouldImport;
|
||||
}
|
||||
|
||||
public void renderElement(LookupElementPresentation presentation, boolean forceQualify, PsiSubstitutor substitutor) {
|
||||
final String className = myContainingClass == null ? "???" : myContainingClass.getName();
|
||||
|
||||
final String memberName = myMember.getName();
|
||||
if (!myShouldImport && StringUtil.isNotEmpty(className) || forceQualify) {
|
||||
presentation.setItemText(className + "." + memberName);
|
||||
} else {
|
||||
presentation.setItemText(memberName);
|
||||
}
|
||||
|
||||
final String qname = myContainingClass == null ? "" : myContainingClass.getQualifiedName();
|
||||
String pkg = StringUtil.getPackageName(qname);
|
||||
String location = StringUtil.isEmpty(pkg) ? "" : " (" + pkg + ")";
|
||||
|
||||
final String params = myMergedOverloads
|
||||
? "(...)"
|
||||
: myMember instanceof PsiMethod
|
||||
? PsiFormatUtil.formatMethod((PsiMethod)myMember, PsiSubstitutor.EMPTY,
|
||||
PsiFormatUtil.SHOW_PARAMETERS,
|
||||
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE)
|
||||
: "";
|
||||
if (myShouldImport && StringUtil.isNotEmpty(className)) {
|
||||
presentation.setTailText(params + " in " + className + location);
|
||||
} else {
|
||||
presentation.setTailText(params + location, !(myMember instanceof PsiMethod));
|
||||
}
|
||||
|
||||
final PsiType type = myMember instanceof PsiMethod ? ((PsiMethod)myMember).getReturnType() : ((PsiField) myMember).getType();
|
||||
if (type != null) {
|
||||
presentation.setTypeText(substitutor.substitute(type).getPresentableText());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+6
-3
@@ -33,7 +33,7 @@ public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends LookupEle
|
||||
|
||||
enum MyResult {
|
||||
annoMethod,
|
||||
returnKeyword,
|
||||
probableKeyword,
|
||||
localOrParameter,
|
||||
superMethodParameters,
|
||||
normal,
|
||||
@@ -46,8 +46,11 @@ public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends LookupEle
|
||||
public MyResult weigh(@NotNull LookupElement item) {
|
||||
final Object object = item.getObject();
|
||||
|
||||
if (object instanceof PsiKeyword && PsiKeyword.RETURN.equals(((PsiKeyword)object).getText())) {
|
||||
return MyResult.returnKeyword;
|
||||
if (object instanceof PsiKeyword) {
|
||||
String keyword = ((PsiKeyword)object).getText();
|
||||
if (PsiKeyword.RETURN.equals(keyword) || PsiKeyword.ELSE.equals(keyword) || PsiKeyword.FINALLY.equals(keyword)) {
|
||||
return MyResult.probableKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
if (object instanceof PsiLocalVariable || object instanceof PsiParameter || object instanceof PsiThisExpression) {
|
||||
|
||||
@@ -69,13 +69,7 @@ public abstract class StaticMemberProcessor {
|
||||
|
||||
if (classes.add(containingClass) && JavaCompletionUtil.isSourceLevelAccessible(myPosition, containingClass, myPackagedContext)) {
|
||||
final boolean shouldImport = myStaticImportedClasses.contains(containingClass);
|
||||
if (!myHintShown && !shouldImport && CompletionService.getCompletionService().getAdvertisementText() == null) {
|
||||
final String shortcut = CompletionContributor.getActionShortcut(IdeActions.ACTION_SHOW_INTENTION_ACTIONS);
|
||||
if (shortcut != null) {
|
||||
CompletionService.getCompletionService().setAdvertisementText("To import a method statically, press " + shortcut);
|
||||
}
|
||||
myHintShown = true;
|
||||
}
|
||||
showHint(shouldImport);
|
||||
|
||||
final PsiMethod[] allMethods = containingClass.getAllMethods();
|
||||
final List<PsiMethod> overloads = ContainerUtil.findAll(allMethods, new Condition<PsiMethod>() {
|
||||
@@ -100,6 +94,32 @@ public abstract class StaticMemberProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final String fieldName : namesCache.getAllFieldNames()) {
|
||||
if (matcher.prefixMatches(fieldName)) {
|
||||
for (final PsiField field : namesCache.getFieldsByName(fieldName, scope)) {
|
||||
if (isStaticallyImportable(field)) {
|
||||
final PsiClass containingClass = field.getContainingClass();
|
||||
assert containingClass != null;
|
||||
|
||||
if (JavaCompletionUtil.isSourceLevelAccessible(myPosition, containingClass, myPackagedContext)) {
|
||||
final boolean shouldImport = myStaticImportedClasses.contains(containingClass);
|
||||
showHint(shouldImport);
|
||||
consumer.consume(createLookupElement(field, containingClass, shouldImport));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showHint(boolean shouldImport) {
|
||||
if (!myHintShown && !shouldImport && CompletionService.getCompletionService().getAdvertisementText() == null) {
|
||||
final String shortcut = CompletionContributor.getActionShortcut(IdeActions.ACTION_SHOW_INTENTION_ACTIONS);
|
||||
if (shortcut != null) {
|
||||
CompletionService.getCompletionService().setAdvertisementText("To import a method statically, press " + shortcut);
|
||||
}
|
||||
myHintShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
public List<PsiMember> processMembersOfRegisteredClasses(@Nullable final PrefixMatcher matcher, PairConsumer<PsiMember, PsiClass> consumer) {
|
||||
@@ -113,7 +133,7 @@ public abstract class StaticMemberProcessor {
|
||||
}
|
||||
}
|
||||
for (final PsiField field : psiClass.getAllFields()) {
|
||||
if (matcher == null || matcher.prefixMatches(field.getName())) {
|
||||
if (matcher == null || matcher.prefixMatches(field. getName())) {
|
||||
if (isStaticallyImportable(field)) {
|
||||
consumer.consume(field, psiClass);
|
||||
}
|
||||
@@ -125,17 +145,11 @@ public abstract class StaticMemberProcessor {
|
||||
|
||||
|
||||
private boolean isStaticallyImportable(final PsiMember member) {
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC) && myResolveHelper.isAccessible(member, myPosition, null)) {
|
||||
final PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
if (!JavaCompletionUtil.isInExcludedPackage(containingClass) &&
|
||||
(!(member instanceof PsiMethod) || !StaticImportMethodFix.isExcluded((PsiMethod)member))) {
|
||||
return true;
|
||||
}
|
||||
return member.hasModifierProperty(PsiModifier.STATIC) && isAccessible(member) && !StaticImportMethodFix.isExcluded(member);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
protected boolean isAccessible(PsiMember member) {
|
||||
return myResolveHelper.isAccessible(member, myPosition, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+3
-1
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.completion.scope;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -109,7 +110,8 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInitializedImplicitly(final PsiField field) {
|
||||
private static boolean isInitializedImplicitly(PsiField field) {
|
||||
field = JavaCompletionUtil.getOriginalElement(field);
|
||||
for(ImplicitUsageProvider provider: ImplicitUsageProvider.EP_NAME.getExtensions()) {
|
||||
if (provider.isImplicitWrite(field)) {
|
||||
return true;
|
||||
|
||||
+4
-4
@@ -142,8 +142,8 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isExcluded(PsiMethod method) {
|
||||
String name = getMethodQualifiedName(method);
|
||||
public static boolean isExcluded(PsiMember method) {
|
||||
String name = getMemberQualifiedName(method);
|
||||
if (name == null) return false;
|
||||
CodeInsightSettings cis = CodeInsightSettings.getInstance();
|
||||
for (String excluded : cis.EXCLUDED_PACKAGES) {
|
||||
@@ -204,7 +204,7 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
String qname = getMethodQualifiedName(selectedValue);
|
||||
String qname = getMemberQualifiedName(selectedValue);
|
||||
if (qname == null) return FINAL_CHOICE;
|
||||
List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
|
||||
return new BaseListPopupStep<String>(null, excludableStrings) {
|
||||
@@ -270,7 +270,7 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getMethodQualifiedName(PsiMethod method) {
|
||||
public static String getMemberQualifiedName(PsiMember method) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return null;
|
||||
String className = containingClass.getQualifiedName();
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.completion.CodeCompletionFeatures;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -35,6 +36,12 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
|
||||
public void handleInsert(InsertionContext context) {
|
||||
super.handleInsert(context);
|
||||
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
|
||||
PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
|
||||
if (ref != null) {
|
||||
JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(ref);
|
||||
}
|
||||
|
||||
final char completionChar = context.getCompletionChar();
|
||||
if (completionChar == '=') {
|
||||
context.setAddCompletionChar(false);
|
||||
@@ -53,7 +60,6 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
|
||||
}
|
||||
else if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(getObject().getType())) {
|
||||
context.setAddCompletionChar(false);
|
||||
final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
|
||||
if (ref != null) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
|
||||
context.getDocument().insertString(ref.getTextRange().getStartOffset(), "!");
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
@@ -238,6 +239,19 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
|
||||
else if (myRole2 == ChildRole.RBRACE && aClass.isEnum()) {
|
||||
createParenthSpace(true, false);
|
||||
}
|
||||
else if (aClass instanceof PsiAnonymousClass && ElementType.JAVA_PLAIN_COMMENT_BIT_SET.contains(myChild1.getElementType())) {
|
||||
ASTNode prev = myChild1.getTreePrev();
|
||||
if (prev.getElementType() == JavaTokenType.WHITE_SPACE && !StringUtil.containsLineBreak(prev.getChars())) {
|
||||
prev = prev.getTreePrev();
|
||||
}
|
||||
if (prev.getElementType() == JavaTokenType.LBRACE) {
|
||||
myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER + 1,
|
||||
mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
}
|
||||
else {
|
||||
processClassBody();
|
||||
}
|
||||
}
|
||||
else processClassBody();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ public class KnownElementWeigher extends ProximityWeigher {
|
||||
if (qname != null) {
|
||||
if (qname.startsWith("java.")) return 2;
|
||||
if (qname.startsWith("javax.")) return 1;
|
||||
if (qname.startsWith("com.")) return -1;
|
||||
if (qname.startsWith("net.")) return -1;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiMethod) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
{
|
||||
Bar b = FOOOO<caret>
|
||||
}
|
||||
|
||||
enum Bar {
|
||||
FOOOOOOO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Foo {
|
||||
{
|
||||
Bar b = Bar.FOOOOOOO<caret>
|
||||
}
|
||||
|
||||
enum Bar {
|
||||
FOOOOOOO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Foo {
|
||||
{
|
||||
Object element;
|
||||
if (true) {}
|
||||
el<caret>
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -24,6 +24,36 @@ public class Foo {
|
||||
class Bar {{ abcmethod()<caret> }}"""
|
||||
}
|
||||
|
||||
public void testFieldName() throws Exception {
|
||||
myFixture.addClass("""
|
||||
package foo;
|
||||
|
||||
public class Foo {
|
||||
public static int abcfield = 2
|
||||
static final int fieldThatsNotVisible = 3
|
||||
}
|
||||
""")
|
||||
|
||||
doTest "class Bar {{ abcf<caret> }}", true, """import static foo.Foo.abcfield;
|
||||
|
||||
class Bar {{ abcfield<caret> }}"""
|
||||
}
|
||||
|
||||
public void testFieldNameQualified() throws Exception {
|
||||
myFixture.addClass("""
|
||||
package foo;
|
||||
|
||||
public class Foo {
|
||||
public static int abcfield = 2
|
||||
static final int fieldThatsNotVisible = 3
|
||||
}
|
||||
""")
|
||||
|
||||
doTest "class Bar {{ abcf<caret> }}", false, """import foo.Foo;
|
||||
|
||||
class Bar {{ Foo.abcfield<caret> }}"""
|
||||
}
|
||||
|
||||
public void testQualifiedMethodName() throws Exception {
|
||||
myFixture.addClass("""
|
||||
package foo;
|
||||
|
||||
+4
@@ -217,6 +217,10 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
checkPreferredItems(0, "private", "protected", "public", "paaa", "paab");
|
||||
}
|
||||
|
||||
public void testPreferElse() {
|
||||
checkPreferredItems(0, "else", "element");
|
||||
}
|
||||
|
||||
public void testPreferSamePackageOverImported() {
|
||||
myFixture.addClass("package bar; public class Bar1 {}");
|
||||
myFixture.addClass("package bar; public class Bar2 {}");
|
||||
|
||||
+2
@@ -514,6 +514,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testFieldWithCastingCaret() throws Throwable { doTest(); }
|
||||
|
||||
public void testInnerEnumConstant() throws Throwable { doTest('\n'); }
|
||||
|
||||
public void testMethodReturnType() throws Throwable {
|
||||
doTest();
|
||||
}
|
||||
|
||||
+15
-23
@@ -431,9 +431,15 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testPrivateOverloads() throws Throwable { doTest(); }
|
||||
|
||||
public void testCastAutoboxing() throws Throwable { doActionItemTest(); }
|
||||
public void testCastAutoboxing2() throws Throwable { doActionItemTest(); }
|
||||
public void testCastAutoboxing3() throws Throwable { doActionItemTest(); }
|
||||
public void testCastAutoboxing() throws Throwable {
|
||||
doItemTest();
|
||||
}
|
||||
public void testCastAutoboxing2() throws Throwable {
|
||||
doItemTest();
|
||||
}
|
||||
public void testCastAutoboxing3() throws Throwable {
|
||||
doItemTest();
|
||||
}
|
||||
public void testCastWildcards() throws Throwable { doTest(); }
|
||||
|
||||
public void testNoSecondMethodTypeArguments() throws Throwable { doTest(Lookup.REPLACE_SELECT_CHAR); }
|
||||
@@ -772,17 +778,17 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testClassLiteralInAnno2() throws Throwable {
|
||||
doActionItemTest();
|
||||
doItemTest();
|
||||
}
|
||||
|
||||
public void testClassLiteralInheritors() throws Throwable {
|
||||
doActionItemTest();
|
||||
doItemTest();
|
||||
}
|
||||
|
||||
public void testInsertOverride() throws Exception {
|
||||
CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(getProject());
|
||||
styleSettings.INSERT_OVERRIDE_ANNOTATION = true;
|
||||
doActionItemTest();
|
||||
doItemTest();
|
||||
}
|
||||
|
||||
public void testForeach() throws Exception {
|
||||
@@ -952,7 +958,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
public void testCastToParameterizedType() throws Throwable { doActionTest(); }
|
||||
|
||||
public void testInnerEnumInMethod() throws Throwable {
|
||||
doActionItemTest();
|
||||
doItemTest();
|
||||
}
|
||||
|
||||
public void testEnumAsDefaultAnnotationParam() throws Throwable { doTest(); }
|
||||
@@ -1023,27 +1029,13 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
doFirstItemTest('\t');
|
||||
}
|
||||
|
||||
private void doTest(boolean performAction, boolean selectItem) throws Exception {
|
||||
private void doActionTest() throws Exception {
|
||||
configureByTestName();
|
||||
if (performAction) {
|
||||
performAction();
|
||||
}
|
||||
if (selectItem) {
|
||||
selectItem(myFixture.getLookupElements()[0]);
|
||||
}
|
||||
checkResultByTestName();
|
||||
}
|
||||
|
||||
private void doActionTest() throws Exception {
|
||||
doTest(true, false);
|
||||
}
|
||||
|
||||
private void doItemTest() throws Exception {
|
||||
doTest(false, true);
|
||||
}
|
||||
|
||||
private void doActionItemTest() throws Exception {
|
||||
doTest(true, true);
|
||||
doFirstItemTest('\n');
|
||||
}
|
||||
|
||||
private void performAction() {
|
||||
|
||||
+23
@@ -330,6 +330,29 @@ public class JavaFormatterBlankLinesTest extends AbstractJavaFormatterTest {
|
||||
);
|
||||
}
|
||||
|
||||
public void testAfterAnonymousClassWhereCodeBlockStartsWithComment() throws Exception {
|
||||
// Inspired by IDEA-66583
|
||||
getSettings().BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER = 0;
|
||||
|
||||
String textWithWhiteSpaceBetweenCommentAndLbrace =
|
||||
"Object object = new Object() { // comment breaks \"blank line after anonymous class header\"\n" +
|
||||
" @Override\n" +
|
||||
" public String toString() {\n" +
|
||||
" return super.toString();\n" +
|
||||
" }\n" +
|
||||
"};";
|
||||
doMethodTest(textWithWhiteSpaceBetweenCommentAndLbrace, textWithWhiteSpaceBetweenCommentAndLbrace);
|
||||
|
||||
String textWithoutWhiteSpaceBetweenCommentAndLbrace =
|
||||
"Object object = new Object() {// comment breaks \"blank line after anonymous class header\"\n" +
|
||||
" @Override\n" +
|
||||
" public String toString() {\n" +
|
||||
" return super.toString();\n" +
|
||||
" }\n" +
|
||||
"};";
|
||||
doMethodTest(textWithoutWhiteSpaceBetweenCommentAndLbrace, textWithoutWhiteSpaceBetweenCommentAndLbrace);
|
||||
}
|
||||
|
||||
public void testBeforeMethodBody() {
|
||||
// Inspired by IDEA-54747
|
||||
getSettings().BLANK_LINES_BEFORE_METHOD_BODY = 3;
|
||||
|
||||
+35
-11
@@ -20,6 +20,8 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jdom.Content;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -33,11 +35,14 @@ import java.util.*;
|
||||
public class CommonCodeStyleSettingsManager implements JDOMExternalizable {
|
||||
|
||||
private Map<Language, CommonCodeStyleSettings> myCommonSettingsMap = null;
|
||||
private Map<String, Content> myUnknownSettingsMap;
|
||||
|
||||
private final CodeStyleSettings myParentSettings;
|
||||
|
||||
private static final String COMMON_SETTINGS_TAG = "codeStyleSettings";
|
||||
private static final String LANGUAGE_ATTR = "language";
|
||||
|
||||
|
||||
public CommonCodeStyleSettingsManager(CodeStyleSettings parentSettings) {
|
||||
myParentSettings = parentSettings;
|
||||
}
|
||||
@@ -101,6 +106,7 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable {
|
||||
|
||||
private void initCommonSettingsMap() {
|
||||
myCommonSettingsMap = new LinkedHashMap<Language, CommonCodeStyleSettings>();
|
||||
myUnknownSettingsMap = new LinkedHashMap<String, Content>();
|
||||
}
|
||||
|
||||
private void registerCommonSettings(@NotNull Language lang, @NotNull CommonCodeStyleSettings settings) {
|
||||
@@ -136,6 +142,8 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable {
|
||||
final CommonCodeStyleSettings settings = defaultSettings != null ? defaultSettings : new CommonCodeStyleSettings(target);
|
||||
settings.readExternal(commonSettingsElement);
|
||||
registerCommonSettings(target, settings);
|
||||
} else {
|
||||
myUnknownSettingsMap.put(languageId, (Content)commonSettingsElement.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,20 +155,36 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable {
|
||||
@Override
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
if (myCommonSettingsMap == null) return;
|
||||
final Language[] languages = myCommonSettingsMap.keySet().toArray(new Language[myCommonSettingsMap.keySet().size()]);
|
||||
Arrays.sort(languages, new Comparator<Language>() {
|
||||
public int compare(final Language o1, final Language o2) {
|
||||
return o1.getDisplayName().compareTo(o2.getDisplayName());
|
||||
|
||||
final Map<String, Language> id2lang = new HashMap<String, Language>();
|
||||
for (final Language language : myCommonSettingsMap.keySet()) {
|
||||
id2lang.put(language.getID(), language);
|
||||
}
|
||||
|
||||
final Set<String> langIdList = new HashSet<String>();
|
||||
langIdList.addAll(myUnknownSettingsMap.keySet());
|
||||
langIdList.addAll(id2lang.keySet());
|
||||
|
||||
final String[] languages = langIdList.toArray(new String[langIdList.size()]);
|
||||
Arrays.sort(languages, new Comparator<String>() {
|
||||
public int compare(final String o1, final String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
|
||||
for (Language language : languages) {
|
||||
final CommonCodeStyleSettings commonSettings = myCommonSettingsMap.get(language);
|
||||
Element commonSettingsElement = new Element(COMMON_SETTINGS_TAG);
|
||||
commonSettings.writeExternal(commonSettingsElement);
|
||||
commonSettingsElement.setAttribute(LANGUAGE_ATTR, language.getID());
|
||||
if (!commonSettingsElement.getChildren().isEmpty()) {
|
||||
element.addContent(commonSettingsElement);
|
||||
for (final String id : languages) {
|
||||
final Language language = id2lang.get(id);
|
||||
if (language != null) {
|
||||
final CommonCodeStyleSettings commonSettings = myCommonSettingsMap.get(language);
|
||||
Element commonSettingsElement = new Element(COMMON_SETTINGS_TAG);
|
||||
commonSettings.writeExternal(commonSettingsElement);
|
||||
commonSettingsElement.setAttribute(LANGUAGE_ATTR, language.getID());
|
||||
if (!commonSettingsElement.getChildren().isEmpty()) {
|
||||
element.addContent(commonSettingsElement);
|
||||
}
|
||||
} else {
|
||||
final Content unknown = myUnknownSettingsMap.get(id);
|
||||
if (unknown != null) element.addContent(unknown.detach());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-11
@@ -53,7 +53,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.psi.impl.PsiFileEx;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
@@ -297,15 +296,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
indicator.addItem(lookupElement);
|
||||
}
|
||||
};
|
||||
LookupElement[] result = CompletionService.getCompletionService().performCompletion(parameters, consumer);
|
||||
if (NameUtil.isUseMinusculeHumpMatcher() && parameters.getInvocationCount() == 0) {
|
||||
if (result.length == 0) {
|
||||
result = CompletionService.getCompletionService().performCompletion(parameters.withRelaxedMatching(), consumer);
|
||||
} else {
|
||||
indicator.restartOnEmpty = true;
|
||||
}
|
||||
}
|
||||
data.set(result);
|
||||
data.set(CompletionService.getCompletionService().performCompletion(parameters, consumer));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -357,7 +348,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
LOG.error("wrong text: copy='" + fileCopy.getText() + "'; element='" + insertedElement.getText() + "'; range=" + range);
|
||||
}
|
||||
|
||||
return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount, invocationCount >= 2);
|
||||
return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount, false);
|
||||
}
|
||||
|
||||
private AutoCompletionDecision shouldAutoComplete(
|
||||
|
||||
+6
-5
@@ -574,8 +574,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public boolean restartOnEmpty = false;
|
||||
|
||||
public void prefixUpdated() {
|
||||
final CharSequence text = myEditor.getDocument().getCharsSequence();
|
||||
final int caretOffset = myEditor.getCaretModel().getOffset();
|
||||
@@ -588,13 +586,16 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
if (hideAutopopupIfMeaningless() && restartOnEmpty) {
|
||||
CompletionAutoPopupHandler.scheduleAutoPopup(getProject(), myEditor, getParameters().getOriginalFile());
|
||||
}
|
||||
hideAutopopupIfMeaningless();
|
||||
updateFocus();
|
||||
}
|
||||
|
||||
public void scheduleRestart() {
|
||||
if (isAutopopupCompletion() && hideAutopopupIfMeaningless()) {
|
||||
CompletionAutoPopupHandler.scheduleAutoPopup(getProject(), myEditor, getParameters().getOriginalFile());
|
||||
return;
|
||||
}
|
||||
|
||||
cancel();
|
||||
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.lookup.LookupElement;
|
||||
import com.intellij.patterns.PatternCondition;
|
||||
import com.intellij.patterns.StandardPatterns;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class RelaxedMatchingContributor extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
final Set<LookupElement> elements = new HashSet<LookupElement>();
|
||||
result.runRemainingContributors(parameters, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
elements.add(element);
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
|
||||
if (!elements.isEmpty() && parameters.getInvocationCount() == 0) {
|
||||
Set<String> prefixes = new HashSet<String>();
|
||||
for (LookupElement element : elements) {
|
||||
prefixes.add(element.getPrefixMatcher().getPrefix());
|
||||
}
|
||||
for (String prefix : prefixes) {
|
||||
result.withPrefixMatcher(prefix)
|
||||
.restartCompletionOnPrefixChange(StandardPatterns.string().with(new PatternCondition<String>("noneMatch") {
|
||||
@Override
|
||||
public boolean accepts(@NotNull String s, ProcessingContext context) {
|
||||
for (LookupElement element : elements) {
|
||||
if (element.getPrefixMatcher().cloneWithPrefix(s).prefixMatches(element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
CompletionParameters relaxed;
|
||||
if (elements.isEmpty() && parameters.getInvocationCount() == 0) {
|
||||
relaxed = parameters.withRelaxedMatching();
|
||||
}
|
||||
else if (parameters.getInvocationCount() >= 2) {
|
||||
relaxed = parameters.withRelaxedMatching().withInvocationCount(parameters.getInvocationCount() - 1);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
result.runRemainingContributors(relaxed, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+28
-11
@@ -49,29 +49,46 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
ourLastCompletionCaseSetting = currentSetting;
|
||||
}
|
||||
|
||||
String key = myRelaxedMatching + myPrefix;
|
||||
NameUtil.Matcher pattern = ourPatternCache.get(key);
|
||||
if (pattern == null) {
|
||||
pattern = createCamelHumpsMatcher();
|
||||
ourPatternCache.put(key, pattern);
|
||||
}
|
||||
myMatcher = pattern;
|
||||
myMatcher = obtainMatcher(myRelaxedMatching);
|
||||
}
|
||||
return myMatcher.matches(name);
|
||||
if (myMatcher.matches(name)) {
|
||||
if (myRelaxedMatching && obtainMatcher(false).matches(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private NameUtil.Matcher obtainMatcher(final boolean relax) {
|
||||
String key = relax + myPrefix;
|
||||
NameUtil.Matcher pattern = ourPatternCache.get(key);
|
||||
if (pattern == null) {
|
||||
pattern = createCamelHumpsMatcher(relax);
|
||||
ourPatternCache.put(key, pattern);
|
||||
}
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
||||
public boolean prefixMatches(@NotNull final LookupElement element) {
|
||||
return prefixMatchersInternal(element, !element.isCaseSensitive());
|
||||
}
|
||||
|
||||
private boolean prefixMatchersInternal(final LookupElement element, final boolean itemCaseInsensitive) {
|
||||
if (itemCaseInsensitive && myRelaxedMatching) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (final String name : element.getAllLookupStrings()) {
|
||||
if (itemCaseInsensitive && StringUtil.startsWithIgnoreCase(name, myPrefix) || prefixMatches(name)) {
|
||||
return true;
|
||||
}
|
||||
if (itemCaseInsensitive && CodeInsightSettings.ALL != CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE && name.length() > 0) {
|
||||
if (itemCaseInsensitive &&
|
||||
CodeInsightSettings.ALL != CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE &&
|
||||
name.length() > 0) {
|
||||
final char c = name.charAt(0);
|
||||
String swappedCase = (Character.isUpperCase(c) ? Character.toLowerCase(c) : Character.toUpperCase(c)) + name.substring(1);
|
||||
if (prefixMatches(swappedCase)) {
|
||||
@@ -87,12 +104,12 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
return new CamelHumpMatcher(prefix, myCaseSensitive, myRelaxedMatching);
|
||||
}
|
||||
|
||||
private NameUtil.Matcher createCamelHumpsMatcher() {
|
||||
private NameUtil.Matcher createCamelHumpsMatcher(final boolean relaxedMatching) {
|
||||
if (!myCaseSensitive) {
|
||||
return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true);
|
||||
}
|
||||
|
||||
if (myRelaxedMatching) {
|
||||
if (relaxedMatching) {
|
||||
return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public class BackspaceHandler extends EditorActionHandler {
|
||||
lookup.performGuardedChange(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
handler.execute(editor, dataContext);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -207,6 +207,7 @@ public abstract class LookupActionHandler extends EditorActionHandler {
|
||||
lookup.performGuardedChange(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
editor.getCaretModel().moveToOffset(offset + 1);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -564,7 +564,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
|
||||
myDeferredTypes.add(contentType);
|
||||
|
||||
s = StringUtil.convertLineSeparators(s);
|
||||
s = StringUtil.convertLineSeparators(s, true);
|
||||
myContentSize += s.length();
|
||||
myDeferredOutputLength += s.length();
|
||||
StringBuilder bufferToUse;
|
||||
@@ -833,7 +833,13 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
myEditor.getScrollingModel().accumulateViewportChanges();
|
||||
}
|
||||
try {
|
||||
document.insertString(document.getTextLength(), text);
|
||||
String[] strings = text.split("\\r");
|
||||
for (int i = 0; i < strings.length - 1; i++) {
|
||||
document.insertString(document.getTextLength(), strings[i]);
|
||||
int lastLine = document.getLineCount() - 1;
|
||||
document.deleteString(document.getLineStartOffset(lastLine), document.getTextLength());
|
||||
}
|
||||
document.insertString(document.getTextLength(), strings[strings.length - 1]);
|
||||
}
|
||||
finally {
|
||||
if (preserveCurrentVisualArea) {
|
||||
|
||||
@@ -383,6 +383,7 @@
|
||||
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.LookupStringWeigher" id="sLookupString" order="after sGrouping"/>
|
||||
<weigher key="completionSorting" implementationClass="com.intellij.codeInsight.completion.LookupElementProximityWeigher" id="sProximity" order="after sLookupString"/>
|
||||
|
||||
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.RelaxedMatchingContributor" id="inexactMatching" order="first"/>
|
||||
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.DefaultCompletionContributor" id="default" order="last"/>
|
||||
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.ComboEditorCompletionContributor" id="comboEditor" order="first"/>
|
||||
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.WordCompletionContributor" id="wordCompletion" order="last"/>
|
||||
|
||||
@@ -254,7 +254,12 @@ public class StringUtil {
|
||||
*/
|
||||
@NotNull
|
||||
public static String convertLineSeparators(@NotNull String text) {
|
||||
return convertLineSeparators(text, "\n", null);
|
||||
return convertLineSeparators(text, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) {
|
||||
return convertLineSeparators(text, "\n", null, keepCarriageReturn);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -264,6 +269,13 @@ public class StringUtil {
|
||||
|
||||
@NotNull
|
||||
public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) {
|
||||
return convertLineSeparators(text, newSeparator, offsetsToKeep, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep,
|
||||
boolean keepCarriageReturn)
|
||||
{
|
||||
StringBuilder buffer = null;
|
||||
int intactLength = 0;
|
||||
final boolean newSeparatorIsSlashN = "\n".equals(newSeparator);
|
||||
@@ -286,12 +298,22 @@ public class StringUtil {
|
||||
}
|
||||
}
|
||||
else if (c == '\r') {
|
||||
boolean followedByLineFeed = i < text.length() - 1 && text.charAt(i + 1) == '\n';
|
||||
if (!followedByLineFeed && keepCarriageReturn) {
|
||||
if (buffer == null) {
|
||||
intactLength++;
|
||||
}
|
||||
else {
|
||||
buffer.append(c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (buffer == null) {
|
||||
buffer = new StringBuilder(text.length());
|
||||
buffer.append(text, 0, intactLength);
|
||||
}
|
||||
buffer.append(newSeparator);
|
||||
if (i < text.length() - 1 && text.charAt(i + 1) == '\n') {
|
||||
if (followedByLineFeed) {
|
||||
i++;
|
||||
shiftOffsets(offsetsToKeep, buffer.length(), 2, newSeparator.length());
|
||||
}
|
||||
|
||||
@@ -172,7 +172,20 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
|
||||
return myFileHistoryPanel;
|
||||
}
|
||||
|
||||
private FileHistoryPanelImpl resetHistoryPanel() {
|
||||
if (myFileHistoryPanel == null) {
|
||||
ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager();
|
||||
final VcsHistorySession copy = mySession.copyWithCachedRevision();
|
||||
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, copy, myVcsHistoryProvider,
|
||||
contentManager, myRefresher);
|
||||
} else {
|
||||
myFileHistoryPanel.getHistoryPanelRefresh().consume(mySession);
|
||||
}
|
||||
return myFileHistoryPanel;
|
||||
}
|
||||
|
||||
public void reportCreatedEmptySession(final VcsAbstractHistorySession session) {
|
||||
if (mySession != null && session != null && mySession.getRevisionList().equals(session.getRevisionList())) return;
|
||||
mySession = session;
|
||||
mySession.shouldBeRefreshed(); // to init current revision!
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@@ -180,7 +193,7 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
|
||||
String actionName = VcsBundle.message("action.name.file.history", myPath.getName());
|
||||
ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager();
|
||||
|
||||
myFileHistoryPanel = ensureHistoryPanelCreated();
|
||||
myFileHistoryPanel = resetHistoryPanel();
|
||||
Content content = ContentFactory.SERVICE.getInstance().createContent(myFileHistoryPanel, actionName, true);
|
||||
ContentsUtil.addOrReplaceContent(contentManager, content, true);
|
||||
|
||||
|
||||
@@ -563,6 +563,7 @@
|
||||
<action id="RenameJavaFileToGroovyFileAction"
|
||||
class="org.jetbrains.plugins.groovy.refactoring.javaToGrovyRename.RenameJavaFileToGroovyFileAction"
|
||||
text="Rename To Groovy" description="Rename Java File to Groovy">
|
||||
<add-to-group group-id="EditorTabPopupMenu" anchor="last"/>
|
||||
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
|
||||
</action>
|
||||
<action id="ExcludeFromStubGeneration"
|
||||
|
||||
+13
-2
@@ -235,8 +235,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (((GrReferenceElement)position.getParent()).getQualifier() != null) return;
|
||||
|
||||
final String s = result.getPrefixMatcher().getPrefix();
|
||||
if (StringUtil.isEmpty(s) || !Character.isLowerCase(s.charAt(0))) return;
|
||||
if (StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) return;
|
||||
|
||||
completeStaticMembers(position).processStaticMethodsGlobally(result);
|
||||
}
|
||||
@@ -493,6 +492,18 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
return new JavaGlobalMemberLookupElement(overloads, containingClass, QUALIFIED_METHOD_INSERT_HANDLER, STATIC_IMPORT_INSERT_HANDLER,
|
||||
shouldImport);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAccessible(PsiMember member) {
|
||||
boolean result = super.isAccessible(member);
|
||||
|
||||
if (!result && member instanceof GrField) {
|
||||
GrAccessorMethod[] getters = ((GrField)member).getGetters();
|
||||
return getters.length > 0 && super.isAccessible(getters[0]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
final PsiFile file = position.getContainingFile();
|
||||
if (file instanceof GroovyFile) {
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
public void testPossibleClosureParameter2() {
|
||||
myFixture.configureByText("a.gpp", "{ a, <caret> }")
|
||||
type 'h'
|
||||
assert !lookup
|
||||
assert !lookup.focused
|
||||
}
|
||||
|
||||
public void testImpossibleClosureParameter() {
|
||||
|
||||
+40
@@ -128,6 +128,46 @@ def foo() {
|
||||
|
||||
}
|
||||
|
||||
public void testImportedStaticField() throws Exception {
|
||||
myFixture.addFileToProject("b.groovy", """
|
||||
class Foo {
|
||||
static def abcfield1
|
||||
static def abcfield2
|
||||
}""")
|
||||
myFixture.configureByText("a.groovy", """def foo() {
|
||||
abcfi<caret>
|
||||
}""")
|
||||
def item = myFixture.complete(CompletionType.CLASS_NAME)[0]
|
||||
((StaticallyImportable) item).shouldBeImported = true
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult """import static Foo.abcfield1
|
||||
|
||||
def foo() {
|
||||
abcfield1<caret>
|
||||
}"""
|
||||
|
||||
}
|
||||
|
||||
public void testImportedInterfaceConstant() throws Exception {
|
||||
myFixture.addFileToProject("b.groovy", """
|
||||
interface Foo {
|
||||
static def abcfield1 = 2
|
||||
static def abcfield2 = 3
|
||||
}""")
|
||||
myFixture.configureByText("a.groovy", """def foo() {
|
||||
abcfi<caret>
|
||||
}""")
|
||||
def item = myFixture.complete(CompletionType.CLASS_NAME)[0]
|
||||
((StaticallyImportable) item).shouldBeImported = true
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult """import static Foo.abcfield1
|
||||
|
||||
def foo() {
|
||||
abcfield1<caret>
|
||||
}"""
|
||||
|
||||
}
|
||||
|
||||
public void testQualifiedStaticMethod() throws Exception {
|
||||
myFixture.addFileToProject("foo/b.groovy", """package foo
|
||||
class Foo {
|
||||
|
||||
@@ -30,7 +30,17 @@
|
||||
<testFramework implementation="com.intellij.execution.junit.JUnit3Framework"/>
|
||||
<testFramework implementation="com.intellij.execution.junit.JUnit4Framework"/>
|
||||
<configurationType implementation="com.intellij.execution.junit.JUnitConfigurationType"/>
|
||||
|
||||
<stacktrace.fold substring="at org.junit.internal.runners."/>
|
||||
<stacktrace.fold substring="at org.junit.runners."/>
|
||||
<stacktrace.fold substring="at org.junit.runner.JUnitCore."/>
|
||||
<stacktrace.fold substring="at org.junit.Assert.fail("/>
|
||||
<stacktrace.fold substring="at org.junit.Assert.failNotSame("/>
|
||||
<stacktrace.fold substring="at org.junit.Assert.failSame("/>
|
||||
<stacktrace.fold substring="at org.junit.Assert.internalArrayEquals("/>
|
||||
<stacktrace.fold substring="at org.junit.internal.ComparisonCriteria.arrayEquals("/>
|
||||
<stacktrace.fold substring="at org.junit.Assert.assert"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
|
||||
+2
-3
@@ -424,10 +424,9 @@ public class TestNGConfigurationEditor extends SettingsEditor<TestNGConfiguratio
|
||||
|
||||
@Nullable
|
||||
protected String selectListenerClass() {
|
||||
final GlobalSearchScope searchScope = getSearchScope(config.getModules());
|
||||
GlobalSearchScope searchScope = getSearchScope(config.getModules());
|
||||
if (searchScope == null) {
|
||||
Messages.showErrorDialog(panel, "Module is not selected", "Can't Browse Listeners");
|
||||
return null;
|
||||
searchScope = GlobalSearchScope.allScope(project);
|
||||
}
|
||||
final TestListenerFilter filter = new TestListenerFilter(searchScope, project);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user