IDEA-79246 IDEA completion suggest raw type for element of array of typed class

This commit is contained in:
peter
2011-12-23 18:28:40 +01:00
parent 5f322bf5e6
commit b35e73487a
8 changed files with 78 additions and 21 deletions
@@ -1,5 +1,7 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiGenerationInfo;
@@ -68,7 +70,9 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
boolean fillTypeArgs = false;
if (delegate instanceof PsiTypeLookupItem) {
fillTypeArgs = psiClass.getTypeParameters().length > 0 && ((PsiTypeLookupItem)delegate).calcGenerics().isEmpty();
fillTypeArgs = !isRawTypeExpected(context, (PsiTypeLookupItem)delegate) &&
psiClass.getTypeParameters().length > 0 &&
((PsiTypeLookupItem)delegate).calcGenerics(position).isEmpty();
delegate.handleInsert(context);
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider());
}
@@ -95,12 +99,7 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
editor.getDocument().insertString(offset, " {}");
editor.getCaretModel().moveToOffset(offset + 2);
if (fillTypeArgs) {
int refEnd = context.getOffset(insideRef);
context.getDocument().insertString(refEnd, "<>");
editor.getCaretModel().moveToOffset(refEnd + 1);
return;
}
if (fillTypeArgs && promptTypeArgs(context, context.getOffset(insideRef))) return;
context.setLaterRunnable(generateAnonymousBody(editor, context.getFile()));
}
@@ -117,9 +116,43 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
if (fillTypeArgs && promptTypeArgs(context, context.getOffset(insideRef))) return;
}
}
static boolean isRawTypeExpected(InsertionContext context, PsiTypeLookupItem delegate) {
PsiNewExpression newExpr =
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiNewExpression.class, false);
if (newExpr != null) {
for (ExpectedTypeInfo info : ExpectedTypesProvider.getExpectedTypes(newExpr, true)) {
PsiType expected = info.getDefaultType();
if (expected.isAssignableFrom(delegate.getPsiType())) {
if (expected instanceof PsiClassType && ((PsiClassType)expected).isRaw()) {
return true;
}
}
}
}
return false;
}
static boolean promptTypeArgs(InsertionContext context, int offset) {
if (offset < 0) {
return false;
}
OffsetKey key = context.trackOffset(offset, false);
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
offset = context.getOffset(key);
if (offset < 0) {
return false;
}
context.getDocument().insertString(offset, "<>");
context.getEditor().getCaretModel().moveToOffset(offset + 1);
return true;
}
public static boolean insertParentheses(InsertionContext context,
LookupItem delegate,
final PsiClass psiClass,
@@ -30,7 +30,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.filters.FilterPositionUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
@@ -127,12 +126,7 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
}
if (fillTypeArgs) {
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
int typeArgs = context.getOffset(refEnd);
if (typeArgs >= 0) {
context.getDocument().insertString(typeArgs, "<>");
context.getEditor().getCaretModel().moveToOffset(typeArgs + 1);
}
ConstructorInsertHandler.promptTypeArgs(context, context.getOffset(refEnd));
}
}
@@ -15,10 +15,7 @@
*/
package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.DefaultInsertHandler;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement;
import com.intellij.codeInsight.completion.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.util.ClassConditionKey;
@@ -74,7 +71,9 @@ public class PsiTypeLookupItem extends LookupItem {
@Override
public void handleInsert(InsertionContext context) {
context.getDocument().insertString(context.getTailOffset(), calcGenerics());
PsiElement position = context.getFile().findElementAt(context.getStartOffset());
assert position != null;
context.getDocument().insertString(context.getTailOffset(), calcGenerics(position));
DefaultInsertHandler.addImportForItem(context, this);
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
@@ -99,18 +98,21 @@ public class PsiTypeLookupItem extends LookupItem {
}
}
public String calcGenerics() {
public String calcGenerics(@NotNull PsiElement context) {
if (myDiamond) {
return "<>";
}
if (getObject() instanceof PsiClass) {
PsiClass psiClass = (PsiClass)getObject();
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper();
PsiSubstitutor substitutor = getSubstitutor();
StringBuilder builder = new StringBuilder();
for (PsiTypeParameter parameter : psiClass.getTypeParameters()) {
PsiType substitute = substitutor.substitute(parameter);
if (substitute == null || PsiUtil.resolveClassInType(substitute) == parameter) {
if (substitute == null ||
(PsiUtil.resolveClassInType(substitute) == parameter &&
resolveHelper.resolveReferencedClass(parameter.getName(), context) != CompletionUtil.getOriginalOrSelf(parameter))) {
return "";
}
if (builder.length() > 0) {
@@ -0,0 +1,5 @@
class Bar<T> {
{
Bar<T> f = new Bar<T>();<caret>
}
}
@@ -0,0 +1,5 @@
class Bar<T> {
{
Bar<T> f = new <caret>
}
}
@@ -0,0 +1,8 @@
interface Foo {}
class FooEx<T> implements Foo {}
class Bar {
{
Foo f = new FooEx<<caret>>();
}
}
@@ -0,0 +1,8 @@
interface Foo {}
class FooEx<T> implements Foo {}
class Bar {
{
Foo f = new FE<caret>
}
}
@@ -895,6 +895,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testIfConditionExpectedType() throws Exception { doTest(); }
public void testUnboundTypeArgs() throws Exception { doTest(); }
public void testUnboundTypeArgs2() throws Exception { doTest(); }
public void testSameTypeArg() throws Exception { doTest(); }
public void testIDEADEV2668() throws Exception {
doTest();