java: IDEA-56612 code completion for catch argument must suggest only exception classes

This commit is contained in:
peter.gromov
2010-12-29 16:16:40 +03:00
parent bfd12da4ad
commit 69610271bc
9 changed files with 53 additions and 67 deletions

View File

@@ -28,7 +28,6 @@ import com.intellij.psi.*;
import com.intellij.psi.filters.ClassFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.filters.classes.ThisOrAnyInnerFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.filters.types.AssignableFromFilter;
import com.intellij.psi.util.PsiTreeUtil;
@@ -38,19 +37,16 @@ import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PsiJavaPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.or;
/**
* @author peter
*/
public class JavaClassNameCompletionContributor extends CompletionContributor {
private static final PsiJavaElementPattern.Capture<PsiElement> AFTER_THROW_NEW = psiElement().afterLeaf(
psiElement().withText(PsiKeyword.NEW).afterLeaf(PsiKeyword.THROW));
private static final PsiJavaElementPattern.Capture<PsiElement> AFTER_NEW = psiElement().afterLeaf(PsiKeyword.NEW);
private static final PsiJavaElementPattern.Capture<PsiElement> IN_TYPE_PARAMETER =
psiElement().afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.SUPER, "&").withParent(
psiElement(PsiReferenceList.class).withParent(PsiTypeParameter.class));
private static final PsiJavaElementPattern.Capture<PsiElement> INSIDE_METHOD_THROWS_CLAUSE = psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(
PsiMethod.class).andNot(psiElement().inside(PsiCodeBlock.class)).andNot(psiElement().inside(PsiParameterList.class));
public JavaClassNameCompletionContributor() {
extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>() {
@@ -63,9 +59,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
final PsiElement insertedElement = parameters.getPosition();
final ElementFilter filter =
AFTER_THROW_NEW.accepts(insertedElement) ? new AssignableFromFilter("java.lang.Throwable") :
or(JavaSmartCompletionContributor.AFTER_THROW_NEW,
JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE,
JavaCompletionContributor.IN_CATCH_TYPE).accepts(insertedElement) ? new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE) :
IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) :
INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement) ? new ThisOrAnyInnerFilter(new AssignableFromFilter("java.lang.Throwable")) :
TrueFilter.INSTANCE;

View File

@@ -30,14 +30,10 @@ import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.PsiJavaElementPattern;
import com.intellij.patterns.PsiNameValuePairPattern;
import com.intellij.patterns.*;
import com.intellij.psi.*;
import com.intellij.psi.filters.*;
import com.intellij.psi.filters.classes.AssignableFromContextFilter;
import com.intellij.psi.filters.classes.ThisOrAnyInnerFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.filters.element.ModifierFilter;
import com.intellij.psi.filters.getters.ExpectedTypesGetter;
@@ -88,6 +84,10 @@ public class JavaCompletionContributor extends CompletionContributor {
elementType().oneOf(JavaTokenType.DOUBLE_LITERAL, JavaTokenType.LONG_LITERAL, JavaTokenType.FLOAT_LITERAL, JavaTokenType.INTEGER_LITERAL)));
private static final PsiJavaElementPattern.Capture<PsiElement> IMPORT_REFERENCE =
psiElement().withParent(psiElement(PsiJavaCodeReferenceElement.class).withParent(PsiImportStatementBase.class));
static final PsiJavaElementPattern.Capture<PsiElement> IN_CATCH_TYPE =
psiElement().afterLeaf(psiElement().withText("(").withParent(PsiCatchSection.class));
static final PsiJavaElementPattern.Capture<PsiElement> INSIDE_METHOD_THROWS_CLAUSE = psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(
PsiMethod.class).andNot(psiElement().inside(PsiCodeBlock.class)).andNot(psiElement().inside(PsiParameterList.class));
@Nullable
private static ElementFilter getReferenceFilter(PsiElement position) {
@@ -102,9 +102,8 @@ public class JavaCompletionContributor extends CompletionContributor {
return new OrFilter(ElementClassFilter.CLASS, ElementClassFilter.PACKAGE_FILTER);
}
// Completion for classes in method throws section
if (psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(psiElement(PsiReferenceList.class).withParent(PsiMethod.class)).accepts(position)) {
return new OrFilter(new ThisOrAnyInnerFilter(new AssignableFromFilter("java.lang.Throwable")), ElementClassFilter.PACKAGE_FILTER);
if (INSIDE_METHOD_THROWS_CLAUSE.accepts(position)) {
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
}
if (psiElement().afterLeaf(PsiKeyword.INSTANCEOF).accepts(position)) {
@@ -125,12 +124,12 @@ public class JavaCompletionContributor extends CompletionContributor {
return ElementClassFilter.VARIABLE;
}
if (psiElement().afterLeaf(psiElement().withText("(").withParent(PsiTryStatement.class)).accepts(position)) {
return new OrFilter(new ThisOrAnyInnerFilter(new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE)), ElementClassFilter.PACKAGE_FILTER);
if (IN_CATCH_TYPE.accepts(position)) {
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
}
if (JavaSmartCompletionContributor.AFTER_THROW_NEW.accepts(position)) {
return new ThisOrAnyInnerFilter(new AssignableFromFilter("java.lang.Throwable"));
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
}
if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {

View File

@@ -16,7 +16,6 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.*;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
@@ -41,7 +40,10 @@ import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.*;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import com.intellij.util.ReflectionCache;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
@@ -76,13 +78,10 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
psiElement().withText(PsiKeyword.NEW).andNot(
psiElement().afterLeaf(
psiElement().withText(PsiKeyword.THROW))));
static final ElementPattern<PsiElement> AFTER_THROW_NEW =
psiElement().afterLeaf(
psiElement().withText(PsiKeyword.NEW).afterLeaf(
psiElement().withText(PsiKeyword.THROW)));
static final ElementPattern<PsiElement> AFTER_THROW_NEW = psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).afterLeaf(PsiKeyword.THROW));
private static final OrFilter THROWABLE_TYPE_FILTER = new OrFilter(
new GeneratorFilter(AssignableGroupFilter.class, new ThrowsListGetter()),
new AssignableFromFilter("java.lang.RuntimeException"));
new AssignableFromFilter(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION));
public static final ElementPattern<PsiElement> INSIDE_EXPRESSION = or(
psiElement().withParent(PsiExpression.class).andNot(psiElement().withParent(PsiLiteralExpression.class)),
psiElement().inside(PsiClassObjectAccessExpression.class),

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2000-2009 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.psi.filters.classes;
import com.intellij.psi.PsiClass;
import com.intellij.psi.filters.OrFilter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.util.ReflectionCache;
/**
* Created by IntelliJ IDEA.
* User: ik
* Date: 28.01.2003
* Time: 20:49:29
* To change this template use Options | File Templates.
*/
public class ThisOrAnyInnerFilter extends OrFilter{
public ThisOrAnyInnerFilter(ElementFilter filter){
super(filter, new AnyInnerFilter(filter));
}
public boolean isClassAcceptable(Class aClass){
return ReflectionCache.isAssignable(PsiClass.class, aClass);
}
public String toString(){
return "this-or-any-inner(" + getFilters().get(0).toString() + ")";
}
}

View File

@@ -0,0 +1,5 @@
class AbcdClass {}
@interface AbcdAnno {}
@Abcd<caret>
class Foo {}

View File

@@ -0,0 +1,5 @@
class AbcdClass {}
@interface AbcdAnno {}
@AbcdAnno
class Foo {}

View File

@@ -0,0 +1,10 @@
class AbcdClass {}
class AbcdException extends Throwable {}
class Foo {
{
try {
} catch (Abcd<caret>)
}
}

View File

@@ -0,0 +1,10 @@
class AbcdClass {}
class AbcdException extends Throwable {}
class Foo {
{
try {
} catch (AbcdException<caret>)
}
}

View File

@@ -825,6 +825,9 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
public void testLiveTemplatePrefixTab() throws Throwable {doTest('\t') }
public void testOnlyAnnotationsAfterAt() throws Throwable { doTest() }
public void testOnlyExceptionsInCatch() throws Throwable { doTest() }
public void testRightShift() throws Throwable {
configure()
assertStringItems("myField1", "myField2");