mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-50677 Groovy 1.7: Smart Code Completion for anonymous interface implementation expression could be added
This commit is contained in:
+13
-4
@@ -27,6 +27,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -35,7 +36,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<LookupItem>> {
|
||||
public class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<LookupItem>> {
|
||||
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);
|
||||
@@ -169,6 +170,7 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
|
||||
return hasParams;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Runnable generateAnonymousBody(final Editor editor, final PsiFile file) {
|
||||
final Project project = file.getProject();
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
@@ -180,13 +182,20 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
|
||||
PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiAnonymousClass)) return null;
|
||||
|
||||
try{
|
||||
return genAnonymousBodyFor((PsiAnonymousClass)parent, editor, file, project);
|
||||
}
|
||||
|
||||
public static Runnable genAnonymousBodyFor(PsiAnonymousClass parent,
|
||||
final Editor editor,
|
||||
final PsiFile file,
|
||||
final Project project) {
|
||||
try {
|
||||
CodeStyleManager.getInstance(project).reformat(parent);
|
||||
}
|
||||
catch(IncorrectOperationException e){
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
offset = parent.getTextRange().getEndOffset() - 1;
|
||||
int offset = parent.getTextRange().getEndOffset() - 1;
|
||||
editor.getCaretModel().moveToOffset(offset);
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
editor.getSelectionModel().removeSelection();
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.intellij.codeInsight.generation;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
@@ -109,7 +109,7 @@ public class GenerateMembersUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends GenerationInfo> List<T> insertMembersBeforeAnchor(PsiClass aClass, PsiElement anchor, @NotNull List<T> memberPrototypes) throws IncorrectOperationException {
|
||||
public static <T extends GenerationInfo> List<T> insertMembersBeforeAnchor(PsiClass aClass, @Nullable PsiElement anchor, @NotNull List<T> memberPrototypes) throws IncorrectOperationException {
|
||||
boolean before = true;
|
||||
for (T memberPrototype : memberPrototypes) {
|
||||
memberPrototype.insert(aClass, anchor, before);
|
||||
@@ -280,7 +280,7 @@ public class GenerateMembersUtil {
|
||||
if (paramName == null) paramName = "p" + i;
|
||||
|
||||
PsiParameter newParameter = factory.createParameter(paramName, substituted);
|
||||
if (parameter.getLanguage() == StdLanguages.JAVA) {
|
||||
if (parameter.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
PsiModifierList modifierList = newParameter.getModifierList();
|
||||
modifierList = (PsiModifierList)modifierList.replace(parameter.getModifierList());
|
||||
processAnnotations(project, modifierList);
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
|
||||
final PsiClass psiClass = com.intellij.psi.util.PsiUtil.resolveClassInType(type);
|
||||
if (psiClass == null) return null;
|
||||
|
||||
if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return null;
|
||||
//if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return null;
|
||||
if (!checkForInnerClass(psiClass, place)) return null;
|
||||
|
||||
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), place);
|
||||
|
||||
+38
-4
@@ -17,15 +17,19 @@
|
||||
package org.jetbrains.plugins.groovy.lang.completion.handlers;
|
||||
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.completion.ConstructorInsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionFeatures;
|
||||
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
|
||||
@@ -33,6 +37,8 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class AfterNewClassInsertHandler implements InsertHandler<LookupItem<PsiClassType>> {
|
||||
private static final Logger LOG = Logger.getInstance(AfterNewClassInsertHandler.class);
|
||||
|
||||
private final PsiClassType myClassType;
|
||||
private final boolean myTriggerFeature;
|
||||
|
||||
@@ -41,14 +47,15 @@ public class AfterNewClassInsertHandler implements InsertHandler<LookupItem<PsiC
|
||||
myTriggerFeature = triggerFeature;
|
||||
}
|
||||
|
||||
public void handleInsert(InsertionContext context, LookupItem<PsiClassType> item) {
|
||||
public void handleInsert(final InsertionContext context, LookupItem<PsiClassType> item) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = myClassType.resolveGenerics();
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
if (psiClass == null || !psiClass.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GroovyPsiElement place = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), GroovyPsiElement.class, false);
|
||||
GroovyPsiElement place =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), GroovyPsiElement.class, false);
|
||||
boolean hasParams = place != null && GroovyCompletionUtil.hasConstructorParameters(psiClass, place);
|
||||
if (myTriggerFeature) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
|
||||
@@ -60,9 +67,36 @@ public class AfterNewClassInsertHandler implements InsertHandler<LookupItem<PsiC
|
||||
else {
|
||||
ParenthesesInsertHandler.NO_PARAMETERS.handleInsert(context, item);
|
||||
}
|
||||
|
||||
GroovyCompletionUtil.addImportForItem(context.getFile(), context.getStartOffset(), item);
|
||||
if (hasParams) {
|
||||
AutoPopupController.getInstance(context.getProject()).autoPopupParameterInfo(context.getEditor(), null);
|
||||
}
|
||||
|
||||
if (psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
final Editor editor = context.getEditor();
|
||||
final int offset = context.getTailOffset();
|
||||
editor.getDocument().insertString(offset, " {}");
|
||||
editor.getCaretModel().moveToOffset(offset + 2);
|
||||
|
||||
context.setLaterRunnable(generateAnonymousBody(editor, context.getFile()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Runnable generateAnonymousBody(final Editor editor, final PsiFile file) {
|
||||
final Project project = file.getProject();
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
if (element == null) return null;
|
||||
|
||||
PsiElement parent = element.getParent().getParent();
|
||||
if (!(parent instanceof PsiAnonymousClass)) return null;
|
||||
|
||||
return ConstructorInsertHandler.genAnonymousBodyFor((PsiAnonymousClass)parent, editor, file, project);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-4
@@ -36,12 +36,8 @@ public class GroovySmartCompletionTest extends GroovyCompletionTestBase {
|
||||
assertOrderedEquals(myFixture.lookupElementStrings, "Bar", "Foo");
|
||||
}
|
||||
|
||||
public void testSmartCompletionAfterNewInDeclarationWithInterface() throws Throwable { doSmartTest(); }
|
||||
|
||||
public void testCaretAfterSmartCompletionAfterNewInDeclaration() throws Throwable { doSmartTest(); }
|
||||
|
||||
public void testSmartCompletionAfterNewInDeclarationWithAbstractClass() throws Throwable { doSmartTest(); }
|
||||
|
||||
public void testSmartCompletionAfterNewInDeclarationWithArray() throws Throwable { doSmartTest(); }
|
||||
|
||||
public void testSmartCompletionAfterNewInDeclarationWithIntArray() throws Throwable { doSmartTest(); }
|
||||
@@ -128,4 +124,19 @@ throw new RuntimeException()
|
||||
void testInnerClassReferenceWithoutQualifier() {
|
||||
doSmartTest()
|
||||
}
|
||||
|
||||
void testAnonymousClassCompletion() {
|
||||
myFixture.configureByText('_a.groovy', '''\
|
||||
Runnable r = new Run<caret>
|
||||
''')
|
||||
myFixture.complete(CompletionType.SMART)
|
||||
myFixture.checkResult('''\
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
void run() {
|
||||
<caret><selection>//To change body of implemented methods use File | Settings | File Templates.</selection>
|
||||
}
|
||||
}
|
||||
''')
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
class Foo {
|
||||
static class Bar {}
|
||||
{
|
||||
List<Bar> l = new AL<caret>
|
||||
List<Bar> l = new ArrL<caret>
|
||||
}
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
abstract class Foo {
|
||||
}
|
||||
class Bar extends Foo {
|
||||
}
|
||||
|
||||
abstract class Foo2 extends Foo {
|
||||
}
|
||||
|
||||
Foo f = new <caret>
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
abstract class Foo {
|
||||
}
|
||||
class Bar extends Foo {
|
||||
}
|
||||
|
||||
abstract class Foo2 extends Foo {
|
||||
}
|
||||
|
||||
Foo f = new Bar()<caret>
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
interface Foo {
|
||||
}
|
||||
class Bar implements Foo {
|
||||
}
|
||||
|
||||
Foo f = new <caret>
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
interface Foo {
|
||||
}
|
||||
class Bar implements Foo {
|
||||
}
|
||||
|
||||
Foo f = new Bar()<caret>
|
||||
Reference in New Issue
Block a user