mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-04 04:09:09 +07:00
[java-inspections] UnreachableCatchInspection extracted from highlighter
Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: b2e389aa89d75c63969a3884a495b3771d2712b2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4b94cd67e6
commit
9dbf2ace73
@@ -114,7 +114,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
|||||||
public void visitTryStatement(@NotNull PsiTryStatement statement) {
|
public void visitTryStatement(@NotNull PsiTryStatement statement) {
|
||||||
super.visitTryStatement(statement);
|
super.visitTryStatement(statement);
|
||||||
if (!hasErrorResults()) {
|
if (!hasErrorResults()) {
|
||||||
UnhandledExceptions thrownTypes = collectUnhandledExceptions(statement);
|
UnhandledExceptions thrownTypes = UnhandledExceptions.fromTryStatement(statement);
|
||||||
if (thrownTypes.hasUnresolvedCalls()) return;
|
if (thrownTypes.hasUnresolvedCalls()) return;
|
||||||
for (PsiParameter parameter : statement.getCatchBlockParameters()) {
|
for (PsiParameter parameter : statement.getCatchBlockParameters()) {
|
||||||
myStatementChecker.checkExceptionAlreadyCaught(parameter);
|
myStatementChecker.checkExceptionAlreadyCaught(parameter);
|
||||||
@@ -841,22 +841,6 @@ final class JavaErrorVisitor extends JavaElementVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NotNull UnhandledExceptions collectUnhandledExceptions(@NotNull PsiTryStatement statement) {
|
|
||||||
UnhandledExceptions thrownTypes = UnhandledExceptions.EMPTY;
|
|
||||||
|
|
||||||
PsiCodeBlock tryBlock = statement.getTryBlock();
|
|
||||||
if (tryBlock != null) {
|
|
||||||
thrownTypes = thrownTypes.merge(UnhandledExceptions.collect(tryBlock));
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiResourceList resources = statement.getResourceList();
|
|
||||||
if (resources != null) {
|
|
||||||
thrownTypes = thrownTypes.merge(UnhandledExceptions.collect(resources));
|
|
||||||
}
|
|
||||||
|
|
||||||
return thrownTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkFeature(@NotNull PsiElement element, @NotNull JavaFeature feature) {
|
void checkFeature(@NotNull PsiElement element, @NotNull JavaFeature feature) {
|
||||||
if (!feature.isSufficient(myLanguageLevel)) {
|
if (!feature.isSufficient(myLanguageLevel)) {
|
||||||
report(JavaErrorKinds.UNSUPPORTED_FEATURE.create(element, feature));
|
report(JavaErrorKinds.UNSUPPORTED_FEATURE.create(element, feature));
|
||||||
|
|||||||
@@ -613,4 +613,6 @@ intention.name.do.not.report.conditions.with.possible.side.effect=Do not report
|
|||||||
dfa.find.cause.or.another=or {0}
|
dfa.find.cause.or.another=or {0}
|
||||||
dfa.find.cause.and.another=and {0}
|
dfa.find.cause.and.another=and {0}
|
||||||
safe.varargs.not.suppress.potentially.unsafe.operations=@SafeVarargs do not suppress potentially unsafe operations
|
safe.varargs.not.suppress.potentially.unsafe.operations=@SafeVarargs do not suppress potentially unsafe operations
|
||||||
safe.varargs.on.reifiable.type=@SafeVarargs is not applicable for reifiable types
|
safe.varargs.on.reifiable.type=@SafeVarargs is not applicable for reifiable types
|
||||||
|
inspection.unreachable.catch.name=Unreachable catch section
|
||||||
|
inspection.unreachable.catch.message=Unreachable section: {1, choice, 0#exception|2#exceptions} ''{0}'' {1, choice, 0#has|2#have} already been caught
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||||
|
|
||||||
import com.intellij.codeInsight.ContainerProvider;
|
import com.intellij.codeInsight.ContainerProvider;
|
||||||
import com.intellij.codeInsight.ExceptionUtil;
|
|
||||||
import com.intellij.codeInsight.JavaModuleSystemEx;
|
import com.intellij.codeInsight.JavaModuleSystemEx;
|
||||||
import com.intellij.codeInsight.JavaModuleSystemEx.ErrorWithFixes;
|
import com.intellij.codeInsight.JavaModuleSystemEx.ErrorWithFixes;
|
||||||
import com.intellij.codeInsight.UnhandledExceptions;
|
|
||||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||||
@@ -49,7 +47,6 @@ import com.intellij.psi.tree.IElementType;
|
|||||||
import com.intellij.psi.util.*;
|
import com.intellij.psi.util.*;
|
||||||
import com.intellij.ui.ColorUtil;
|
import com.intellij.ui.ColorUtil;
|
||||||
import com.intellij.ui.NewUI;
|
import com.intellij.ui.NewUI;
|
||||||
import com.intellij.util.ArrayUtilRt;
|
|
||||||
import com.intellij.util.JavaPsiConstructorUtil;
|
import com.intellij.util.JavaPsiConstructorUtil;
|
||||||
import com.intellij.util.ObjectUtils;
|
import com.intellij.util.ObjectUtils;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
@@ -637,81 +634,6 @@ public final class HighlightUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static @NotNull UnhandledExceptions collectUnhandledExceptions(@NotNull PsiTryStatement statement) {
|
|
||||||
UnhandledExceptions thrownTypes = UnhandledExceptions.EMPTY;
|
|
||||||
|
|
||||||
PsiCodeBlock tryBlock = statement.getTryBlock();
|
|
||||||
if (tryBlock != null) {
|
|
||||||
thrownTypes = thrownTypes.merge(UnhandledExceptions.collect(tryBlock));
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiResourceList resources = statement.getResourceList();
|
|
||||||
if (resources != null) {
|
|
||||||
thrownTypes = thrownTypes.merge(UnhandledExceptions.collect(resources));
|
|
||||||
}
|
|
||||||
|
|
||||||
return thrownTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void checkWithImprovedCatchAnalysis(@NotNull PsiParameter parameter,
|
|
||||||
@NotNull Collection<? extends PsiClassType> thrownInTryStatement,
|
|
||||||
@NotNull PsiFile containingFile, @NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
|
||||||
PsiElement scope = parameter.getDeclarationScope();
|
|
||||||
if (!(scope instanceof PsiCatchSection catchSection)) return;
|
|
||||||
|
|
||||||
PsiCatchSection[] allCatchSections = catchSection.getTryStatement().getCatchSections();
|
|
||||||
int idx = ArrayUtilRt.find(allCatchSections, catchSection);
|
|
||||||
if (idx <= 0) return;
|
|
||||||
|
|
||||||
Collection<PsiClassType> thrownTypes = new HashSet<>(thrownInTryStatement);
|
|
||||||
PsiManager manager = containingFile.getManager();
|
|
||||||
GlobalSearchScope parameterResolveScope = parameter.getResolveScope();
|
|
||||||
thrownTypes.add(PsiType.getJavaLangError(manager, parameterResolveScope));
|
|
||||||
thrownTypes.add(PsiType.getJavaLangRuntimeException(manager, parameterResolveScope));
|
|
||||||
|
|
||||||
List<PsiTypeElement> parameterTypeElements = PsiUtil.getParameterTypeElements(parameter);
|
|
||||||
boolean isMultiCatch = parameterTypeElements.size() > 1;
|
|
||||||
for (PsiTypeElement catchTypeElement : parameterTypeElements) {
|
|
||||||
PsiType catchType = catchTypeElement.getType();
|
|
||||||
if (ExceptionUtil.isGeneralExceptionType(catchType)) continue;
|
|
||||||
|
|
||||||
// collect exceptions caught by this type
|
|
||||||
List<PsiClassType> caught = new ArrayList<>();
|
|
||||||
for (PsiClassType t : thrownTypes) {
|
|
||||||
if (catchType.isAssignableFrom(t) || t.isAssignableFrom(catchType)) {
|
|
||||||
caught.add(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (caught.isEmpty()) continue;
|
|
||||||
Collection<PsiClassType> caughtCopy = new HashSet<>(caught);
|
|
||||||
|
|
||||||
// exclude all caught by previous catch sections
|
|
||||||
for (int i = 0; i < idx; i++) {
|
|
||||||
PsiParameter prevCatchParameter = allCatchSections[i].getParameter();
|
|
||||||
if (prevCatchParameter == null) continue;
|
|
||||||
for (PsiTypeElement prevCatchTypeElement : PsiUtil.getParameterTypeElements(prevCatchParameter)) {
|
|
||||||
PsiType prevCatchType = prevCatchTypeElement.getType();
|
|
||||||
caught.removeIf(prevCatchType::isAssignableFrom);
|
|
||||||
if (caught.isEmpty()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check & warn
|
|
||||||
if (caught.isEmpty()) {
|
|
||||||
String message = JavaErrorBundle.message("exception.already.caught.warn", formatTypes(caughtCopy), caughtCopy.size());
|
|
||||||
HighlightInfo.Builder builder =
|
|
||||||
HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(catchSection).descriptionAndTooltip(message);
|
|
||||||
IntentionAction action = isMultiCatch ?
|
|
||||||
getFixFactory().createDeleteMultiCatchFix(catchTypeElement) :
|
|
||||||
getFixFactory().createDeleteCatchFix(parameter);
|
|
||||||
builder.registerFix(action, null, null, null, null);
|
|
||||||
errorSink.accept(builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static HighlightInfo.Builder checkNotAStatement(@NotNull PsiStatement statement) {
|
static HighlightInfo.Builder checkNotAStatement(@NotNull PsiStatement statement) {
|
||||||
if (PsiUtil.isStatement(statement)) {
|
if (PsiUtil.isStatement(statement)) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||||
|
|
||||||
import com.intellij.codeInsight.UnhandledExceptions;
|
|
||||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||||
import com.intellij.codeInsight.daemon.impl.DefaultHighlightUtil;
|
import com.intellij.codeInsight.daemon.impl.DefaultHighlightUtil;
|
||||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||||
@@ -1170,20 +1169,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitTryStatement(@NotNull PsiTryStatement statement) {
|
|
||||||
super.visitTryStatement(statement);
|
|
||||||
if (!hasErrorResults()) {
|
|
||||||
UnhandledExceptions thrownTypes = HighlightUtil.collectUnhandledExceptions(statement);
|
|
||||||
if (thrownTypes.hasUnresolvedCalls()) return;
|
|
||||||
for (PsiParameter parameter : statement.getCatchBlockParameters()) {
|
|
||||||
if (!hasErrorResults()) {
|
|
||||||
HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes.exceptions(), myFile, myErrorSink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitResourceExpression(@NotNull PsiResourceExpression resource) {
|
public void visitResourceExpression(@NotNull PsiResourceExpression resource) {
|
||||||
super.visitResourceExpression(resource);
|
super.visitResourceExpression(resource);
|
||||||
|
|||||||
@@ -1972,6 +1972,11 @@
|
|||||||
level="INFORMATION"
|
level="INFORMATION"
|
||||||
implementationClass="com.intellij.codeInspection.streamToLoop.StreamToLoopInspection"
|
implementationClass="com.intellij.codeInspection.streamToLoop.StreamToLoopInspection"
|
||||||
key="inspection.stream.to.loop.display.name" bundle="messages.JavaBundle"/>
|
key="inspection.stream.to.loop.display.name" bundle="messages.JavaBundle"/>
|
||||||
|
<localInspection groupPath="Java" language="JAVA" shortName="UnreachableCatch"
|
||||||
|
groupKey="group.names.verbose.or.redundant.code.constructs" groupBundle="messages.InspectionsBundle"
|
||||||
|
enabledByDefault="true" level="WARNING"
|
||||||
|
implementationClass="com.intellij.codeInspection.deadCode.UnreachableCatchInspection"
|
||||||
|
key="inspection.unreachable.catch.name" bundle="messages.JavaAnalysisBundle"/>
|
||||||
<localInspection groupPath="Java" language="JAVA" shortName="OptionalToIf"
|
<localInspection groupPath="Java" language="JAVA" shortName="OptionalToIf"
|
||||||
groupKey="group.names.code.style.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="true"
|
groupKey="group.names.code.style.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="true"
|
||||||
level="INFORMATION"
|
level="INFORMATION"
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
|
package com.intellij.codeInspection.deadCode;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.ExceptionUtil;
|
||||||
|
import com.intellij.codeInsight.UnhandledExceptions;
|
||||||
|
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
|
||||||
|
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteCatchFix;
|
||||||
|
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteMultiCatchFix;
|
||||||
|
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder;
|
||||||
|
import com.intellij.ide.nls.NlsMessages;
|
||||||
|
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||||
|
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
|
||||||
|
import com.intellij.modcommand.ModCommandAction;
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
|
import com.intellij.psi.util.PsiUtil;
|
||||||
|
import com.intellij.util.ArrayUtilRt;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class UnreachableCatchInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||||
|
@Override
|
||||||
|
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||||
|
return new JavaElementVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitTryStatement(@NotNull PsiTryStatement statement) {
|
||||||
|
UnhandledExceptions thrownTypes = UnhandledExceptions.fromTryStatement(statement);
|
||||||
|
if (thrownTypes.hasUnresolvedCalls()) return;
|
||||||
|
for (PsiParameter parameter : statement.getCatchBlockParameters()) {
|
||||||
|
checkWithImprovedCatchAnalysis(statement, parameter, thrownTypes.exceptions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkWithImprovedCatchAnalysis(@NotNull PsiTryStatement statement, @NotNull PsiParameter parameter,
|
||||||
|
@NotNull Collection<? extends PsiClassType> thrownInTryStatement) {
|
||||||
|
PsiElement scope = parameter.getDeclarationScope();
|
||||||
|
if (!(scope instanceof PsiCatchSection catchSection)) return;
|
||||||
|
|
||||||
|
PsiCatchSection[] allCatchSections = catchSection.getTryStatement().getCatchSections();
|
||||||
|
int idx = ArrayUtilRt.find(allCatchSections, catchSection);
|
||||||
|
if (idx <= 0) return;
|
||||||
|
|
||||||
|
Collection<PsiClassType> thrownTypes = new HashSet<>(thrownInTryStatement);
|
||||||
|
PsiManager manager = holder.getFile().getManager();
|
||||||
|
GlobalSearchScope parameterResolveScope = parameter.getResolveScope();
|
||||||
|
thrownTypes.add(PsiType.getJavaLangError(manager, parameterResolveScope));
|
||||||
|
thrownTypes.add(PsiType.getJavaLangRuntimeException(manager, parameterResolveScope));
|
||||||
|
|
||||||
|
List<PsiTypeElement> parameterTypeElements = PsiUtil.getParameterTypeElements(parameter);
|
||||||
|
boolean isMultiCatch = parameterTypeElements.size() > 1;
|
||||||
|
for (PsiTypeElement catchTypeElement : parameterTypeElements) {
|
||||||
|
PsiType catchType = catchTypeElement.getType();
|
||||||
|
if (ExceptionUtil.isGeneralExceptionType(catchType)) continue;
|
||||||
|
|
||||||
|
// collect exceptions caught by this type
|
||||||
|
List<PsiClassType> caught = new ArrayList<>();
|
||||||
|
for (PsiClassType t : thrownTypes) {
|
||||||
|
if (catchType.isAssignableFrom(t) || t.isAssignableFrom(catchType)) {
|
||||||
|
caught.add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (caught.isEmpty()) continue;
|
||||||
|
Collection<PsiClassType> caughtCopy = new HashSet<>(caught);
|
||||||
|
|
||||||
|
// exclude all caught by previous catch sections
|
||||||
|
for (int i = 0; i < idx; i++) {
|
||||||
|
PsiParameter prevCatchParameter = allCatchSections[i].getParameter();
|
||||||
|
if (prevCatchParameter == null) continue;
|
||||||
|
for (PsiTypeElement prevCatchTypeElement : PsiUtil.getParameterTypeElements(prevCatchParameter)) {
|
||||||
|
PsiType prevCatchType = prevCatchTypeElement.getType();
|
||||||
|
caught.removeIf(prevCatchType::isAssignableFrom);
|
||||||
|
if (caught.isEmpty()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check & warn
|
||||||
|
if (caught.isEmpty()) {
|
||||||
|
if (JavaErrorCollector.findSingleError(statement) != null) return;
|
||||||
|
String types = caughtCopy.stream().map(JavaHighlightUtil::formatType).collect(NlsMessages.joiningAnd());
|
||||||
|
String message = JavaAnalysisBundle.message("inspection.unreachable.catch.message", types, caughtCopy.size());
|
||||||
|
ModCommandAction action = isMultiCatch ?
|
||||||
|
new DeleteMultiCatchFix(catchTypeElement) :
|
||||||
|
new DeleteCatchFix(parameter);
|
||||||
|
holder.problem(catchSection.getFirstChild(), message).fix(action).register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
Reports catch sections which are never executed, despite allowed by Java language specification.
|
||||||
|
<p>
|
||||||
|
While normally, unreachable catch sections are disallowed by Java compiler and reported as compilation errors,
|
||||||
|
in some rare cases the analysis mandated by Java language specification is not complete.
|
||||||
|
This inspection provides enhanced analysis and reports some unreachable catch sections which are not reported by the compiler.
|
||||||
|
Such sections are redundant and could be safely removed.
|
||||||
|
</p>
|
||||||
|
<p><b>Example:</b></p>
|
||||||
|
<pre><code>
|
||||||
|
void method() {
|
||||||
|
try {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// this catch is allowed by specification
|
||||||
|
// but never executed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>The quick-fix is provided, which removes the redundant catch section:</p>
|
||||||
|
<pre><code>
|
||||||
|
void method() {
|
||||||
|
try {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<!-- tooltip end -->
|
||||||
|
<p><small>New in 2025.1</small></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -146,7 +146,6 @@ repeated.modifier=Repeated modifier ''{0}''
|
|||||||
modifier.not.allowed=Modifier ''{0}'' not allowed here
|
modifier.not.allowed=Modifier ''{0}'' not allowed here
|
||||||
modifier.not.allowed.on.local.classes=Modifier ''{0}'' not allowed on local classes
|
modifier.not.allowed.on.local.classes=Modifier ''{0}'' not allowed on local classes
|
||||||
modifier.not.allowed.on.classes.without.sealed.super=Modifier 'non-sealed' not allowed on classes that do not have a sealed superclass
|
modifier.not.allowed.on.classes.without.sealed.super=Modifier 'non-sealed' not allowed on classes that do not have a sealed superclass
|
||||||
exception.already.caught.warn=Unreachable section: {1, choice, 0#exception|2#exceptions} ''{0}'' {1, choice, 0#has|2#have} already been caught
|
|
||||||
not.a.statement=Not a statement
|
not.a.statement=Not a statement
|
||||||
invalid.statement=Invalid statement
|
invalid.statement=Invalid statement
|
||||||
incompatible.types=Incompatible types. Found: ''{1}'', required: ''{0}''
|
incompatible.types=Incompatible types. Found: ''{1}'', required: ''{0}''
|
||||||
|
|||||||
@@ -215,4 +215,25 @@ public class UnhandledExceptions {
|
|||||||
};
|
};
|
||||||
return collect(element, topElement, callFilter);
|
return collect(element, topElement, callFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param statement try-statement to collect unhandled exceptions from its body
|
||||||
|
* @return exceptions unhandled in try statement body and resource declarations; they are still could be handled by declared
|
||||||
|
* catch sections on the same try statement. The primary purpose of this method is to check whether catch sections are correct.
|
||||||
|
*/
|
||||||
|
public static @NotNull UnhandledExceptions fromTryStatement(@NotNull PsiTryStatement statement) {
|
||||||
|
UnhandledExceptions thrownTypes = EMPTY;
|
||||||
|
|
||||||
|
PsiCodeBlock tryBlock = statement.getTryBlock();
|
||||||
|
if (tryBlock != null) {
|
||||||
|
thrownTypes = thrownTypes.merge(collect(tryBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
PsiResourceList resources = statement.getResourceList();
|
||||||
|
if (resources != null) {
|
||||||
|
thrownTypes = thrownTypes.merge(collect(resources));
|
||||||
|
}
|
||||||
|
|
||||||
|
return thrownTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class C {
|
|||||||
void m0() {
|
void m0() {
|
||||||
try { throw new FileNotFoundException(); }
|
try { throw new FileNotFoundException(); }
|
||||||
catch (FileNotFoundException e) { }
|
catch (FileNotFoundException e) { }
|
||||||
<warning descr="Unreachable section: exception 'java.io.FileNotFoundException' has already been caught">catch (IOException e) { }</warning>
|
<warning descr="Unreachable section: exception 'java.io.FileNotFoundException' has already been caught">catch</warning> (IOException e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
void m1() {
|
void m1() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.intellij.codeInspection.InspectionProfileEntry;
|
|||||||
import com.intellij.codeInspection.SafeVarargsHasNoEffectInspection;
|
import com.intellij.codeInspection.SafeVarargsHasNoEffectInspection;
|
||||||
import com.intellij.codeInspection.SafeVarargsOnNonReifiableTypeInspection;
|
import com.intellij.codeInspection.SafeVarargsOnNonReifiableTypeInspection;
|
||||||
import com.intellij.codeInspection.compiler.JavacQuirksInspection;
|
import com.intellij.codeInspection.compiler.JavacQuirksInspection;
|
||||||
|
import com.intellij.codeInspection.deadCode.UnreachableCatchInspection;
|
||||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
|
||||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
|
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
|
||||||
import com.intellij.codeInspection.defUse.DefUseInspection;
|
import com.intellij.codeInspection.defUse.DefUseInspection;
|
||||||
@@ -38,7 +39,8 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
enableInspectionTools(new UnusedDeclarationInspection(), new UncheckedWarningLocalInspection(), new JavacQuirksInspection(), new RedundantCastInspection(),
|
enableInspectionTools(new UnusedDeclarationInspection(), new UncheckedWarningLocalInspection(), new JavacQuirksInspection(), new RedundantCastInspection(),
|
||||||
new SafeVarargsHasNoEffectInspection(), new SafeVarargsOnNonReifiableTypeInspection());
|
new SafeVarargsHasNoEffectInspection(), new SafeVarargsOnNonReifiableTypeInspection(),
|
||||||
|
new UnreachableCatchInspection());
|
||||||
setLanguageLevel(LanguageLevel.JDK_1_7);
|
setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_7, getModule(), getTestRootDisposable());
|
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_7, getModule(), getTestRootDisposable());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user