IDEA-120855 Auto-complete should indicate that suggested variants are not compatible with the module language level

This commit is contained in:
peter
2014-11-05 13:32:33 +01:00
parent e7af4d6e06
commit 8df23a549a
7 changed files with 85 additions and 16 deletions
@@ -355,29 +355,31 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
}
@Nullable
public static String getSignature(PsiMember member) {
private static String getSignature(@Nullable PsiMember member) {
if (member instanceof PsiClass) {
return ((PsiClass)member).getQualifiedName();
}
if (member instanceof PsiField) {
return getSignature(member.getContainingClass()) + "#" + member.getName();
String containingClass = getSignature(member.getContainingClass());
return containingClass == null ? null : containingClass + "#" + member.getName();
}
if (member instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)member;
String containingClass = getSignature(member.getContainingClass());
if (containingClass == null) return null;
StringBuilder buf = new StringBuilder();
buf.append(getSignature(method.getContainingClass()));
buf.append(containingClass);
buf.append('#');
buf.append(method.getName());
buf.append('(');
final PsiType[] params = method.getSignature(PsiSubstitutor.EMPTY).getParameterTypes();
for (PsiType type : params) {
for (PsiType type : method.getSignature(PsiSubstitutor.EMPTY).getParameterTypes()) {
buf.append(type.getCanonicalText());
buf.append(";");
}
buf.append(')');
return buf.toString();
}
assert false;
return null;
}
}
@@ -134,6 +134,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
});
}
static LookupElement highlightIfNeeded(JavaPsiClassReferenceElement element, CompletionParameters parameters) {
return JavaCompletionUtil.highlightIfNeeded(null, element, element.getObject(), parameters.getPosition());
}
public static JavaPsiClassReferenceElement createClassLookupItem(final PsiClass psiClass, final boolean inJavaContext) {
return AllClassesGetter.createLookupItem(psiClass, inJavaContext ? JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER
: AllClassesGetter.TRY_SHORTENING);
@@ -264,7 +264,7 @@ public class JavaCompletionContributor extends CompletionContributor {
return PsiUtilCore.findLanguageFromElement(position).isKindOf(JavaLanguage.INSTANCE);
}
public static void addAllClasses(CompletionParameters parameters,
public static void addAllClasses(final CompletionParameters parameters,
final CompletionResultSet result,
final InheritorsHolder inheritors) {
if (!isClassNamePossible(parameters) || !mayStartClassName(result)) {
@@ -276,7 +276,7 @@ public class JavaCompletionContributor extends CompletionContributor {
@Override
public void consume(LookupElement element) {
if (!inheritors.alreadyProcessed(element)) {
result.addElement(element);
result.addElement(JavaClassNameCompletionContributor.highlightIfNeeded((JavaPsiClassReferenceElement)element, parameters));
}
}
});
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.guess.GuessManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInspection.java15api.Java15APIUsageInspectionBase;
import com.intellij.lang.StdLanguages;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
@@ -50,6 +51,7 @@ import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.ui.JBColor;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NullableFunction;
import com.intellij.util.PairConsumer;
@@ -60,7 +62,9 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.*;
import java.util.List;
import static com.intellij.patterns.PlatformPatterns.psiElement;
@@ -383,7 +387,7 @@ public class JavaCompletionUtil {
}
mentioned.add(CompletionUtil.getOriginalOrSelf((PsiMember)o));
}
set.add(highlightIfNeeded(qualifierType, castQualifier(item, castItem, plainQualifier, processor), o));
set.add(highlightIfNeeded(qualifierType, castQualifier(item, castItem, plainQualifier, processor), o, element));
}
}
@@ -503,11 +507,37 @@ public class JavaCompletionUtil {
return type instanceof PsiClassType ? ((PsiClassType)type).rawType() : type;
}
public static LookupElement highlightIfNeeded(PsiType qualifierType, LookupElement item, Object object) {
return containsMember(qualifierType, object) ? highlight(item) : item;
@NotNull
public static LookupElement highlightIfNeeded(@Nullable PsiType qualifierType,
@NotNull LookupElement item,
@NotNull Object object,
@NotNull PsiElement place) {
final boolean bold = containsMember(qualifierType, object);
boolean red = false;
if (object instanceof PsiMember) {
red = Java15APIUsageInspectionBase.isForbiddenApiUsage((PsiMember)object, PsiUtil.getLanguageLevel(place));
}
LookupElement result = item;
if (bold || red) {
final Color fg = red ? JBColor.RED : null;
result = LookupElementDecorator.withRenderer(result, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
element.getDelegate().renderElement(presentation);
presentation.setItemTextBold(bold);
if (fg != null) {
presentation.setItemTextForeground(fg);
}
}
});
}
if (bold) {
result = PrioritizedLookupElement.withExplicitProximity(result, 1);
}
return result;
}
public static boolean containsMember(PsiType qualifierType, Object object) {
public static boolean containsMember(@Nullable PsiType qualifierType, @NotNull Object object) {
if (qualifierType instanceof PsiArrayType && object instanceof PsiMember) { //length and clone()
PsiFile file = ((PsiMember)object).getContainingFile();
if (file == null || file.getVirtualFile() == null) { //yes, they're a bit dummy
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.completion.impl.BetterPrefixMatcher;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -145,7 +144,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
if (ref != null) {
for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters,
result.getPrefixMatcher())) {
qualifiedCollector.addElement(new JavaChainLookupElement(base, item));
qualifiedCollector.addElement(JavaCompletionUtil.highlightIfNeeded(null, new JavaChainLookupElement(base, item), item.getObject(), position));
}
}
}
@@ -178,7 +177,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
return allClasses;
}
private static void suggestNonImportedClasses(CompletionParameters parameters, final CompletionResultSet result, @Nullable final InheritorsHolder inheritorsHolder) {
private static void suggestNonImportedClasses(final CompletionParameters parameters, final CompletionResultSet result, @Nullable final InheritorsHolder inheritorsHolder) {
JavaClassNameCompletionContributor.addAllClasses(parameters,
true, result.getPrefixMatcher(), new Consumer<LookupElement>() {
@Override
@@ -189,6 +188,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
if (classElement != null) {
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
element = JavaClassNameCompletionContributor.highlightIfNeeded(classElement, parameters);
}
result.addElement(element);
@@ -6,6 +6,7 @@ package com.intellij.codeInsight.completion
import com.intellij.JavaTestUtil
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.openapi.application.ApplicationManager
@@ -18,14 +19,17 @@ import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.SourceFolder
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.ui.JBColor
import org.jetbrains.annotations.NotNull
/**
@@ -171,4 +175,33 @@ public class Test {
assert oldCount == tracker.javaStructureModificationCount
}
public void testForbiddenApiVariants() {
IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_4)
myFixture.addClass("""\
package java.nio.channels;
public class SocketChannel {
public SocketChannel shutdownInput() {}
public boolean isConnected();
}""")
myFixture.addClass("package java.nio.channels; public class AsynchronousServerSocketChannel { }")
myFixture.configureByText 'a.java', 'class Foo {{ new SocketChanne<caret>x }}'
myFixture.completeBasic()
def p = LookupElementPresentation.renderElement(myFixture.lookup.items[0])
assert p.itemText == 'SocketChannel'
assert p.itemTextForeground == JBColor.foreground()
p = LookupElementPresentation.renderElement(myFixture.lookup.items.find { it.lookupString == 'AsynchronousServerSocketChannel' })
assert p.itemTextForeground == JBColor.RED
myFixture.type('\n.s')
myFixture.completeBasic()
p = LookupElementPresentation.renderElement(myFixture.lookup.items[0])
assert p.itemText == 'shutdownInput'
assert p.itemTextForeground == JBColor.RED
p = LookupElementPresentation.renderElement(myFixture.lookup.items.find { it.lookupString == 'isConnected' })
assert p.itemTextForeground == JBColor.foreground()
}
}
@@ -252,7 +252,7 @@ public class GrMainCompletionProvider extends CompletionProvider<CompletionParam
if (!(object instanceof PsiClass)) {
int priority = assignPriority(lookupElement, qualifierType);
lookupElement = JavaCompletionUtil.highlightIfNeeded(qualifierType,
PrioritizedLookupElement.withPriority(lookupElement, priority), object);
PrioritizedLookupElement.withPriority(lookupElement, priority), object, reference);
}
if ((object instanceof PsiMethod || object instanceof PsiField) &&