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