update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / highlighting / HighlightExitPointsHandler.java
blob23314813264ff57d28834664882b2ce82b61f614
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight.highlighting;
18 import com.intellij.codeInsight.CodeInsightBundle;
19 import com.intellij.featureStatistics.FeatureUsageTracker;
20 import com.intellij.openapi.editor.Editor;
21 import com.intellij.openapi.project.Project;
22 import com.intellij.psi.*;
23 import com.intellij.psi.controlFlow.*;
24 import com.intellij.psi.util.PsiTreeUtil;
25 import com.intellij.util.Consumer;
26 import com.intellij.util.containers.IntArrayList;
27 import org.jetbrains.annotations.Nullable;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
34 public class HighlightExitPointsHandler extends HighlightUsagesHandlerBase<PsiElement> {
35 private final PsiElement myTarget;
37 public HighlightExitPointsHandler(final Editor editor, final PsiFile file, final PsiElement target) {
38 super(editor, file);
39 myTarget = target;
42 public List<PsiElement> getTargets() {
43 return Collections.singletonList(myTarget);
46 protected void selectTargets(final List<PsiElement> targets, final Consumer<List<PsiElement>> selectionConsumer) {
47 selectionConsumer.consume(targets);
50 public void computeUsages(final List<PsiElement> targets) {
51 FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.highlight.return");
53 PsiElement parent = myTarget.getParent();
54 if (!(parent instanceof PsiReturnStatement) && !(parent instanceof PsiThrowStatement)) return;
56 PsiMethod method = PsiTreeUtil.getParentOfType(myTarget, PsiMethod.class);
57 if (method == null) return;
59 PsiCodeBlock body = method.getBody();
60 try {
61 highlightExitPoints((PsiStatement)parent, body);
63 catch (AnalysisCanceledException e) {
64 // ignore
68 @Nullable
69 private static PsiElement getExitTarget(PsiStatement exitStatement) {
70 if (exitStatement instanceof PsiReturnStatement) {
71 return PsiTreeUtil.getParentOfType(exitStatement, PsiMethod.class);
73 else if (exitStatement instanceof PsiBreakStatement) {
74 return ((PsiBreakStatement)exitStatement).findExitedStatement();
76 else if (exitStatement instanceof PsiContinueStatement) {
77 return ((PsiContinueStatement)exitStatement).findContinuedStatement();
79 else if (exitStatement instanceof PsiThrowStatement) {
80 final PsiExpression expr = ((PsiThrowStatement)exitStatement).getException();
81 if (expr == null) return null;
82 final PsiType exceptionType = expr.getType();
83 if (!(exceptionType instanceof PsiClassType)) return null;
85 PsiElement target = exitStatement;
86 while (!(target instanceof PsiMethod || target == null || target instanceof PsiClass || target instanceof PsiFile)) {
87 if (target instanceof PsiTryStatement) {
88 final PsiTryStatement tryStatement = (PsiTryStatement)target;
89 final PsiParameter[] params = tryStatement.getCatchBlockParameters();
90 for (PsiParameter param : params) {
91 if (param.getType().isAssignableFrom(exceptionType)) {
92 break;
97 target = target.getParent();
99 if (target instanceof PsiMethod || target instanceof PsiTryStatement) {
100 return target;
102 return null;
105 return null;
108 private void highlightExitPoints(final PsiStatement parent, final PsiCodeBlock body) throws AnalysisCanceledException {
109 final Project project = myTarget.getProject();
110 ControlFlow flow = ControlFlowFactory.getInstance(project).getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance(), false);
112 Collection<PsiStatement> exitStatements = ControlFlowUtil.findExitPointsAndStatements(flow, 0, flow.getSize(), new IntArrayList(),
113 PsiReturnStatement.class, PsiBreakStatement.class,
114 PsiContinueStatement.class, PsiThrowStatement.class);
115 if (!exitStatements.contains(parent)) return;
117 PsiElement originalTarget = getExitTarget(parent);
119 final Iterator<PsiStatement> it = exitStatements.iterator();
120 while (it.hasNext()) {
121 PsiStatement psiStatement = it.next();
122 if (getExitTarget(psiStatement) != originalTarget) {
123 it.remove();
127 for (PsiElement e : exitStatements) {
128 addOccurrence(e);
130 myStatusText = CodeInsightBundle.message("status.bar.exit.points.highlighted.message", exitStatements.size(),
131 HighlightUsagesHandler.getShortcutText());