IDEA-128948 Smart type completion should propose generic parameter type

This commit is contained in:
peter
2014-08-26 14:32:23 +02:00
parent 6564528108
commit 53e2c49b27
7 changed files with 57 additions and 12 deletions
@@ -16,6 +16,7 @@
package com.intellij.codeInsight;
import com.intellij.codeInsight.completion.AllClassesGetter;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.lang.Language;
@@ -33,21 +34,21 @@ import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.*;
import com.intellij.psi.util.proximity.PsiProximityComparator;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.Consumer;
import com.intellij.util.FilteredQuery;
import com.intellij.util.Processor;
import com.intellij.util.Query;
import com.intellij.psi.util.FileTypeUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
public class CodeInsightUtil {
@Nullable
@@ -283,6 +284,11 @@ public class CodeInsightUtil {
final Processor<PsiClass> inheritorsProcessor =
createInheritorsProcessor(context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor);
addContextTypeArguments(context, baseType, inheritorsProcessor);
if (baseClass.hasModifierProperty(PsiModifier.FINAL)) return;
if (matcher.getPrefix().length() > 2) {
AllClassesGetter.processJavaClasses(matcher, context.getProject(), scope, new Processor<PsiClass>() {
@Override
@@ -307,6 +313,30 @@ public class CodeInsightUtil {
}
private static void addContextTypeArguments(final PsiElement context,
final PsiClassType baseType,
final Processor<PsiClass> inheritorsProcessor) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
Set<String> usedNames = ContainerUtil.newHashSet();
PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject());
PsiElement each = context;
while (true) {
PsiTypeParameterListOwner typed = PsiTreeUtil.getParentOfType(each, PsiTypeParameterListOwner.class);
if (typed == null) break;
for (PsiTypeParameter parameter : typed.getTypeParameters()) {
if (baseType.isAssignableFrom(factory.createType(parameter)) && usedNames.add(parameter.getName())) {
inheritorsProcessor.process(CompletionUtil.getOriginalOrSelf(parameter));
}
}
each = typed;
}
}
});
}
public static Processor<PsiClass> createInheritorsProcessor(final PsiElement context, final PsiClassType baseType,
final int arrayDim,
final boolean getRawSubtypes,
@@ -278,10 +278,12 @@ public class JavaCompletionSorting {
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement item) {
public MyResult weigh(@NotNull LookupElement item) {
final Object object = item.getObject();
if (object instanceof PsiClass) {
if (object instanceof PsiTypeParameter) return MyResult.typeParameter;
if (myTypeParameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(myTypeParameter)))) {
return MyResult.exactlyExpected;
}
@@ -340,6 +342,7 @@ public class JavaCompletionSorting {
private enum MyResult {
expectedNoSelect,
typeParameter,
exactlyDefault,
ofDefaultType,
exactlyExpected,
@@ -229,10 +229,7 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
//long
for (final PsiClassType type : expectedClassTypes) {
final PsiClass psiClass = type.resolve();
if (psiClass != null && !psiClass.hasModifierProperty(PsiModifier.FINAL)) {
CodeInsightUtil.processSubTypes(type, parameters.getPosition(), false, matcher, consumer);
}
CodeInsightUtil.processSubTypes(type, parameters.getPosition(), false, matcher, consumer);
}
}
@@ -158,8 +158,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
@Override
public void consume(PsiType type) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass == null) return;
if (psiClass == null || psiClass instanceof PsiTypeParameter) return;
//noinspection SuspiciousMethodCalls
if (expectedClassTypes.contains(type)) return;
result.addElement(createInstanceofLookupElement(psiClass, parameterizedTypes));
@@ -307,3 +307,4 @@ public interface JVMElementFactory {
*/
boolean isValidLocalVariableName(@NotNull String name);
}
@@ -0,0 +1,8 @@
class StringEx<T extends String> {
}
class Outer<T extends String> {
static class CompletionTest<T extends String> {
private StringEx<<caret>> myString;
}
}
@@ -777,6 +777,11 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
myFixture.assertPreferredCompletionItems(0, "i", "z", "zz", "i, z, zz");
}
public void testSuggestTypeParametersInTypeArgumentList() {
configureByTestName();
myFixture.assertPreferredCompletionItems(0, "T", "String");
}
public void testWrongAnonymous() throws Throwable {
configureByTestName();
select();