java: consider deepest qualifier for auto-import on completion (IDEA-230624)

GitOrigin-RevId: 8cb006428a6f92a929b6d916fbea26a95d293a0e
This commit is contained in:
Peter Gromov
2020-01-16 08:11:51 +00:00
committed by intellij-monorepo-bot
parent 93275ffa82
commit 6bbd84e9cb
7 changed files with 55 additions and 19 deletions
@@ -81,9 +81,7 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
context.setAddCompletionChar(false);
}
if (ref == null || !ref.isQualified()) {
PsiTypeLookupItem.addImportForItem(context, psiClass);
}
PsiTypeLookupItem.addImportForItem(context, psiClass);
if (!context.getOffsetMap().containsOffset(refEnd)) {
return;
}
@@ -8,11 +8,12 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtilRt;
import org.jetbrains.annotations.NonNls;
@@ -302,7 +303,23 @@ public class PsiTypeLookupItem extends LookupItem implements TypedLookupItem {
int startOffset = context.getStartOffset();
int tail = context.getTailOffset();
int newTail = JavaCompletionUtil.insertClassReference(aClass, file, startOffset, tail);
PsiJavaCodeReferenceElement ref =
PsiTreeUtil.findElementOfClassAtOffset(file, tail - 1, PsiJavaCodeReferenceElement.class, false);
boolean goneDeeper = false;
while (ref != null) {
PsiElement qualifier = ref.getQualifier();
PsiClass outer = aClass.getContainingClass();
if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !Comparing.equal(aClass.getName(), ref.getReferenceName()) || outer == null) break;
goneDeeper = true;
ref = (PsiJavaCodeReferenceElement)qualifier;
aClass = outer;
}
int newTail = JavaCompletionUtil.insertClassReference(aClass, file,
goneDeeper ? ref.getTextRange().getStartOffset() : startOffset,
goneDeeper ? ref.getTextRange().getEndOffset() : tail);
if (newTail > context.getDocument().getTextLength() || newTail < 0) {
LOG.error("Invalid offset after insertion\n" +
"offset=" + newTail + "\n" +
@@ -315,8 +332,8 @@ public class PsiTypeLookupItem extends LookupItem implements TypedLookupItem {
return;
}
context.setTailOffset(newTail);
JavaCompletionUtil.shortenReference(file, context.getStartOffset());
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
if (!goneDeeper) {
context.setTailOffset(newTail);
}
}
}
@@ -11,10 +11,7 @@ import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.DummyHolderFactory;
import com.intellij.psi.impl.source.JavaDummyElement;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.*;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.javadoc.PsiDocComment;
@@ -22,6 +19,7 @@ import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -250,6 +248,12 @@ public class PsiJavaParserFacadeImpl implements PsiJavaParserFacade {
if (!(element instanceof PsiJavaCodeReferenceElement)) {
throw newException("Incorrect reference '" + text + "'", holder);
}
if (context instanceof PsiIdentifier) {
context = context.getParent();
}
if (element instanceof PsiJavaCodeReferenceElementImpl && context instanceof PsiJavaCodeReferenceElementImpl) {
((PsiJavaCodeReferenceElementImpl)element).setKindWhenDummy(((PsiJavaCodeReferenceElementImpl)context).getKindEnum(context.getContainingFile()));
}
return (PsiJavaCodeReferenceElement)element;
}
@@ -369,7 +373,7 @@ public class PsiJavaParserFacadeImpl implements PsiJavaParserFacade {
return context != null && context.isValid() ? PsiUtil.getLanguageLevel(context) : LanguageLevel.HIGHEST;
}
private static IncorrectOperationException newException(String msg, DummyHolder holder) {
private static IncorrectOperationException newException(@NonNls String msg, DummyHolder holder) {
FileElement root = holder.getTreeElement();
if (root instanceof JavaDummyElement) {
Throwable cause = ((JavaDummyElement)root).getParserError();
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.source.resolve;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,12 +28,9 @@ public class ResolveClassUtil {
public static PsiClass resolveClass(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiFile containingFile) {
if (ref instanceof PsiJavaCodeReferenceElementImpl &&
((PsiJavaCodeReferenceElementImpl)ref).getKindEnum(containingFile) == PsiJavaCodeReferenceElementImpl.Kind.CLASS_IN_QUALIFIED_NEW_KIND) {
PsiElement parent = ref.getParent();
if (parent instanceof PsiAnonymousClass) {
parent = parent.getParent();
}
if (parent instanceof PsiNewExpression) {
PsiExpression qualifier = ((PsiNewExpression)parent).getQualifier();
PsiNewExpression parent = PsiTreeUtil.getContextOfType(ref, PsiNewExpression.class);
if (parent != null) {
PsiExpression qualifier = parent.getQualifier();
if (qualifier != null) {
PsiType qualifierType = qualifier.getType();
if (qualifierType instanceof PsiClassType) {
@@ -0,0 +1,5 @@
class C {
{
new Oute<caret>
}
}
@@ -0,0 +1,7 @@
import p.Outer;
class C {
{
new Outer.Inner()<caret>
}
}
@@ -1958,4 +1958,11 @@ class Abc {
myFixture.completeBasic()
myFixture.checkResult("enum X ex")
}
void testAddImportWhenCompletingInnerAfterNew() {
myFixture.addClass("package p; public class Outer { public static class Inner {} }")
configureByTestName()
selectItem(myItems.find { it.lookupString.contains('Inner') })
checkResult()
}
}