ComponentWithBrowseButton - optional remove listener on hide
[fedora-idea.git] / java / debugger / impl / src / com / intellij / debugger / engine / RequestHint.java
blob7b6703e2de6484286319adf625383b4aaa34bffb
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.
18 * @author: Eugene Zhuravlev
19 * Date: Jul 23, 2002
20 * Time: 11:10:11 AM
22 package com.intellij.debugger.engine;
24 import com.intellij.debugger.SourcePosition;
25 import com.intellij.debugger.engine.evaluation.EvaluateException;
26 import com.intellij.debugger.engine.jdi.StackFrameProxy;
27 import com.intellij.debugger.impl.DebuggerUtilsEx;
28 import com.intellij.debugger.impl.PositionUtil;
29 import com.intellij.debugger.jdi.StackFrameProxyImpl;
30 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
31 import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
32 import com.intellij.debugger.settings.DebuggerSettings;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.diagnostic.Logger;
35 import com.intellij.openapi.util.Computable;
36 import com.intellij.psi.PsiMethod;
37 import com.intellij.psi.util.PsiTreeUtil;
38 import com.sun.jdi.*;
39 import com.sun.jdi.request.StepRequest;
40 import org.jetbrains.annotations.NonNls;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
44 public class RequestHint {
45 public static final int STOP = 0;
46 private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.RequestHint");
47 private final int myDepth;
48 private SourcePosition myPosition;
49 private int myFrameCount;
50 private VirtualMachineProxyImpl myVirtualMachineProxy;
52 private final @Nullable SmartStepFilter myTargetMethodSignature;
53 private boolean myIgnoreFilters = false;
54 private boolean myRestoreBreakpoints = false;
55 private final boolean mySkipThisMethod = false;
57 public static final class SmartStepFilter {
58 private final JVMName myDeclaringClassName;
59 private final @NonNls String myTargetMethodName;
60 private final JVMName myTargetMethodSignature;
62 public SmartStepFilter(PsiMethod psiMethod) {
63 myDeclaringClassName = JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass());
64 myTargetMethodName = psiMethod.isConstructor()? "<init>" : psiMethod.getName();
65 myTargetMethodSignature = JVMNameUtil.getJVMSignature(psiMethod);
68 public boolean shouldStopAtLocation(final SuspendContextImpl context) {
69 try {
70 final StackFrameProxyImpl frameProxy = context.getFrameProxy();
71 if (frameProxy == null) {
72 return true;
74 final Location location = frameProxy.location();
75 final Method method = location.method();
76 if (!myTargetMethodName.equals(method.name())) {
77 return false;
79 final DebugProcessImpl process = context.getDebugProcess();
80 if (!signatureMatches(method, myTargetMethodSignature.getName(process))) {
81 return false;
83 final ObjectReference thisObject = frameProxy.thisObject();
84 final ReferenceType locationClass = thisObject != null? thisObject.referenceType() : method.declaringType();
85 return DebuggerUtilsEx.isAssignableFrom(myDeclaringClassName.getName(process), locationClass);
87 catch (EvaluateException e) {
88 LOG.info(e);
90 return true;
93 private static boolean signatureMatches(Method method, final String expectedSignature) throws EvaluateException {
94 if (expectedSignature.equals(method.signature())) {
95 return true;
97 // check if there are any bridge methods that match
98 for (Method candidate : method.declaringType().methodsByName(method.name())) {
99 if (candidate != method && candidate.isBridge() && expectedSignature.equals(candidate.signature())) {
100 return true;
103 return false;
107 public RequestHint(final ThreadReferenceProxyImpl stepThread, final SuspendContextImpl suspendContext, @NotNull SmartStepFilter smartStepFilter) {
108 this(stepThread, suspendContext, StepRequest.STEP_INTO, smartStepFilter);
111 public RequestHint(final ThreadReferenceProxyImpl stepThread, final SuspendContextImpl suspendContext, int depth) {
112 this(stepThread, suspendContext, depth, null);
115 private RequestHint(final ThreadReferenceProxyImpl stepThread, final SuspendContextImpl suspendContext, int depth, SmartStepFilter smartStepFilter) {
116 final DebugProcessImpl debugProcess = suspendContext.getDebugProcess();
117 myDepth = depth;
118 myTargetMethodSignature = smartStepFilter;
119 myVirtualMachineProxy = debugProcess.getVirtualMachineProxy();
121 try {
122 myFrameCount = stepThread.frameCount();
124 ApplicationManager.getApplication().runReadAction(new Runnable() {
125 public void run() {
126 myPosition = ContextUtil.getSourcePosition(new StackFrameContext() {
127 public StackFrameProxy getFrameProxy() {
128 try {
129 return stepThread.frame(0);
131 catch (EvaluateException e) {
132 if (LOG.isDebugEnabled()) {
133 LOG.debug(e);
135 return null;
139 public DebugProcess getDebugProcess() {
140 return suspendContext.getDebugProcess();
146 catch (Exception e) {
147 myPosition = null;
151 public void setIgnoreFilters(boolean ignoreFilters) {
152 myIgnoreFilters = ignoreFilters;
155 public void setRestoreBreakpoints(boolean restoreBreakpoints) {
156 myRestoreBreakpoints = restoreBreakpoints;
159 public boolean isRestoreBreakpoints() {
160 return myRestoreBreakpoints;
163 public boolean isIgnoreFilters() {
164 return myIgnoreFilters;
167 public int getDepth() {
168 return mySkipThisMethod ? StepRequest.STEP_OUT : myDepth;
171 public int getNextStepDepth(final SuspendContextImpl context) {
172 try {
173 if ((myDepth == StepRequest.STEP_OVER || myDepth == StepRequest.STEP_INTO) && myPosition != null) {
174 final Integer resultDepth = ApplicationManager.getApplication().runReadAction(new Computable<Integer>() {
175 public Integer compute() {
176 final SourcePosition locationPosition = ContextUtil.getSourcePosition(context);
177 if (locationPosition == null) {
178 return null;
180 int frameCount = -1;
181 final ThreadReferenceProxyImpl contextThread = context.getThread();
182 if (contextThread != null) {
183 try {
184 frameCount = contextThread.frameCount();
186 catch (EvaluateException e) {
189 final boolean filesEqual = myPosition.getFile().equals(locationPosition.getFile());
190 if (filesEqual && myPosition.getLine() == locationPosition.getLine() && myFrameCount == frameCount) {
191 return myDepth;
193 if (myDepth == StepRequest.STEP_INTO) {
194 // check if we are still at the line from which the stepping begun
195 if (filesEqual && myFrameCount == frameCount && myPosition.getLine() != locationPosition.getLine()) {
196 return STOP;
199 return null;
202 if (resultDepth != null) {
203 return resultDepth.intValue();
206 // the rest of the code makes sence for depth == STEP_INTO only
208 if (myDepth == StepRequest.STEP_INTO) {
209 final DebuggerSettings settings = DebuggerSettings.getInstance();
210 if (settings.SKIP_SYNTHETIC_METHODS) {
211 final StackFrameProxyImpl frameProxy = context.getFrameProxy();
212 Location location = frameProxy.location();
213 Method method = location.method();
214 if (method != null) {
215 if (myVirtualMachineProxy.canGetSyntheticAttribute()? method.isSynthetic() : method.name().indexOf('$') >= 0) {
216 return myDepth;
220 if (!myIgnoreFilters) {
221 if(settings.SKIP_GETTERS) {
222 boolean isGetter = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>(){
223 public Boolean compute() {
224 final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(PositionUtil.getContextElement(context), PsiMethod.class);
225 return (psiMethod != null && DebuggerUtils.isSimpleGetter(psiMethod))? Boolean.TRUE : Boolean.FALSE;
227 }).booleanValue();
229 if(isGetter) {
230 return StepRequest.STEP_OUT;
234 if (settings.SKIP_CONSTRUCTORS) {
235 Location location = context.getFrameProxy().location();
236 Method method = location.method();
237 if (method != null && method.isConstructor()) {
238 return StepRequest.STEP_OUT;
242 if (settings.SKIP_CLASSLOADERS) {
243 Location location = context.getFrameProxy().location();
244 if (DebuggerUtilsEx.isAssignableFrom("java.lang.ClassLoader", location.declaringType())) {
245 return StepRequest.STEP_OUT;
249 // smart step feature
250 if (myTargetMethodSignature != null) {
251 if (!myTargetMethodSignature.shouldStopAtLocation(context)) {
252 return StepRequest.STEP_OUT;
257 catch (VMDisconnectedException e) {
259 catch (EvaluateException e) {
260 LOG.error(e);
262 return STOP;