mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
smart completion after new in groovy argument lists
This commit is contained in:
+3
-72
@@ -19,8 +19,6 @@ import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
@@ -30,19 +28,15 @@ import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.GroovyIcons;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.handlers.AfterNewClassInsertHandler;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.handlers.ArrayInsertHandler;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.handlers.NamedArgumentInsertHandler;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
@@ -70,6 +64,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.CompletionProcessor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
|
||||
@@ -89,10 +84,6 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipWhitespaces
|
||||
*/
|
||||
public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
private static final ElementPattern<PsiElement> AFTER_NEW =
|
||||
psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).andNot(psiElement().afterLeaf(psiElement().withText(PsiKeyword.THROW))))
|
||||
.withSuperParent(3, GrVariable.class);
|
||||
|
||||
private static final ElementPattern<PsiElement> AFTER_DOT = psiElement().afterLeaf(".").withParent(GrReferenceExpression.class);
|
||||
|
||||
private static final String[] MODIFIERS =
|
||||
@@ -299,44 +290,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
});
|
||||
|
||||
extend(CompletionType.SMART, AFTER_NEW, new CompletionProvider<CompletionParameters>(false) {
|
||||
protected void addCompletions(@NotNull final CompletionParameters parameters,
|
||||
final ProcessingContext matchingContext,
|
||||
@NotNull final CompletionResultSet result) {
|
||||
final PsiElement identifierCopy = parameters.getPosition();
|
||||
|
||||
final List<PsiClassType> expectedClassTypes = new SmartList<PsiClassType>();
|
||||
final List<PsiArrayType> expectedArrayTypes = new ArrayList<PsiArrayType>();
|
||||
|
||||
PsiType psiType = ((GrVariable)identifierCopy.getParent().getParent().getParent()).getTypeGroovy();
|
||||
if (psiType instanceof PsiClassType) {
|
||||
PsiType type = JavaCompletionUtil.eliminateWildcards(JavaCompletionUtil.originalize(psiType));
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
if (classType.resolve() != null) {
|
||||
expectedClassTypes.add(classType);
|
||||
}
|
||||
}
|
||||
else if (psiType instanceof PsiArrayType) {
|
||||
expectedArrayTypes.add((PsiArrayType)psiType);
|
||||
}
|
||||
|
||||
for (final PsiArrayType type : expectedArrayTypes) {
|
||||
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy);
|
||||
if (item.getObject() instanceof PsiClass) {
|
||||
JavaCompletionUtil.setShowFQN(item);
|
||||
}
|
||||
item.setInsertHandler(new ArrayInsertHandler());
|
||||
result.addElement(item);
|
||||
}
|
||||
|
||||
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
|
||||
public void consume(final PsiType type) {
|
||||
addExpectedType(result, type, identifierCopy);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//provide 'this' and 'super' completions in ClassName.<caret>
|
||||
extend(CompletionType.BASIC, AFTER_DOT, new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
@@ -353,7 +306,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
GrReferenceExpression referenceExpression = (GrReferenceExpression)qualifier;
|
||||
final PsiElement resolved = referenceExpression.resolve();
|
||||
if (!(resolved instanceof PsiClass)) return;
|
||||
if (!org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.hasEnclosingInstanceInScope((PsiClass)resolved, position, false)) return;
|
||||
if (!PsiUtil.hasEnclosingInstanceInScope((PsiClass)resolved, position, false)) return;
|
||||
|
||||
for (String keyword : THIS_SUPER) {
|
||||
result.addElement(LookupElementBuilder.create(keyword));
|
||||
@@ -494,7 +447,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
Map<String, PsiMethod> writableProperties = new HashMap<String, PsiMethod>();
|
||||
for (PsiMethod method : containingClass.getAllMethods()) {
|
||||
if (GroovyPropertyUtils.isSimplePropertySetter(method)) {
|
||||
if (org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isStaticsOK(method, call)) {
|
||||
if (PsiUtil.isStaticsOK(method, call)) {
|
||||
final String name = GroovyPropertyUtils.getPropertyNameBySetter(method);
|
||||
if (name != null && !writableProperties.containsKey(name)) {
|
||||
writableProperties.put(name, method);
|
||||
@@ -538,28 +491,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean checkForInnerClass(PsiClass psiClass, PsiElement identifierCopy) {
|
||||
return !PsiUtil.isInnerClass(psiClass) ||
|
||||
org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
|
||||
.hasEnclosingInstanceInScope(psiClass.getContainingClass(), identifierCopy, true);
|
||||
}
|
||||
|
||||
private static void addExpectedType(final CompletionResultSet result, final PsiType type, final PsiElement place) {
|
||||
if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return;
|
||||
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
|
||||
if (psiClass == null) return;
|
||||
|
||||
if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return;
|
||||
if (!checkForInnerClass(psiClass, place)) return;
|
||||
|
||||
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), place);
|
||||
JavaCompletionUtil.setShowFQN(item);
|
||||
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, place));
|
||||
result.addElement(item);
|
||||
}
|
||||
|
||||
public void beforeCompletion(@NotNull final CompletionInitializationContext context) {
|
||||
if (context.getCompletionType() == CompletionType.BASIC && context.getFile() instanceof GroovyFile) {
|
||||
if (semicolonNeeded(context)) {
|
||||
|
||||
+75
-4
@@ -26,20 +26,20 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.SmartList;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.handlers.AfterNewClassInsertHandler;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.handlers.ArrayInsertHandler;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
@@ -53,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
@@ -69,6 +70,8 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
|
||||
GrAssignmentExpression.class),
|
||||
psiElement(
|
||||
GrVariable.class))));
|
||||
private static final ElementPattern<PsiElement> AFTER_NEW =
|
||||
psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).andNot(psiElement().afterLeaf(psiElement().withText(PsiKeyword.THROW))));
|
||||
private static final TObjectHashingStrategy<TypeConstraint> EXPECTED_TYPE_INFO_STRATEGY =
|
||||
new TObjectHashingStrategy<TypeConstraint>() {
|
||||
public int computeHashCode(final TypeConstraint object) {
|
||||
@@ -183,8 +186,76 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extend(CompletionType.SMART, AFTER_NEW, new CompletionProvider<CompletionParameters>() {
|
||||
protected void addCompletions(@NotNull final CompletionParameters parameters,
|
||||
final ProcessingContext matchingContext,
|
||||
@NotNull final CompletionResultSet result) {
|
||||
final PsiElement identifierCopy = parameters.getPosition();
|
||||
final GrExpression expression = PsiTreeUtil.getParentOfType(identifierCopy, GrExpression.class);
|
||||
if (expression == null) return;
|
||||
|
||||
final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression);
|
||||
for (PsiType type : types) {
|
||||
if (type instanceof PsiArrayType) {
|
||||
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy);
|
||||
if (item.getObject() instanceof PsiClass) {
|
||||
JavaCompletionUtil.setShowFQN(item);
|
||||
}
|
||||
item.setInsertHandler(new ArrayInsertHandler());
|
||||
result.addElement(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final List<PsiClassType> expectedClassTypes = new SmartList<PsiClassType>();
|
||||
|
||||
for (PsiType psiType : types) {
|
||||
if (psiType instanceof PsiClassType) {
|
||||
PsiType type = JavaCompletionUtil.eliminateWildcards(JavaCompletionUtil.originalize(psiType));
|
||||
final PsiClassType classType = (PsiClassType)type;
|
||||
if (classType.resolve() != null) {
|
||||
expectedClassTypes.add(classType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
|
||||
public void consume(final PsiType type) {
|
||||
addExpectedType(result, type, identifierCopy);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
|
||||
super.fillCompletionVariants(parameters, result);
|
||||
}
|
||||
|
||||
private static void addExpectedType(final CompletionResultSet result, final PsiType type, final PsiElement place) {
|
||||
if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return;
|
||||
|
||||
final PsiClass psiClass = com.intellij.psi.util.PsiUtil.resolveClassInType(type);
|
||||
if (psiClass == null) return;
|
||||
|
||||
if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return;
|
||||
if (!checkForInnerClass(psiClass, place)) return;
|
||||
|
||||
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), place);
|
||||
JavaCompletionUtil.setShowFQN(item);
|
||||
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, place));
|
||||
result.addElement(item);
|
||||
}
|
||||
|
||||
private static boolean checkForInnerClass(PsiClass psiClass, PsiElement identifierCopy) {
|
||||
return !com.intellij.psi.util.PsiUtil.isInnerClass(psiClass) ||
|
||||
PsiUtil.hasEnclosingInstanceInScope(psiClass.getContainingClass(), identifierCopy, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
|
||||
if (context.getCompletionType() != CompletionType.SMART) return;
|
||||
|
||||
+6
-4
@@ -440,7 +440,7 @@ public class GrClosureSignatureUtil {
|
||||
@NotNull GrClosableBlock[] closureArguments, final boolean partial) {
|
||||
List<InnerArg> innerArgs = new ArrayList<InnerArg>();
|
||||
|
||||
boolean hasNamedArgs = namedArgs != null && namedArgs.length > 0;
|
||||
boolean hasNamedArgs = namedArgs.length > 0;
|
||||
GrClosureParameter[] params = signature.getParameters();
|
||||
|
||||
if (hasNamedArgs) {
|
||||
@@ -454,10 +454,12 @@ public class GrClosureSignatureUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (expressionArgs != null) {
|
||||
for (GrExpression expression : expressionArgs) {
|
||||
innerArgs.add(new InnerArg(expression.getType(), expression));
|
||||
for (GrExpression expression : expressionArgs) {
|
||||
PsiType type = expression.getType();
|
||||
if (expression instanceof GrNewExpression && com.intellij.psi.util.PsiUtil.resolveClassInType(type) == null) {
|
||||
type = null;
|
||||
}
|
||||
innerArgs.add(new InnerArg(type, expression));
|
||||
}
|
||||
|
||||
for (GrClosableBlock closureArgument : closureArguments) {
|
||||
|
||||
@@ -68,6 +68,8 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase {
|
||||
doSmartTest();
|
||||
}
|
||||
|
||||
public void testSmartAfterNewInCall() throws Throwable { doSmartTest(); }
|
||||
|
||||
public void testNamedParametersForApplication() throws Throwable {
|
||||
doVariantableTest("abx", "aby");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
def foo(List<String> l) {}
|
||||
foo(new ArrLi<caret>)
|
||||
@@ -0,0 +1,2 @@
|
||||
def foo(List<String> l) {}
|
||||
foo(new ArrayList<String>(<caret>))
|
||||
Reference in New Issue
Block a user