add utility method for containing method
[idea/community.git] / java / debugger / impl / src / com / intellij / debugger / ui / breakpoints / JavaLineBreakpointType.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.debugger.ui.breakpoints;
17
18 import com.intellij.debugger.DebuggerBundle;
19 import com.intellij.debugger.HelpID;
20 import com.intellij.debugger.SourcePosition;
21 import com.intellij.debugger.impl.DebuggerUtilsEx;
22 import com.intellij.openapi.editor.Document;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.util.TextRange;
25 import com.intellij.openapi.util.text.StringUtil;
26 import com.intellij.openapi.vfs.VirtualFile;
27 import com.intellij.psi.*;
28 import com.intellij.util.SmartList;
29 import com.intellij.xdebugger.XDebuggerUtil;
30 import com.intellij.xdebugger.XSourcePosition;
31 import com.intellij.xdebugger.breakpoints.XBreakpoint;
32 import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
33 import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
34 import com.intellij.xdebugger.impl.XSourcePositionImpl;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
37 import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties;
38
39 import javax.swing.*;
40 import java.util.Collections;
41 import java.util.List;
42
43 /**
44  * Base class for java line-connected exceptions (line, method, field)
45  * @author egor
46  */
47 public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase<JavaLineBreakpointProperties> implements JavaBreakpointType {
48   public JavaLineBreakpointType() {
49     super("java-line", DebuggerBundle.message("line.breakpoints.tab.title"));
50   }
51
52   //@Override
53   protected String getHelpID() {
54     return HelpID.LINE_BREAKPOINTS;
55   }
56
57   //@Override
58   public String getDisplayName() {
59     return DebuggerBundle.message("line.breakpoints.tab.title");
60   }
61
62   @Override
63   public List<XBreakpointGroupingRule<XLineBreakpoint<JavaLineBreakpointProperties>, ?>> getGroupingRules() {
64     return XDebuggerUtil.getInstance().getGroupingByFileRuleAsList();
65   }
66
67   @Nullable
68   @Override
69   public JavaLineBreakpointProperties createProperties() {
70     return new JavaLineBreakpointProperties();
71   }
72
73   @Nullable
74   @Override
75   public JavaLineBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
76     return new JavaLineBreakpointProperties();
77   }
78
79   @NotNull
80   @Override
81   public Breakpoint createJavaBreakpoint(Project project, XBreakpoint breakpoint) {
82     return new LineBreakpoint(project, breakpoint);
83   }
84
85   @Override
86   public int getPriority() {
87     return 100;
88   }
89
90   @NotNull
91   @Override
92   public List<JavaBreakpointVariant> computeVariants(@NotNull Project project, @NotNull XSourcePosition position) {
93     PsiFile file = PsiManager.getInstance(project).findFile(position.getFile());
94     if (file == null) {
95       return Collections.emptyList();
96     }
97
98     SourcePosition pos = SourcePosition.createFromLine(file, position.getLine());
99     List<PsiLambdaExpression> lambdas = DebuggerUtilsEx.collectLambdas(pos, true);
100     if (lambdas.isEmpty()) {
101       return Collections.emptyList();
102     }
103
104     PsiElement startMethod = DebuggerUtilsEx.getContainingMethod(pos);
105     //noinspection SuspiciousMethodCalls
106     if (lambdas.contains(startMethod) && lambdas.size() == 1) {
107       return Collections.emptyList();
108     }
109
110     Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
111     if (document == null) {
112       return Collections.emptyList();
113     }
114
115     List<JavaBreakpointVariant> res = new SmartList<JavaBreakpointVariant>();
116     res.add(new JavaBreakpointVariant(position)); //all
117
118     if (startMethod instanceof PsiMethod) {
119       res.add(new ExactJavaBreakpointVariant(position, startMethod, -1)); // base method
120     }
121
122     int ordinal = 0;
123     for (PsiLambdaExpression lambda : lambdas) { //lambdas
124       PsiElement firstElem = DebuggerUtilsEx.getFirstElementOnTheLine(lambda, document, position.getLine());
125       res.add(new ExactJavaBreakpointVariant(XSourcePositionImpl.createByElement(firstElem), lambda, ordinal++));
126     }
127
128     return res;
129   }
130
131   class JavaBreakpointVariant extends XLineBreakpointVariant {
132     protected final XSourcePosition mySourcePosition;
133
134     private JavaBreakpointVariant(XSourcePosition position) {
135       mySourcePosition = position;
136     }
137
138     @Override
139     public String getText() {
140       return "All";
141     }
142
143     @Override
144     public Icon getIcon() {
145       return null;
146     }
147
148     @Override
149     public TextRange getHighlightRange() {
150       return null;
151     }
152
153     @Override
154     public JavaLineBreakpointProperties createProperties() {
155       return createBreakpointProperties(mySourcePosition.getFile(),
156                                         mySourcePosition.getLine());
157     }
158   }
159
160   private class ExactJavaBreakpointVariant extends JavaBreakpointVariant {
161     private final PsiElement myElement;
162     private final Integer myLambdaOrdinal;
163
164     public ExactJavaBreakpointVariant(XSourcePosition position, PsiElement element, Integer lambdaOrdinal) {
165       super(position);
166       myElement = element;
167       myLambdaOrdinal = lambdaOrdinal;
168     }
169
170     @Override
171     public Icon getIcon() {
172       return myElement.getIcon(0);
173     }
174
175     @Override
176     public String getText() {
177       return StringUtil.shortenTextWithEllipsis(myElement.getText(), 100, 0);
178     }
179
180     @Override
181     public TextRange getHighlightRange() {
182       return myElement.getTextRange();
183     }
184
185     @Override
186     public JavaLineBreakpointProperties createProperties() {
187       JavaLineBreakpointProperties properties = super.createProperties();
188       properties.setLambdaOrdinal(myLambdaOrdinal);
189       return properties;
190     }
191   }
192
193   @Nullable
194   @Override
195   public TextRange getHighlightRange(XLineBreakpoint<JavaLineBreakpointProperties> breakpoint) {
196     JavaLineBreakpointProperties properties = breakpoint.getProperties();
197     if (properties != null) {
198       Integer ordinal = properties.getLambdaOrdinal();
199       if (ordinal != null) {
200         Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
201         if (javaBreakpoint instanceof LineBreakpoint) {
202           PsiElement method = ((LineBreakpoint)javaBreakpoint).getContainingMethod();
203           if (method != null) {
204             return method.getTextRange();
205           }
206         }
207       }
208     }
209     return null;
210   }
211 }