From d4ac758388a432ce41ce68764fad85f39f4d240a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Apr 2012 12:06:43 +0400 Subject: [PATCH] IDEA-84224 --- .../quickfix/AddExceptionToThrowsFix.java | 61 +++++---- .../src/com/intellij/psi/util/PsiUtil.java | 129 ++++++++++-------- .../quickFix/addToThrows/after1.java | 2 +- .../quickFix/addToThrows/after2.java | 2 +- .../quickFix/addToThrows/afterMultiple.java | 11 ++ .../quickFix/addToThrows/before1.java | 2 +- .../quickFix/addToThrows/before2.java | 2 +- .../quickFix/addToThrows/beforeMultiple.java | 11 ++ .../src/messages/QuickFixBundle.properties | 2 +- 9 files changed, 132 insertions(+), 90 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/afterMultiple.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/beforeMultiple.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java index 7ce033a5bdd6..4106444e97d0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java @@ -29,6 +29,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +42,7 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AddExceptionToThrowsFix"); private final PsiElement myWrongElement; - public AddExceptionToThrowsFix(PsiElement wrongElement) { + public AddExceptionToThrowsFix(@NotNull PsiElement wrongElement) { myWrongElement = wrongElement; } @@ -56,16 +57,15 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { PsiDocumentManager.getInstance(project).commitAllDocuments(); - final PsiMethod targetMethod = PsiTreeUtil.getParentOfType(myWrongElement, PsiMethod.class); - PsiElement element = findElement(myWrongElement, targetMethod); - LOG.assertTrue(element != null); - - final Set unhandledExceptions = filterInProjectExceptions(targetMethod, ExceptionUtil.getUnhandledExceptions(element)); + PsiMethod targetMethod = PsiTreeUtil.getParentOfType(myWrongElement, PsiMethod.class); + List exceptions = getUnhandledExceptions(myWrongElement, targetMethod); + if (exceptions == null || targetMethod == null) return; + Set unhandledExceptions = new THashSet(exceptions); addExceptionsToThrowsList(project, targetMethod, unhandledExceptions); } - static void addExceptionsToThrowsList(final Project project, final PsiMethod targetMethod, final Set unhandledExceptions) { + static void addExceptionsToThrowsList(@NotNull final Project project, @NotNull final PsiMethod targetMethod, @NotNull final Set unhandledExceptions) { final PsiMethod[] superMethods = getSuperMethods(targetMethod); boolean hasSuperMethodsWithoutExceptions = hasSuperMethodsWithoutExceptions(superMethods, unhandledExceptions); @@ -119,13 +119,13 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { ); } - private static PsiMethod[] getSuperMethods(PsiMethod targetMethod) { + private static PsiMethod[] getSuperMethods(@NotNull PsiMethod targetMethod) { List result = new ArrayList(); collectSuperMethods(targetMethod, result); return result.toArray(new PsiMethod[result.size()]); } - private static void collectSuperMethods(PsiMethod method, List result) { + private static void collectSuperMethods(@NotNull PsiMethod method, @NotNull List result) { PsiMethod[] superMethods = method.findSuperMethods(); for (PsiMethod superMethod : superMethods) { result.add(superMethod); @@ -133,7 +133,7 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { } } - private static boolean hasSuperMethodsWithoutExceptions(PsiMethod[] superMethods, Set unhandledExceptions) { + private static boolean hasSuperMethodsWithoutExceptions(@NotNull PsiMethod[] superMethods, @NotNull Set unhandledExceptions) { for (PsiMethod superMethod : superMethods) { PsiClassType[] referencedTypes = superMethod.getThrowsList().getReferencedTypes(); @@ -150,7 +150,9 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { return false; } - private static void processMethod(Project project, PsiMethod targetMethod, Set unhandledExceptions) throws IncorrectOperationException { + private static void processMethod(@NotNull Project project, + @NotNull PsiMethod targetMethod, + @NotNull Set unhandledExceptions) throws IncorrectOperationException { for (PsiClassType unhandledException : unhandledExceptions) { PsiClass exceptionClass = unhandledException.resolve(); if (exceptionClass != null) { @@ -168,10 +170,10 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { PsiMethod method = PsiTreeUtil.getParentOfType(myWrongElement, PsiMethod.class); if (method == null || !method.getThrowsList().isPhysical()) return false; - PsiElement element = findElement(myWrongElement, method); - if (element == null) return false; + List unhandled = getUnhandledExceptions(myWrongElement, method); + if (unhandled == null || unhandled.isEmpty()) return false; - setText(QuickFixBundle.message("add.exception.to.throws.text")); + setText(QuickFixBundle.message("add.exception.to.throws.text", unhandled.size())); return true; } @@ -182,31 +184,22 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { } @Nullable - private static PsiElement findElement(PsiElement element, PsiMethod topElement) { + private static List getUnhandledExceptions(@Nullable PsiElement element, PsiMethod topElement) { if (element == null || element == topElement) return null; List unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element); if (!filterInProjectExceptions(topElement, unhandledExceptions).isEmpty()) { - return element; + return unhandledExceptions; } - return findElement(element.getParent(), topElement); + return getUnhandledExceptions(element.getParent(), topElement); } - private static Set filterInProjectExceptions(PsiMethod targetMethod, List unhandledExceptions) { + @NotNull + private static Set filterInProjectExceptions(@Nullable PsiMethod targetMethod, @NotNull List unhandledExceptions) { if (targetMethod == null) return Collections.emptySet(); Set result = new HashSet(); - if (!targetMethod.getManager().isInProject(targetMethod)) { - PsiClassType[] referencedTypes = targetMethod.getThrowsList().getReferencedTypes(); - for (PsiClassType referencedType : referencedTypes) { - PsiClass psiClass = referencedType.resolve(); - if (psiClass == null) continue; - for (PsiClassType exception : unhandledExceptions) { - if (referencedType.isAssignableFrom(exception)) result.add(exception); - } - } - } - else { + if (targetMethod.getManager().isInProject(targetMethod)) { PsiMethod[] superMethods = targetMethod.findSuperMethods(); for (PsiMethod superMethod : superMethods) { Set classTypes = filterInProjectExceptions(superMethod, unhandledExceptions); @@ -217,6 +210,16 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction { result.addAll(unhandledExceptions); } } + else { + PsiClassType[] referencedTypes = targetMethod.getThrowsList().getReferencedTypes(); + for (PsiClassType referencedType : referencedTypes) { + PsiClass psiClass = referencedType.resolve(); + if (psiClass == null) continue; + for (PsiClassType exception : unhandledExceptions) { + if (referencedType.isAssignableFrom(exception)) result.add(exception); + } + } + } return result; } diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index 8afb087bed1f..a6f6ba762f61 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -51,7 +51,7 @@ public final class PsiUtil extends PsiUtilCore { private PsiUtil() {} - public static boolean isOnAssignmentLeftHand(PsiExpression expr) { + public static boolean isOnAssignmentLeftHand(@NotNull PsiExpression expr) { PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, PsiParenthesizedExpression.class); return parent instanceof PsiAssignmentExpression && PsiTreeUtil.isAncestor(((PsiAssignmentExpression)parent).getLExpression(), expr, false); @@ -63,7 +63,7 @@ public final class PsiUtil extends PsiUtilCore { JavaPsiFacade.getInstance(element.getProject()).isInPackage(element, aPackage); } - public static boolean isAccessedForWriting(PsiExpression expr) { + public static boolean isAccessedForWriting(@NotNull PsiExpression expr) { if (isOnAssignmentLeftHand(expr)) return true; PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, PsiParenthesizedExpression.class); if (parent instanceof PsiPrefixExpression) { @@ -79,19 +79,19 @@ public final class PsiUtil extends PsiUtilCore { } } - public static boolean isAccessedForReading(PsiExpression expr) { + public static boolean isAccessedForReading(@NotNull PsiExpression expr) { PsiElement parent = PsiTreeUtil.skipParentsOfType(expr, PsiParenthesizedExpression.class); return !(parent instanceof PsiAssignmentExpression) || !PsiTreeUtil.isAncestor(((PsiAssignmentExpression)parent).getLExpression(), expr, false) || ((PsiAssignmentExpression)parent).getOperationTokenType() != JavaTokenType.EQ; } - public static boolean isAccessible(PsiMember member, @NotNull PsiElement place, @Nullable PsiClass accessObjectClass) { + public static boolean isAccessible(@NotNull PsiMember member, @NotNull PsiElement place, @Nullable PsiClass accessObjectClass) { return JavaPsiFacade.getInstance(place.getProject()).getResolveHelper().isAccessible(member, place, accessObjectClass); } @NotNull - public static JavaResolveResult getAccessObjectClass(PsiExpression expression) { + public static JavaResolveResult getAccessObjectClass(@NotNull PsiExpression expression) { if (expression instanceof PsiSuperExpression || expression instanceof PsiThisExpression) return JavaResolveResult.EMPTY; PsiType type = expression.getType(); if (type instanceof PsiClassType) { @@ -112,7 +112,7 @@ public final class PsiUtil extends PsiUtilCore { return JavaResolveResult.EMPTY; } - public static boolean isConstantExpression(PsiExpression expression) { + public static boolean isConstantExpression(@Nullable PsiExpression expression) { if (expression == null) return false; IsConstantExpressionVisitor visitor = new IsConstantExpressionVisitor(); expression.accept(visitor); @@ -120,23 +120,31 @@ public final class PsiUtil extends PsiUtilCore { } // todo: move to PsiThrowsList? - public static void addException(PsiMethod method, @NonNls String exceptionFQName) throws IncorrectOperationException { + public static void addException(@NotNull PsiMethod method, @NotNull @NonNls String exceptionFQName) throws IncorrectOperationException { PsiClass exceptionClass = JavaPsiFacade.getInstance(method.getProject()).findClass(exceptionFQName, method.getResolveScope()); addException(method, exceptionClass, exceptionFQName); } - public static void addException(PsiMethod method, PsiClass exceptionClass) throws IncorrectOperationException { + public static void addException(@NotNull PsiMethod method, @NotNull PsiClass exceptionClass) throws IncorrectOperationException { addException(method, exceptionClass, exceptionClass.getQualifiedName()); } - private static void addException(PsiMethod method, PsiClass exceptionClass, String exceptionName) throws IncorrectOperationException { + private static void addException(@NotNull PsiMethod method, @Nullable PsiClass exceptionClass, @Nullable String exceptionName) throws IncorrectOperationException { + assert exceptionClass != null || exceptionName != null : "One of exceptionName, exceptionClass must be not null"; PsiReferenceList throwsList = method.getThrowsList(); PsiJavaCodeReferenceElement[] refs = throwsList.getReferenceElements(); + boolean replaced = false; for (PsiJavaCodeReferenceElement ref : refs) { if (ref.isReferenceTo(exceptionClass)) return; PsiClass aClass = (PsiClass)ref.resolve(); - if (exceptionClass != null && aClass != null) { - if (aClass.isInheritor(exceptionClass, true)) { + if (exceptionClass == null || aClass == null) { + continue; + } + if (aClass.isInheritor(exceptionClass, true)) { + if (replaced) { + ref.delete(); + } + else { PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); PsiJavaCodeReferenceElement ref1; if (exceptionName != null) { @@ -147,13 +155,14 @@ public final class PsiUtil extends PsiUtilCore { ref1 = factory.createReferenceElementByType(type); } ref.replace(ref1); - return; - } - else if (exceptionClass.isInheritor(aClass, true)) { - return; + replaced = true; } } + else if (exceptionClass.isInheritor(aClass, true)) { + return; + } } + if (replaced) return; PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); PsiJavaCodeReferenceElement ref; @@ -168,7 +177,7 @@ public final class PsiUtil extends PsiUtilCore { } // todo: move to PsiThrowsList? - public static void removeException(PsiMethod method, @NonNls String exceptionClass) throws IncorrectOperationException { + public static void removeException(@NotNull PsiMethod method, @NonNls String exceptionClass) throws IncorrectOperationException { PsiJavaCodeReferenceElement[] refs = method.getThrowsList().getReferenceElements(); for (PsiJavaCodeReferenceElement ref : refs) { if (ref.getCanonicalText().equals(exceptionClass)) { @@ -185,7 +194,8 @@ public final class PsiUtil extends PsiUtilCore { /** * @return enclosing outermost (method or class initializer) body but not higher than scope */ - public static PsiElement getTopLevelEnclosingCodeBlock(PsiElement element, PsiElement scope) { + @Nullable + public static PsiElement getTopLevelEnclosingCodeBlock(@Nullable PsiElement element, PsiElement scope) { PsiElement blockSoFar = null; while (element != null) { // variable can be defined in for loop initializer @@ -219,16 +229,16 @@ public final class PsiUtil extends PsiUtilCore { return blockSoFar; } - public static boolean isLocalOrAnonymousClass(PsiClass psiClass) { + public static boolean isLocalOrAnonymousClass(@NotNull PsiClass psiClass) { return psiClass instanceof PsiAnonymousClass || isLocalClass(psiClass); } - public static boolean isLocalClass(PsiClass psiClass) { + public static boolean isLocalClass(@NotNull PsiClass psiClass) { PsiElement parent = psiClass.getParent(); return parent instanceof PsiDeclarationStatement && parent.getParent() instanceof PsiCodeBlock; } - public static boolean isAbstractClass(PsiClass clazz) { + public static boolean isAbstractClass(@NotNull PsiClass clazz) { PsiModifierList modifierList = clazz.getModifierList(); return modifierList != null && modifierList.hasModifierProperty(PsiModifier.ABSTRACT); } @@ -237,7 +247,7 @@ public final class PsiUtil extends PsiUtilCore { * @return topmost code block where variable makes sense */ @Nullable - public static PsiElement getVariableCodeBlock(PsiVariable variable, PsiElement context) { + public static PsiElement getVariableCodeBlock(@NotNull PsiVariable variable, @Nullable PsiElement context) { PsiElement codeBlock = null; if (variable instanceof PsiParameter) { PsiElement declarationScope = ((PsiParameter)variable).getDeclarationScope(); @@ -276,7 +286,7 @@ public final class PsiUtil extends PsiUtilCore { return codeBlock; } - public static boolean isIncrementDecrementOperation(PsiElement element) { + public static boolean isIncrementDecrementOperation(@NotNull PsiElement element) { if (element instanceof PsiPostfixExpression) { final IElementType sign = ((PsiPostfixExpression)element).getOperationTokenType(); if (sign == JavaTokenType.PLUSPLUS || sign == JavaTokenType.MINUSMINUS) @@ -318,7 +328,7 @@ public final class PsiUtil extends PsiUtilCore { /** * @return true if element specified is statement or expression statement. see JLS 14.5-14.8 */ - public static boolean isStatement(PsiElement element) { + public static boolean isStatement(@NotNull PsiElement element) { PsiElement parent = element.getParent(); if (element instanceof PsiExpressionListStatement) { @@ -366,7 +376,7 @@ public final class PsiUtil extends PsiUtilCore { @Nullable - public static PsiElement getElementInclusiveRange(PsiElement scope, TextRange range) { + public static PsiElement getElementInclusiveRange(@NotNull PsiElement scope, @NotNull TextRange range) { PsiElement psiElement = scope.findElementAt(range.getStartOffset()); while (psiElement != null && !psiElement.getTextRange().contains(range)) { if (psiElement == scope) return null; @@ -414,7 +424,8 @@ public final class PsiUtil extends PsiUtilCore { return PsiClassType.ClassResolveResult.EMPTY; } - public static PsiType convertAnonymousToBaseType(PsiType type) { + @NotNull + public static PsiType convertAnonymousToBaseType(@NotNull PsiType type) { PsiClass psiClass = resolveClassInType(type); if (psiClass instanceof PsiAnonymousClass) { int dims = type.getArrayDimensions(); @@ -427,17 +438,17 @@ public final class PsiUtil extends PsiUtilCore { return type; } - public static boolean isApplicable(PsiMethod method, PsiSubstitutor substitutorForMethod, PsiExpressionList argList) { + public static boolean isApplicable(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutorForMethod, @NotNull PsiExpressionList argList) { return getApplicabilityLevel(method, substitutorForMethod, argList) != ApplicabilityLevel.NOT_APPLICABLE; } - public static boolean isApplicable(PsiMethod method, PsiSubstitutor substitutorForMethod, PsiExpression[] argList) { + public static boolean isApplicable(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutorForMethod, @NotNull PsiExpression[] argList) { final PsiType[] types = ContainerUtil.map2Array(argList, PsiType.class, PsiExpression.EXPRESSION_TO_TYPE); return getApplicabilityLevel(method, substitutorForMethod, types, getLanguageLevel(method)) != ApplicabilityLevel.NOT_APPLICABLE; } @MethodCandidateInfo.ApplicabilityLevelConstant - public static int getApplicabilityLevel(PsiMethod method, PsiSubstitutor substitutorForMethod, PsiExpressionList argList) { + public static int getApplicabilityLevel(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutorForMethod, @NotNull PsiExpressionList argList) { return getApplicabilityLevel(method, substitutorForMethod, argList.getExpressionTypes(), getLanguageLevel(argList)); } @@ -476,9 +487,10 @@ public final class PsiUtil extends PsiUtilCore { return ApplicabilityLevel.NOT_APPLICABLE; } - private static boolean areFirstArgumentsApplicable(final PsiType[] args, final PsiParameter[] parms, final LanguageLevel languageLevel, - @NotNull final PsiSubstitutor substitutorForMethod) { - + private static boolean areFirstArgumentsApplicable(@NotNull PsiType[] args, + @NotNull final PsiParameter[] parms, + @NotNull LanguageLevel languageLevel, + @NotNull final PsiSubstitutor substitutorForMethod) { for (int i = 0; i < parms.length - 1; i++) { final PsiType type = args[i]; if (type == null) return false; @@ -491,9 +503,9 @@ public final class PsiUtil extends PsiUtilCore { return true; } - private static PsiType getParameterType(final PsiParameter parameter, - final LanguageLevel languageLevel, - @NotNull final PsiSubstitutor substitutor) { + private static PsiType getParameterType(@NotNull final PsiParameter parameter, + @NotNull LanguageLevel languageLevel, + @NotNull final PsiSubstitutor substitutor) { PsiType parmType = parameter.getType(); if (parmType instanceof PsiClassType) { parmType = ((PsiClassType)parmType).setLanguageLevel(languageLevel); @@ -501,11 +513,11 @@ public final class PsiUtil extends PsiUtilCore { return substitutor.substitute(parmType); } - public static boolean equalOnClass(PsiSubstitutor s1, PsiSubstitutor s2, PsiClass aClass) { + public static boolean equalOnClass(@NotNull PsiSubstitutor s1, @NotNull PsiSubstitutor s2, @NotNull PsiClass aClass) { return equalOnEquivalentClasses(s1, aClass, s2, aClass); } - public static boolean equalOnEquivalentClasses(PsiSubstitutor s1, PsiClass aClass, PsiSubstitutor s2, PsiClass bClass) { + public static boolean equalOnEquivalentClasses(@NotNull PsiSubstitutor s1, @NotNull PsiClass aClass, @NotNull PsiSubstitutor s2, @NotNull PsiClass bClass) { // assume generic class equals to non-generic if (aClass.hasTypeParameters() != bClass.hasTypeParameters()) return true; final PsiTypeParameter[] typeParameters1 = aClass.getTypeParameters(); @@ -530,14 +542,14 @@ public final class PsiUtil extends PsiUtilCore { /** * JLS 15.28 */ - public static boolean isCompileTimeConstant(final PsiField field) { + public static boolean isCompileTimeConstant(@NotNull final PsiField field) { return field.hasModifierProperty(PsiModifier.FINAL) && (TypeConversionUtil.isPrimitiveAndNotNull(field.getType()) || field.getType().equalsToText("java.lang.String")) && field.hasInitializer() && isConstantExpression(field.getInitializer()); } - public static boolean allMethodsHaveSameSignature(PsiMethod[] methods) { + public static boolean allMethodsHaveSameSignature(@NotNull PsiMethod[] methods) { if (methods.length == 0) return true; final MethodSignature methodSignature = methods[0].getSignature(PsiSubstitutor.EMPTY); for (int i = 1; i < methods.length; i++) { @@ -566,7 +578,7 @@ public final class PsiUtil extends PsiUtilCore { * Checks whether given class is inner (as opposed to nested) * */ - public static boolean isInnerClass(PsiClass aClass) { + public static boolean isInnerClass(@NotNull PsiClass aClass) { return !aClass.hasModifierProperty(PsiModifier.STATIC) && aClass.getContainingClass() != null; } @@ -597,7 +609,7 @@ public final class PsiUtil extends PsiUtilCore { * @return element with static modifier enclosing place and enclosed by aClass (if not null) */ @Nullable - public static PsiModifierListOwner getEnclosingStaticElement(PsiElement place, @Nullable PsiClass aClass) { + public static PsiModifierListOwner getEnclosingStaticElement(@NotNull PsiElement place, @Nullable PsiClass aClass) { LOG.assertTrue(aClass == null || !place.isPhysical() || PsiTreeUtil.isContextAncestor(aClass, place, false)); PsiElement parent = place; while (parent != aClass) { @@ -611,7 +623,7 @@ public final class PsiUtil extends PsiUtilCore { } @Nullable - public static PsiType getTypeByPsiElement(final PsiElement element) { + public static PsiType getTypeByPsiElement(@NotNull final PsiElement element) { if (element instanceof PsiVariable) { return ((PsiVariable)element).getType(); } @@ -619,7 +631,8 @@ public final class PsiUtil extends PsiUtilCore { return null; } - public static PsiType captureToplevelWildcards(final PsiType type, final PsiElement context) { + @NotNull + public static PsiType captureToplevelWildcards(@NotNull final PsiType type, final PsiElement context) { if (type instanceof PsiClassType) { final PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics(); final PsiClass aClass = result.getElement(); @@ -660,14 +673,14 @@ public final class PsiUtil extends PsiUtilCore { : Collections.singletonList(typeElement); } - public static void checkIsIdentifier(PsiManager manager, String text) throws IncorrectOperationException{ + public static void checkIsIdentifier(@NotNull PsiManager manager, String text) throws IncorrectOperationException{ if (!JavaPsiFacade.getInstance(manager.getProject()).getNameHelper().isIdentifier(text)){ throw new IncorrectOperationException(PsiBundle.message("0.is.not.an.identifier", text) ); } } @Nullable - public static VirtualFile getJarFile(PsiElement candidate) { + public static VirtualFile getJarFile(@NotNull PsiElement candidate) { VirtualFile file = candidate.getContainingFile().getVirtualFile(); if (file != null && file.getFileSystem().getProtocol().equals("jar")) { return VfsUtilCore.getVirtualFileForJar(file); @@ -683,13 +696,13 @@ public final class PsiUtil extends PsiUtilCore { private PsiTypeParameter myNext; - private TypeParameterIterator(PsiTypeParameterListOwner owner) { + private TypeParameterIterator(@NotNull PsiTypeParameterListOwner owner) { myCurrentOwner = owner; obtainCurrentParams(owner); myNextObtained = false; } - private void obtainCurrentParams(PsiTypeParameterListOwner owner) { + private void obtainCurrentParams(@NotNull PsiTypeParameterListOwner owner) { myCurrentParams = owner.getTypeParameters(); myIndex = myCurrentParams.length - 1; } @@ -736,11 +749,14 @@ public final class PsiUtil extends PsiUtilCore { * Returns iterator of type parameters visible in owner. Type parameters are iterated in * inner-to-outer, right-to-left order. */ + @NotNull public static Iterator typeParametersIterator(@NotNull PsiTypeParameterListOwner owner) { return new TypeParameterIterator(owner); } + @NotNull public static Iterable typeParametersIterable(@NotNull final PsiTypeParameterListOwner owner) { return new Iterable() { + @NotNull @Override public Iterator iterator() { return typeParametersIterator(owner); @@ -748,7 +764,7 @@ public final class PsiUtil extends PsiUtilCore { }; } - public static boolean canBeOverriden(PsiMethod method) { + public static boolean canBeOverriden(@NotNull PsiMethod method) { PsiClass parentClass = method.getContainingClass(); return parentClass != null && !method.isConstructor() && @@ -759,7 +775,8 @@ public final class PsiUtil extends PsiUtilCore { !parentClass.hasModifierProperty(PsiModifier.FINAL); } - public static PsiElement[] mapElements(ResolveResult[] candidates) { + @NotNull + public static PsiElement[] mapElements(@NotNull ResolveResult[] candidates) { PsiElement[] result = new PsiElement[candidates.length]; for (int i = 0; i < candidates.length; i++) { result[i] = candidates[i].getElement(); @@ -774,7 +791,7 @@ public final class PsiUtil extends PsiUtilCore { return parent; } - public static boolean checkName(PsiElement element, String name, final PsiElement context) { + public static boolean checkName(@NotNull PsiElement element, @NotNull String name, final PsiElement context) { if (element instanceof PsiMetaOwner) { final PsiMetaData data = ((PsiMetaOwner) element).getMetaData(); if (data != null) return name.equals(data.getName(context)); @@ -782,7 +799,7 @@ public final class PsiUtil extends PsiUtilCore { return element instanceof PsiNamedElement && name.equals(((PsiNamedElement)element).getName()); } - public static boolean isRawSubstitutor (@NotNull PsiTypeParameterListOwner owner, PsiSubstitutor substitutor) { + public static boolean isRawSubstitutor (@NotNull PsiTypeParameterListOwner owner, @NotNull PsiSubstitutor substitutor) { for (PsiTypeParameter parameter : typeParametersIterable(owner)) { if (substitutor.substitute(parameter) == null) return true; } @@ -824,25 +841,25 @@ public final class PsiUtil extends PsiUtilCore { return ((PsiJavaFile)file).getLanguageLevel(); } - public static boolean isInstantiatable(PsiClass clazz) { + public static boolean isInstantiatable(@NotNull PsiClass clazz) { return !clazz.hasModifierProperty(PsiModifier.ABSTRACT) && clazz.hasModifierProperty(PsiModifier.PUBLIC) && hasDefaultConstructor(clazz); } - public static boolean hasDefaultConstructor(PsiClass clazz) { + public static boolean hasDefaultConstructor(@NotNull PsiClass clazz) { return hasDefaultConstructor(clazz, false); } - public static boolean hasDefaultConstructor(PsiClass clazz, boolean allowProtected) { + public static boolean hasDefaultConstructor(@NotNull PsiClass clazz, boolean allowProtected) { return hasDefaultConstructor(clazz, allowProtected, true); } - public static boolean hasDefaultConstructor(PsiClass clazz, boolean allowProtected, boolean checkModifiers) { + public static boolean hasDefaultConstructor(@NotNull PsiClass clazz, boolean allowProtected, boolean checkModifiers) { return hasDefaultCtrInHierarchy(clazz, allowProtected, checkModifiers, null); } - private static boolean hasDefaultCtrInHierarchy(PsiClass clazz, boolean allowProtected, boolean checkModifiers, @Nullable Set visited) { + private static boolean hasDefaultCtrInHierarchy(@NotNull PsiClass clazz, boolean allowProtected, boolean checkModifiers, @Nullable Set visited) { final PsiMethod[] constructors = clazz.getConstructors(); if (constructors.length > 0) { for (PsiMethod cls: constructors) { @@ -872,7 +889,7 @@ public final class PsiUtil extends PsiUtilCore { } @Nullable - public static PsiType substituteTypeParameter(@Nullable final PsiType psiType, final String superClass, final int typeParamIndex, + public static PsiType substituteTypeParameter(@Nullable final PsiType psiType, @NotNull final String superClass, final int typeParamIndex, final boolean eraseTypeParameter) { if (psiType == null) return null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after1.java index 931fc0277860..76c72d6ff754 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after1.java @@ -1,4 +1,4 @@ -// "Add Exception(s) to Method Signature" "true" +// "Add Exception to Method Signature" "true" class C { static class E1 extends Exception { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after2.java index 4ca3d57ad052..a1a2e93021cd 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/after2.java @@ -1,4 +1,4 @@ -// "Add Exception(s) to Method Signature" "true" +// "Add Exception to Method Signature" "true" class C { static class E1 extends Exception { } static class E2 extends Exception { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/afterMultiple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/afterMultiple.java new file mode 100644 index 000000000000..790159f28287 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/afterMultiple.java @@ -0,0 +1,11 @@ +// "Add Exception to Method Signature" "true" +import java.io.*; + +class C { + String detectEncoding(File inputFile) throws IOException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8")); + final String line = reader.readLine(); + + return "ISO-8859-1"; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before1.java index e3bfa8c80d58..8555c0e7e9b9 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before1.java @@ -1,4 +1,4 @@ -// "Add Exception(s) to Method Signature" "true" +// "Add Exception to Method Signature" "true" class C { static class E1 extends Exception { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before2.java index 623e28bbdba2..c3c30fe62eee 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/before2.java @@ -1,4 +1,4 @@ -// "Add Exception(s) to Method Signature" "true" +// "Add Exception to Method Signature" "true" class C { static class E1 extends Exception { } static class E2 extends Exception { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/beforeMultiple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/beforeMultiple.java new file mode 100644 index 000000000000..7502ecbed3ad --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addToThrows/beforeMultiple.java @@ -0,0 +1,11 @@ +// "Add Exception to Method Signature" "true" +import java.io.*; + +class C { + String detectEncoding(File inputFile) throws FileNotFoundException, ObjectStreamException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "UTF-8")); + final String line = reader.readLine(); + + return "ISO-8859-1"; + } +} diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index 504731f4d002..d951b419d983 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -9,7 +9,7 @@ add.catch.clause.text=Add Catch Clause(s) add.exception.to.throws.inherited.method.warning.text=Method ''{0}'' is inherited.\n\ Do you want to add exceptions to method signatures in the whole method hierarchy? method.is.inherited.warning.title=Method Is Inherited -add.exception.to.throws.text=Add Exception(s) to Method Signature +add.exception.to.throws.text=Add {0, choice, 0#Exception|2#Exceptions} to Method Signature add.exception.to.throws.family=Add Exception to Method Signature add.method.body.text=Add Method Body add.method.family=Add Method