move code out of JavaSmartCompletionContributor to make it a bit more modular

This commit is contained in:
peter
2015-09-16 15:37:10 +02:00
parent 47d891a99a
commit a4d2b8a1d1
10 changed files with 353 additions and 220 deletions
@@ -0,0 +1,80 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author peter
*/
class CatchTypeProvider extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> CATCH_CLAUSE_TYPE = psiElement().insideStarting(
psiElement(PsiTypeElement.class).withParent(
psiElement(PsiCatchSection.class)));
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters,
final ProcessingContext context,
@NotNull final CompletionResultSet result) {
PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiTryStatement.class);
final PsiCodeBlock tryBlock = tryStatement == null ? null : tryStatement.getTryBlock();
if (tryBlock == null) return;
final InheritorsHolder holder = new InheritorsHolder(result);
for (final PsiClassType type : ExceptionUtil.getThrownExceptions(tryBlock.getStatements())) {
PsiClass typeClass = type.resolve();
if (typeClass != null) {
result.addElement(createCatchTypeVariant(tryBlock, type));
holder.registerClass(typeClass);
}
}
final Collection<PsiClassType> expectedClassTypes = Collections.singletonList(JavaPsiFacade.getElementFactory(
tryBlock.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE));
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
@Override
public void consume(PsiType type) {
final PsiClass psiClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null;
if (psiClass == null || psiClass instanceof PsiTypeParameter) return;
if (!holder.alreadyProcessed(psiClass)) {
result.addElement(createCatchTypeVariant(tryBlock, (PsiClassType)type));
}
}
});
}
@NotNull
private static LookupElement createCatchTypeVariant(PsiCodeBlock tryBlock, PsiClassType type) {
return TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock), TailType.HUMBLE_SPACE_BEFORE_WORD);
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameValuePair;
import com.intellij.psi.PsiType;
import com.intellij.psi.filters.getters.ExpectedTypesGetter;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.StandardPatterns.or;
/**
* @author peter
*/
class ExpectedAnnotationsProvider extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> ANNOTATION_ATTRIBUTE_VALUE = or(
PsiJavaPatterns.psiElement().withParent(PsiNameValuePair.class),
PsiJavaPatterns.psiElement().withSuperParent(2, PsiNameValuePair.class));
@Override
public void addCompletions(@NotNull final CompletionParameters parameters,
final ProcessingContext context,
@NotNull final CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
for (final PsiType type : ExpectedTypesGetter.getExpectedTypes(element, false)) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass != null && psiClass.isAnnotationType()) {
result.addElement(AllClassesGetter.createLookupItem(psiClass, AnnotationInsertHandler.INSTANCE));
}
}
}
}
@@ -26,6 +26,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PatternCondition;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -43,10 +45,26 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* User: anna
*/
public class FunctionalExpressionCompletionProvider extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> LAMBDA = psiElement().with(new PatternCondition<PsiElement>("LAMBDA_CONTEXT") {
@Override
public boolean accepts(@NotNull PsiElement element, ProcessingContext context) {
return isLambdaContext(element);
}});
private static boolean isLambdaContext(@NotNull PsiElement element) {
final PsiElement rulezzRef = element.getParent();
return rulezzRef != null &&
rulezzRef instanceof PsiReferenceExpression &&
((PsiReferenceExpression)rulezzRef).getQualifier() == null &&
LambdaUtil.isValidLambdaContext(rulezzRef.getParent());
}
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@@ -55,7 +73,7 @@ public class FunctionalExpressionCompletionProvider extends CompletionProvider<C
}
static List<LookupElement> getLambdaVariants(@NotNull CompletionParameters parameters, boolean prioritize) {
if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return Collections.emptyList();
if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile()) || !isLambdaContext(parameters.getPosition())) return Collections.emptyList();
List<LookupElement> result = ContainerUtil.newArrayList();
for (ExpectedTypeInfo expectedType : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
@@ -0,0 +1,93 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.filters.getters.InstanceOfLeftPartTypeGetter;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
import java.util.Set;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author peter
*/
class InstanceofTypeProvider extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> AFTER_INSTANCEOF = psiElement().afterLeaf(PsiKeyword.INSTANCEOF);
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters,
final ProcessingContext context,
@NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
final PsiType[] leftTypes = InstanceOfLeftPartTypeGetter.getLeftTypes(position);
final Set<PsiClassType> expectedClassTypes = new LinkedHashSet<PsiClassType>();
final Set<PsiClass> parameterizedTypes = new THashSet<PsiClass>();
for (final PsiType type : leftTypes) {
if (type instanceof PsiClassType) {
final PsiClassType classType = (PsiClassType)type;
if (!classType.isRaw()) {
ContainerUtil.addIfNotNull(classType.resolve(), parameterizedTypes);
}
expectedClassTypes.add(classType.rawType());
}
}
JavaInheritorsGetter
.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
@Override
public void consume(PsiType type) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass == null || psiClass instanceof PsiTypeParameter) return;
//noinspection SuspiciousMethodCalls
if (expectedClassTypes.contains(type)) return;
result.addElement(createInstanceofLookupElement(psiClass, parameterizedTypes));
}
});
}
private static LookupElement createInstanceofLookupElement(PsiClass psiClass, Set<PsiClass> toWildcardInheritors) {
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
if (typeParameters.length > 0) {
for (final PsiClass parameterizedType : toWildcardInheritors) {
if (psiClass.isInheritor(parameterizedType, true)) {
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
final PsiWildcardType wildcard = PsiWildcardType.createUnbounded(psiClass.getManager());
for (final PsiTypeParameter typeParameter : typeParameters) {
substitutor = substitutor.put(typeParameter, wildcard);
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject());
return PsiTypeLookupItem.createLookupItem(factory.createType(psiClass, substitutor), psiClass);
}
}
}
return new JavaPsiClassReferenceElement(psiClass);
}
}
@@ -222,13 +222,11 @@ public class JavaCompletionContributor extends CompletionContributor {
}
final InheritorsHolder inheritors = new InheritorsHolder(result);
if (JavaSmartCompletionContributor.IN_TYPE_ARGS.accepts(position)) {
if (TypeArgumentCompletionProvider.IN_TYPE_ARGS.accepts(position)) {
new TypeArgumentCompletionProvider(false, inheritors).addCompletions(parameters, new ProcessingContext(), result);
}
if (JavaSmartCompletionContributor.LAMBDA.accepts(parameters.getPosition())) {
result.addAllElements(FunctionalExpressionCompletionProvider.getLambdaVariants(parameters, true));
}
result.addAllElements(FunctionalExpressionCompletionProvider.getLambdaVariants(parameters, true));
PrefixMatcher matcher = result.getPrefixMatcher();
if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {
@@ -404,7 +402,7 @@ public class JavaCompletionContributor extends CompletionContributor {
return;
}
if (reference instanceof PsiLabelReference) {
processLabelReference(result, (PsiLabelReference)reference);
LabelReferenceCompletion.processLabelReference(result, (PsiLabelReference)reference);
return;
}
@@ -832,12 +830,6 @@ public class JavaCompletionContributor extends CompletionContributor {
return null;
}
static void processLabelReference(CompletionResultSet result, PsiLabelReference ref) {
for (String s : ref.getVariants()) {
result.addElement(TailTypeDecorator.withTail(LookupElementBuilder.create(s), TailType.SEMICOLON));
}
}
private static class IndentingDecorator extends LookupElementDecorator<LookupElement> {
public IndentingDecorator(LookupElement delegate) {
super(delegate);
@@ -53,10 +53,10 @@ import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.*;
import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.string;
/**
* Created by IntelliJ IDEA.
@@ -132,6 +132,25 @@ public class JavaDocCompletionContributor extends CompletionContributor {
return LookupItemUtil.objectToLookupItem(element);
}
});
extend(CompletionType.SMART, psiElement().inside(
psiElement(PsiDocTag.class).withName(
string().oneOf(PsiKeyword.THROWS, "exception"))), new CompletionProvider<CompletionParameters>() {
@Override
public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
final Set<PsiClass> throwsSet = new HashSet<PsiClass>();
final PsiMethod method = PsiTreeUtil.getContextOfType(element, PsiMethod.class, true);
if(method != null){
for (PsiClassType ref : method.getThrowsList().getReferencedTypes()) {
final PsiClass exception = ref.resolve();
if (exception != null && throwsSet.add(exception)) {
result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.HUMBLE_SPACE_BEFORE_WORD));
}
}
}
}
});
}
private static PsiParameter getDocTagParam(PsiElement tag) {
@@ -15,43 +15,36 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.*;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypeInfoImpl;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.util.Key;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.filters.ElementExtractorFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.OrFilter;
import com.intellij.psi.filters.getters.ExpectedTypesGetter;
import com.intellij.psi.filters.getters.InstanceOfLeftPartTypeGetter;
import com.intellij.psi.filters.getters.JavaMembersGetter;
import com.intellij.psi.filters.types.AssignableFromFilter;
import com.intellij.psi.filters.types.AssignableToFilter;
import com.intellij.psi.impl.source.PsiLabelReference;
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.PsiJavaPatterns.psiMethod;
import static com.intellij.patterns.StandardPatterns.*;
import static com.intellij.patterns.StandardPatterns.or;
/**
* @author peter
@@ -70,7 +63,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
};
private static final ElementExtractorFilter THROWABLES_FILTER = new ElementExtractorFilter(new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE));
@NonNls private static final String EXCEPTION_TAG = "exception";
public static final ElementPattern<PsiElement> AFTER_NEW =
psiElement().afterLeaf(
psiElement().withText(PsiKeyword.NEW).andNot(
@@ -86,32 +78,19 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
static final ElementPattern<PsiElement> INSIDE_TYPECAST_EXPRESSION = psiElement().withParent(
psiElement(PsiReferenceExpression.class).afterLeaf(
psiElement().withText(")").withParent(PsiTypeCastExpression.class)));
static final PsiElementPattern.Capture<PsiElement> IN_TYPE_ARGS =
psiElement().inside(psiElement(PsiReferenceParameterList.class));
static final PsiElementPattern.Capture<PsiElement> LAMBDA = psiElement().with(new PatternCondition<PsiElement>("LAMBDA_CONTEXT") {
@Override
public boolean accepts(@NotNull PsiElement element, ProcessingContext context) {
final PsiElement rulezzRef = element.getParent();
return rulezzRef != null &&
rulezzRef instanceof PsiReferenceExpression &&
((PsiReferenceExpression)rulezzRef).getQualifier() == null &&
LambdaUtil.isValidLambdaContext(rulezzRef.getParent());
}});
static final PsiElementPattern.Capture<PsiElement> METHOD_REFERENCE = psiElement().with(new PatternCondition<PsiElement>("METHOD_REFERENCE_CONTEXT") {
@Override
public boolean accepts(@NotNull PsiElement element, ProcessingContext context) {
final PsiElement rulezzRef = element.getParent();
return rulezzRef != null &&
LambdaUtil.isValidLambdaContext(rulezzRef.getParent());
}});
@Nullable
private static ElementFilter getReferenceFilter(PsiElement element) {
private static ElementFilter getClassReferenceFilter(PsiElement element) {
//throw new foo
if (AFTER_THROW_NEW.accepts(element)) {
return THROWABLES_FILTER;
}
//throws list
PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
if (method != null && PsiTreeUtil.isAncestor(method.getThrowsList(), element, true)) {
return THROWABLES_FILTER;
}
//new xxx.yyy
if (psiElement().afterLeaf(psiElement().withText(".")).withSuperParent(2, psiElement(PsiNewExpression.class)).accepts(element)) {
@@ -138,39 +117,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
extend(CompletionType.SMART, MethodReturnTypeProvider.IN_METHOD_RETURN_TYPE, new MethodReturnTypeProvider());
extend(CompletionType.SMART, psiElement().afterLeaf(PsiKeyword.INSTANCEOF), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
final PsiType[] leftTypes = InstanceOfLeftPartTypeGetter.getLeftTypes(position);
final Set<PsiClassType> expectedClassTypes = new LinkedHashSet<PsiClassType>();
final Set<PsiClass> parameterizedTypes = new THashSet<PsiClass>();
for (final PsiType type : leftTypes) {
if (type instanceof PsiClassType) {
final PsiClassType classType = (PsiClassType)type;
if (!classType.isRaw()) {
ContainerUtil.addIfNotNull(classType.resolve(), parameterizedTypes);
}
expectedClassTypes.add(classType.rawType());
}
}
JavaInheritorsGetter
.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
@Override
public void consume(PsiType type) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass == null || psiClass instanceof PsiTypeParameter) return;
//noinspection SuspiciousMethodCalls
if (expectedClassTypes.contains(type)) return;
result.addElement(createInstanceofLookupElement(psiClass, parameterizedTypes));
}
});
}
});
extend(CompletionType.SMART, InstanceofTypeProvider.AFTER_INSTANCEOF, new InstanceofTypeProvider());
extend(CompletionType.SMART, psiElement(), new CompletionProvider<CompletionParameters>() {
@Override
@@ -180,7 +127,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
final PsiElement element = parameters.getPosition();
final PsiReference reference = element.getContainingFile().findReferenceAt(parameters.getOffset());
if (reference != null) {
ElementFilter filter = getReferenceFilter(element);
ElementFilter filter = getClassReferenceFilter(element);
if (filter != null) {
final List<ExpectedTypeInfo> infos = Arrays.asList(getExpectedTypes(parameters));
for (final LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) {
@@ -203,23 +150,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
});
//method throws clause
extend(CompletionType.SMART, psiElement().inside(
psiElement(PsiReferenceList.class).save("refList").withParent(
psiMethod().withThrowsList(get("refList")))), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
final PsiReference reference = element.getContainingFile().findReferenceAt(parameters.getOffset());
assert reference != null;
for (final LookupElement item : completeReference(element, reference, THROWABLES_FILTER, true, false, parameters, result.getPrefixMatcher())) {
result.addElement(item);
}
}
});
extend(CompletionType.SMART, INSIDE_EXPRESSION, new ExpectedTypeBasedCompletionProvider() {
@Override
protected void addCompletions(final CompletionParameters params, final CompletionResultSet result, final Collection<ExpectedTypeInfo> _infos) {
@@ -245,12 +175,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
BasicExpressionCompletionContributor.fillCompletionVariants(new JavaSmartCompletionParameters(params, info), new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
final TypedLookupItem typed = lookupElement.as(TypedLookupItem.CLASS_CONDITION_KEY);
if (typed != null) {
final PsiType psiType = typed.getType();
if (psiType != null && info.getType().isAssignableFrom(psiType)) {
result.addElement(decorate(lookupElement, _infos));
}
final PsiType psiType = JavaCompletionUtil.getLookupElementType(lookupElement);
if (psiType != null && info.getType().isAssignableFrom(psiType)) {
result.addElement(decorate(lookupElement, _infos));
}
}
}, result.getPrefixMatcher());
@@ -269,103 +196,18 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
});
extend(CompletionType.SMART, or(
PsiJavaPatterns.psiElement().withParent(PsiNameValuePair.class),
PsiJavaPatterns.psiElement().withSuperParent(2, PsiNameValuePair.class)), new CompletionProvider<CompletionParameters>() {
@Override
public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
extend(CompletionType.SMART, ExpectedAnnotationsProvider.ANNOTATION_ATTRIBUTE_VALUE, new ExpectedAnnotationsProvider());
for (final PsiType type : ExpectedTypesGetter.getExpectedTypes(element, false)) {
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass != null && psiClass.isAnnotationType()) {
result.addElement(AllClassesGetter.createLookupItem(psiClass, AnnotationInsertHandler.INSTANCE));
}
}
}
});
extend(CompletionType.SMART, psiElement().inside(
psiElement(PsiDocTag.class).withName(
string().oneOf(PsiKeyword.THROWS, EXCEPTION_TAG))), new CompletionProvider<CompletionParameters>() {
@Override
public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
final Set<PsiClass> throwsSet = new HashSet<PsiClass>();
final PsiMethod method = PsiTreeUtil.getContextOfType(element, PsiMethod.class, true);
if(method != null){
for (PsiClassType ref : method.getThrowsList().getReferencedTypes()) {
final PsiClass exception = ref.resolve();
if (exception != null && throwsSet.add(exception)) {
result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.HUMBLE_SPACE_BEFORE_WORD));
}
}
}
}
});
final Key<PsiTryStatement> tryKey = Key.create("try");
extend(CompletionType.SMART, psiElement().insideStarting(
psiElement(PsiTypeElement.class).withParent(
psiElement(PsiCatchSection.class).withParent(
psiElement(PsiTryStatement.class).save(tryKey)))), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiCodeBlock tryBlock = context.get(tryKey).getTryBlock();
if (tryBlock == null) return;
final InheritorsHolder holder = new InheritorsHolder(result);
for (final PsiClassType type : ExceptionUtil.getThrownExceptions(tryBlock.getStatements())) {
PsiClass typeClass = type.resolve();
if (typeClass != null) {
result.addElement(createCatchTypeVariant(tryBlock, type));
holder.registerClass(typeClass);
}
}
final Collection<PsiClassType> expectedClassTypes = ContainerUtil.createMaybeSingletonList(JavaPsiFacade.getElementFactory(
tryBlock.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE));
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
@Override
public void consume(PsiType type) {
final PsiClass psiClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null;
if (psiClass == null || psiClass instanceof PsiTypeParameter) return;
if (!holder.alreadyProcessed(psiClass)) {
result.addElement(createCatchTypeVariant(tryBlock, (PsiClassType)type));
}
}
});
}
@NotNull
private LookupElement createCatchTypeVariant(PsiCodeBlock tryBlock, PsiClassType type) {
return TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock), TailType.HUMBLE_SPACE_BEFORE_WORD);
}
});
extend(CompletionType.SMART, IN_TYPE_ARGS, new TypeArgumentCompletionProvider(true, null));
extend(CompletionType.SMART, CatchTypeProvider.CATCH_CLAUSE_TYPE, new CatchTypeProvider());
extend(CompletionType.SMART, TypeArgumentCompletionProvider.IN_TYPE_ARGS, new TypeArgumentCompletionProvider(true, null));
extend(CompletionType.SMART, AFTER_NEW, new JavaInheritorsGetter(ConstructorInsertHandler.SMART_INSTANCE));
extend(CompletionType.SMART, psiElement().afterLeaf(PsiKeyword.BREAK, PsiKeyword.CONTINUE), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
PsiReference ref = parameters.getPosition().getContainingFile().findReferenceAt(parameters.getOffset());
if (ref instanceof PsiLabelReference) {
JavaCompletionContributor.processLabelReference(result, (PsiLabelReference)ref);
}
}
});
extend(CompletionType.SMART, LabelReferenceCompletion.LABEL_REFERENCE, new LabelReferenceCompletion());
extend(CompletionType.SMART, LAMBDA, new FunctionalExpressionCompletionProvider());
extend(CompletionType.SMART, METHOD_REFERENCE, new MethodReferenceCompletionProvider());
extend(CompletionType.SMART, psiElement(), new FunctionalExpressionCompletionProvider());
extend(CompletionType.SMART, psiElement(), new MethodReferenceCompletionProvider());
}
@NotNull
@@ -402,27 +244,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
return new SmartCompletionDecorator(lookupElement, infos);
}
private static LookupElement createInstanceofLookupElement(PsiClass psiClass, Set<PsiClass> toWildcardInheritors) {
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
if (typeParameters.length > 0) {
for (final PsiClass parameterizedType : toWildcardInheritors) {
if (psiClass.isInheritor(parameterizedType, true)) {
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
final PsiWildcardType wildcard = PsiWildcardType.createUnbounded(psiClass.getManager());
for (final PsiTypeParameter typeParameter : typeParameters) {
substitutor = substitutor.put(typeParameter, wildcard);
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject());
return PsiTypeLookupItem.createLookupItem(factory.createType(psiClass, substitutor), psiClass);
}
}
}
return new JavaPsiClassReferenceElement(psiClass);
}
@NotNull
public static ExpectedTypeInfo[] getExpectedTypes(final CompletionParameters parameters) {
return getExpectedTypes(parameters, parameters.getCompletionType() == CompletionType.SMART);
@@ -0,0 +1,52 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.PsiReference;
import com.intellij.psi.impl.source.PsiLabelReference;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PlatformPatterns.psiElement;
/**
* @author peter
*/
class LabelReferenceCompletion extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> LABEL_REFERENCE = psiElement().afterLeaf(PsiKeyword.BREAK, PsiKeyword.CONTINUE);
static void processLabelReference(CompletionResultSet result, PsiLabelReference ref) {
for (String s : ref.getVariants()) {
result.addElement(TailTypeDecorator.withTail(LookupElementBuilder.create(s), TailType.SEMICOLON));
}
}
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
PsiReference ref = parameters.getPosition().getContainingFile().findReferenceAt(parameters.getOffset());
if (ref instanceof PsiLabelReference) {
processLabelReference(result, (PsiLabelReference)ref);
}
}
}
@@ -40,6 +40,10 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple
ProcessingContext context,
@NotNull final CompletionResultSet result) {
if (!PsiUtil.isLanguageLevel8OrHigher(parameters.getOriginalFile())) return;
final PsiElement rulezzRef = parameters.getPosition().getParent();
if (rulezzRef == null || !LambdaUtil.isValidLambdaContext(rulezzRef.getParent())) return;
final ExpectedTypeInfo[] expectedTypes = JavaSmartCompletionContributor.getExpectedTypes(parameters);
for (ExpectedTypeInfo expectedType : expectedTypes) {
final PsiType defaultType = expectedType.getDefaultType();
@@ -27,6 +27,7 @@ import com.intellij.codeInsight.lookup.TailTypeDecorator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -48,6 +49,7 @@ import static com.intellij.patterns.PsiJavaPatterns.psiElement;
* @author peter
*/
class TypeArgumentCompletionProvider extends CompletionProvider<CompletionParameters> {
static final ElementPattern<PsiElement> IN_TYPE_ARGS = psiElement().inside(PsiReferenceParameterList.class);
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.TypeArgumentCompletionProvider");
private final boolean mySmart;
@Nullable private final InheritorsHolder myInheritors;