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
) {
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();
61 highlightExitPoints((PsiStatement
)parent
, body
);
63 catch (AnalysisCanceledException e
) {
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
)) {
97 target
= target
.getParent();
99 if (target
instanceof PsiMethod
|| target
instanceof PsiTryStatement
) {
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
) {
127 for (PsiElement e
: exitStatements
) {
130 myStatusText
= CodeInsightBundle
.message("status.bar.exit.points.highlighted.message", exitStatements
.size(),
131 HighlightUsagesHandler
.getShortcutText());