IDEA-191883 "Tab" completion doesn't work as expected for inner classes

This commit is contained in:
peter
2018-05-16 18:35:13 +02:00
parent 3679c2a3a4
commit 987368ccfd
7 changed files with 45 additions and 25 deletions
@@ -16,7 +16,6 @@ import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
@@ -50,8 +49,6 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.ConstructorInsertHandler");
public static final ConstructorInsertHandler SMART_INSTANCE = new ConstructorInsertHandler(true);
public static final ConstructorInsertHandler BASIC_INSTANCE = new ConstructorInsertHandler(false);
static final OffsetKey PARAM_LIST_START = OffsetKey.create("paramListStart");
static final OffsetKey PARAM_LIST_END = OffsetKey.create("paramListEnd");
private final boolean mySmart;
private ConstructorInsertHandler(boolean smart) {
@@ -66,12 +63,8 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
boolean isAbstract = psiClass.hasModifierProperty(PsiModifier.ABSTRACT);
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar() && context.getOffsetMap().containsOffset(PARAM_LIST_START)) {
final int plStart = context.getOffset(PARAM_LIST_START);
final int plEnd = context.getOffset(PARAM_LIST_END);
if (plStart >= 0 && plEnd >= 0) {
context.getDocument().deleteString(plStart, plEnd);
}
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar()) {
JavaClassNameInsertHandler.overwriteTopmostReference(context);
}
context.commitDocument();
@@ -87,7 +80,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
if (delegate instanceof PsiTypeLookupItem) {
if (context.getDocument().getTextLength() > context.getTailOffset() &&
context.getDocument().getCharsSequence().charAt(context.getTailOffset()) == '<') {
PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset(), PsiJavaCodeReferenceElement.class, false);
PsiJavaCodeReferenceElement ref = JavaClassNameInsertHandler.findJavaReference(context.getFile(), context.getTailOffset());
if (ref != null) {
PsiReferenceParameterList parameterList = ref.getParameterList();
if (parameterList != null && context.getTailOffset() == parameterList.getTextRange().getStartOffset()) {
@@ -47,8 +47,8 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
int offset = context.getTailOffset() - 1;
final PsiFile file = context.getFile();
if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatementBase.class, false) != null) {
final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiJavaCodeReferenceElement.class, false);
final String qname = item.getQualifiedName();
PsiJavaCodeReferenceElement ref = findJavaReference(file, offset);
String qname = item.getQualifiedName();
if (qname != null && (ref == null || !qname.equals(ref.getCanonicalText()))) {
AllClassesGetter.INSERT_FQN.handleInsert(context, item);
}
@@ -72,7 +72,7 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
String qname = psiClass.getQualifiedName();
if (qname != null && PsiTreeUtil.getParentOfType(position, PsiDocComment.class, false) != null &&
(ref == null || !ref.isQualified()) &&
shouldInsertFqnInJavadoc(item, file, project)) {
shouldInsertFqnInJavadoc(item, file)) {
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), qname);
return;
}
@@ -101,6 +101,10 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
context.commitDocument();
if (item.getUserData(JavaChainLookupElement.CHAIN_QUALIFIER) == null &&
shouldInsertParentheses(file.findElementAt(context.getTailOffset() - 1))) {
if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
overwriteTopmostReference(context);
context.commitDocument();
}
if (ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) {
fillTypeArgs |= psiClass.hasTypeParameters() && PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_5);
}
@@ -123,10 +127,20 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
}
}
private static boolean shouldInsertFqnInJavadoc(@NotNull JavaPsiClassReferenceElement item,
@NotNull PsiFile file,
@NotNull Project project)
{
static PsiJavaCodeReferenceElement findJavaReference(PsiFile file, int offset) {
return PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiJavaCodeReferenceElement.class, false);
}
static void overwriteTopmostReference(InsertionContext context) {
context.commitDocument();
PsiJavaCodeReferenceElement ref = findJavaReference(context.getFile(), context.getTailOffset());
if (ref != null) {
while (ref.getParent() instanceof PsiJavaCodeReferenceElement) ref = (PsiJavaCodeReferenceElement)ref.getParent();
context.getDocument().deleteString(context.getTailOffset(), ref.getTextRange().getEndOffset());
}
}
private static boolean shouldInsertFqnInJavadoc(@NotNull JavaPsiClassReferenceElement item, @NotNull PsiFile file) {
JavaCodeStyleSettings javaSettings = getInstance(file);
switch (javaSettings.CLASS_NAMES_IN_JAVADOC) {
@@ -792,14 +792,6 @@ public class JavaCompletionContributor extends CompletionContributor {
PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
if (ref != null && !(ref instanceof PsiReferenceExpression)) {
if (JavaSmartCompletionContributor.AFTER_NEW.accepts(ref)) {
final PsiReferenceParameterList paramList = ref.getParameterList();
if (paramList != null && paramList.getTextLength() > 0) {
context.getOffsetMap().addOffset(ConstructorInsertHandler.PARAM_LIST_START, paramList.getTextRange().getStartOffset());
context.getOffsetMap().addOffset(ConstructorInsertHandler.PARAM_LIST_END, paramList.getTextRange().getEndOffset());
}
}
return;
}
@@ -54,6 +54,8 @@ public class JavaCompletionSession {
}
public void addClassItem(LookupElement lookupElement) {
if (!myResult.getPrefixMatcher().prefixMatches(lookupElement)) return;
PsiClass psiClass = extractClass(lookupElement);
if (psiClass != null) {
registerClass(psiClass);
@@ -0,0 +1,6 @@
class Scratch {
interface Some {}
public static class Inner implements Some {}
Some f = new Scratc<caret>h.z();
}
@@ -0,0 +1,6 @@
class Scratch {
interface Some {}
public static class Inner implements Some {}
Some f = new Scratch.Inner()<caret>;
}
@@ -1852,4 +1852,11 @@ class Bar {{
void testSuggestGetInstanceMethodName() { doTest() }
void testTabOnNewInnerClass() {
configureByTestName()
lookup.currentItem = myFixture.lookupElements.find { it.lookupString.contains('Inner') }
myFixture.type('\t')
checkResult()
}
}