mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
java: IDEA-56612 code completion for catch argument must suggest only exception classes
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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() + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class AbcdClass {}
|
||||
@interface AbcdAnno {}
|
||||
|
||||
@Abcd<caret>
|
||||
class Foo {}
|
||||
@@ -0,0 +1,5 @@
|
||||
class AbcdClass {}
|
||||
@interface AbcdAnno {}
|
||||
|
||||
@AbcdAnno
|
||||
class Foo {}
|
||||
@@ -0,0 +1,10 @@
|
||||
class AbcdClass {}
|
||||
class AbcdException extends Throwable {}
|
||||
|
||||
class Foo {
|
||||
{
|
||||
try {
|
||||
|
||||
} catch (Abcd<caret>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class AbcdClass {}
|
||||
class AbcdException extends Throwable {}
|
||||
|
||||
class Foo {
|
||||
{
|
||||
try {
|
||||
|
||||
} catch (AbcdException<caret>)
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user