From 0e99a3cacdcfd4e7cafc36355b49bbedf7053c0a Mon Sep 17 00:00:00 2001 From: Jinbo Wang Date: Tue, 28 Jun 2022 17:34:26 +0800 Subject: [PATCH] Revert "Support method breakpoints (#424)" This reverts commit 9bb983200e3176beb579238f68662fa4317c76b5. --- .../java/debug/core/DebugSession.java | 6 - .../java/debug/core/IDebugSession.java | 2 +- .../java/debug/core/IMethodBreakpoint.java | 33 --- .../java/debug/core/MethodBreakpoint.java | 258 ------------------ .../debug/core/adapter/BreakpointManager.java | 60 ---- .../java/debug/core/adapter/DebugAdapter.java | 3 +- .../core/adapter/IBreakpointManager.java | 20 -- .../handler/InitializeRequestHandler.java | 1 - .../SetFunctionBreakpointsRequestHandler.java | 189 ------------- .../java/debug/core/protocol/Types.java | 1 - 10 files changed, 2 insertions(+), 571 deletions(-) delete mode 100644 com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IMethodBreakpoint.java delete mode 100644 com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/MethodBreakpoint.java delete mode 100644 com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetFunctionBreakpointsRequestHandler.java diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java index ab4341f51..a56eaf695 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/DebugSession.java @@ -146,10 +146,4 @@ public IEventHub getEventHub() { public VirtualMachine getVM() { return vm; } - - @Override - public IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition, - int hitCount) { - return new MethodBreakpoint(vm, this.getEventHub(), className, functionName, condition, hitCount); - } } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IDebugSession.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IDebugSession.java index 03780c2d9..24138fef1 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IDebugSession.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IDebugSession.java @@ -36,7 +36,7 @@ public interface IDebugSession { void setExceptionBreakpoints(boolean notifyCaught, boolean notifyUncaught, String[] classFilters, String[] classExclusionFilters); - IMethodBreakpoint createFunctionBreakpoint(String className, String functionName, String condition, int hitCount); + // TODO: createFunctionBreakpoint Process process(); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IMethodBreakpoint.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IMethodBreakpoint.java deleted file mode 100644 index 668884567..000000000 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/IMethodBreakpoint.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2022 Microsoft Corporation and others. -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* Gayan Perera - initial API and implementation -*******************************************************************************/ -package com.microsoft.java.debug.core; - -import java.util.concurrent.CompletableFuture; - -public interface IMethodBreakpoint extends IDebugResource { - String methodName(); - - String className(); - - int getHitCount(); - - String getCondition(); - - void setHitCount(int hitCount); - - void setCondition(String condition); - - CompletableFuture install(); - - Object getProperty(Object key); - - void putProperty(Object key, Object value); -} diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/MethodBreakpoint.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/MethodBreakpoint.java deleted file mode 100644 index 82c5b75e2..000000000 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/MethodBreakpoint.java +++ /dev/null @@ -1,258 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2022 Microsoft Corporation and others. -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* Gayan Perera - initial API and implementation -*******************************************************************************/ -package com.microsoft.java.debug.core; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.lang3.StringUtils; - -import com.sun.jdi.ReferenceType; -import com.sun.jdi.ThreadReference; -import com.sun.jdi.VMDisconnectedException; -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.event.ClassPrepareEvent; -import com.sun.jdi.event.ThreadDeathEvent; -import com.sun.jdi.request.ClassPrepareRequest; -import com.sun.jdi.request.EventRequest; -import com.sun.jdi.request.MethodEntryRequest; - -import io.reactivex.Observable; -import io.reactivex.disposables.Disposable; - -public class MethodBreakpoint implements IMethodBreakpoint, IEvaluatableBreakpoint { - - private VirtualMachine vm; - private IEventHub eventHub; - private String className; - private String functionName; - private String condition; - private int hitCount; - - private HashMap propertyMap = new HashMap<>(); - private Object compiledConditionalExpression = null; - private Map compiledExpressions = new ConcurrentHashMap<>(); - - private List requests = new ArrayList<>(); - private List subscriptions = new ArrayList<>(); - - public MethodBreakpoint(VirtualMachine vm, IEventHub eventHub, String className, String functionName, - String condition, int hitCount) { - Objects.requireNonNull(vm); - Objects.requireNonNull(eventHub); - Objects.requireNonNull(className); - Objects.requireNonNull(functionName); - this.vm = vm; - this.eventHub = eventHub; - this.className = className; - this.functionName = functionName; - this.condition = condition; - this.hitCount = hitCount; - } - - @Override - public List requests() { - return requests; - } - - @Override - public List subscriptions() { - return subscriptions; - } - - @Override - public void close() throws Exception { - try { - vm.eventRequestManager().deleteEventRequests(requests()); - } catch (VMDisconnectedException ex) { - // ignore since removing breakpoints is meaningless when JVM is terminated. - } - subscriptions().forEach(Disposable::dispose); - requests.clear(); - subscriptions.clear(); - } - - @Override - public boolean containsEvaluatableExpression() { - return containsConditionalExpression() || containsLogpointExpression(); - } - - @Override - public boolean containsConditionalExpression() { - return StringUtils.isNotBlank(getCondition()); - } - - @Override - public boolean containsLogpointExpression() { - return false; - } - - @Override - public String getCondition() { - return condition; - } - - @Override - public void setCondition(String condition) { - this.condition = condition; - setCompiledConditionalExpression(null); - compiledExpressions.clear(); - } - - @Override - public String getLogMessage() { - return null; - } - - @Override - public void setLogMessage(String logMessage) { - // for future implementation - } - - @Override - public void setCompiledConditionalExpression(Object compiledExpression) { - this.compiledConditionalExpression = compiledExpression; - } - - @Override - public Object getCompiledConditionalExpression() { - return compiledConditionalExpression; - } - - @Override - public void setCompiledLogpointExpression(Object compiledExpression) { - // for future implementation - } - - @Override - public Object getCompiledLogpointExpression() { - return null; - } - - @Override - public void setCompiledExpression(long threadId, Object compiledExpression) { - compiledExpressions.put(threadId, compiledExpression); - } - - @Override - public Object getCompiledExpression(long threadId) { - return compiledExpressions.get(threadId); - } - - @Override - public int getHitCount() { - return hitCount; - } - - @Override - public void setHitCount(int hitCount) { - this.hitCount = hitCount; - Observable.fromIterable(this.requests()) - .filter(request -> request instanceof MethodEntryRequest) - .subscribe(request -> { - request.addCountFilter(hitCount); - request.enable(); - }); - } - - @Override - public CompletableFuture install() { - Disposable subscription = eventHub.events() - .filter(debugEvent -> debugEvent.event instanceof ThreadDeathEvent) - .subscribe(debugEvent -> { - ThreadReference deathThread = ((ThreadDeathEvent) debugEvent.event).thread(); - compiledExpressions.remove(deathThread.uniqueID()); - }); - - subscriptions.add(subscription); - - // It's possible that different class loaders create new class with the same - // name. - // Here to listen to future class prepare events to handle such case. - ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest(); - classPrepareRequest.addClassFilter(className); - classPrepareRequest.enable(); - requests.add(classPrepareRequest); - - CompletableFuture future = new CompletableFuture<>(); - subscription = eventHub.events() - .filter(debugEvent -> debugEvent.event instanceof ClassPrepareEvent - && (classPrepareRequest.equals(debugEvent.event.request()))) - .subscribe(debugEvent -> { - ClassPrepareEvent event = (ClassPrepareEvent) debugEvent.event; - Optional createdRequest = createMethodEntryRequest(event.referenceType()); - if (createdRequest.isPresent()) { - MethodEntryRequest methodEntryRequest = createdRequest.get(); - requests.add(methodEntryRequest); - if (!future.isDone()) { - this.putProperty("verified", true); - future.complete(this); - } - } - }); - subscriptions.add(subscription); - - List types = vm.classesByName(className); - for (ReferenceType type : types) { - Optional createdRequest = createMethodEntryRequest(type); - if (createdRequest.isPresent()) { - MethodEntryRequest methodEntryRequest = createdRequest.get(); - requests.add(methodEntryRequest); - if (!future.isDone()) { - this.putProperty("verified", true); - future.complete(this); - } - } - } - return future; - } - - private Optional createMethodEntryRequest(ReferenceType type) { - return type.methodsByName(functionName).stream().findFirst().map(method -> { - MethodEntryRequest request = vm.eventRequestManager().createMethodEntryRequest(); - - request.addClassFilter(type); - request.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); - if (hitCount > 0) { - request.addCountFilter(hitCount); - } - request.enable(); - return request; - }); - } - - @Override - public Object getProperty(Object key) { - return propertyMap.get(key); - } - - @Override - public void putProperty(Object key, Object value) { - propertyMap.put(key, value); - } - - @Override - public String methodName() { - return functionName; - } - - @Override - public String className() { - return className; - } - -} diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java index 4b0a7ae89..78898df73 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/BreakpointManager.java @@ -25,7 +25,6 @@ import com.microsoft.java.debug.core.Configuration; import com.microsoft.java.debug.core.IBreakpoint; -import com.microsoft.java.debug.core.IMethodBreakpoint; import com.microsoft.java.debug.core.IWatchpoint; public class BreakpointManager implements IBreakpointManager { @@ -36,7 +35,6 @@ public class BreakpointManager implements IBreakpointManager { private List breakpoints; private Map> sourceToBreakpoints; private Map watchpoints; - private Map methodBreakpoints; private AtomicInteger nextBreakpointId = new AtomicInteger(1); /** @@ -46,7 +44,6 @@ public BreakpointManager() { this.breakpoints = Collections.synchronizedList(new ArrayList<>(5)); this.sourceToBreakpoints = new HashMap<>(); this.watchpoints = new HashMap<>(); - this.methodBreakpoints = new HashMap<>(); } @Override @@ -211,61 +208,4 @@ private String getWatchpointKey(IWatchpoint watchpoint) { public IWatchpoint[] getWatchpoints() { return this.watchpoints.values().stream().filter(wp -> wp != null).toArray(IWatchpoint[]::new); } - - @Override - public IMethodBreakpoint[] getMethodBreakpoints() { - return this.methodBreakpoints.values().stream().filter(Objects::nonNull).toArray(IMethodBreakpoint[]::new); - } - - @Override - public IMethodBreakpoint[] setMethodBreakpoints(IMethodBreakpoint[] breakpoints) { - List result = new ArrayList<>(); - List toAdds = new ArrayList<>(); - List toRemoves = new ArrayList<>(); - - Set visitedKeys = new HashSet<>(); - for (IMethodBreakpoint change : breakpoints) { - if (change == null) { - result.add(change); - continue; - } - - String key = getMethodBreakpointKey(change); - IMethodBreakpoint cache = methodBreakpoints.get(key); - if (cache != null) { - visitedKeys.add(key); - result.add(cache); - } else { - toAdds.add(change); - result.add(change); - } - } - - for (IMethodBreakpoint cache : methodBreakpoints.values()) { - if (!visitedKeys.contains(getMethodBreakpointKey(cache))) { - toRemoves.add(cache); - } - } - - for (IMethodBreakpoint toRemove : toRemoves) { - try { - // Destroy the method breakpoint on the debugee VM. - toRemove.close(); - this.methodBreakpoints.remove(getMethodBreakpointKey(toRemove)); - } catch (Exception e) { - logger.log(Level.SEVERE, String.format("Remove the method breakpoint exception: %s", e.toString()), e); - } - } - - for (IMethodBreakpoint toAdd : toAdds) { - toAdd.putProperty("id", this.nextBreakpointId.getAndIncrement()); - this.methodBreakpoints.put(getMethodBreakpointKey(toAdd), toAdd); - } - - return result.toArray(new IMethodBreakpoint[0]); - } - - private String getMethodBreakpointKey(IMethodBreakpoint breakpoint) { - return breakpoint.className() + "#" + breakpoint.methodName(); - } } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java index 0bf5d2683..afdb5759c 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/DebugAdapter.java @@ -39,7 +39,6 @@ import com.microsoft.java.debug.core.adapter.handler.SetBreakpointsRequestHandler; import com.microsoft.java.debug.core.adapter.handler.SetDataBreakpointsRequestHandler; import com.microsoft.java.debug.core.adapter.handler.SetExceptionBreakpointsRequestHandler; -import com.microsoft.java.debug.core.adapter.handler.SetFunctionBreakpointsRequestHandler; import com.microsoft.java.debug.core.adapter.handler.SetVariableRequestHandler; import com.microsoft.java.debug.core.adapter.handler.SourceRequestHandler; import com.microsoft.java.debug.core.adapter.handler.StackTraceRequestHandler; @@ -128,7 +127,7 @@ private void initialize() { registerHandlerForDebug(new InlineValuesRequestHandler()); registerHandlerForDebug(new RefreshVariablesHandler()); registerHandlerForDebug(new ProcessIdHandler()); - registerHandlerForDebug(new SetFunctionBreakpointsRequestHandler()); + // NO_DEBUG mode only registerHandlerForNoDebug(new DisconnectRequestWithoutDebuggingHandler()); registerHandlerForNoDebug(new ProcessIdHandler()); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/IBreakpointManager.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/IBreakpointManager.java index 196714d52..9ba609221 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/IBreakpointManager.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/IBreakpointManager.java @@ -12,7 +12,6 @@ package com.microsoft.java.debug.core.adapter; import com.microsoft.java.debug.core.IBreakpoint; -import com.microsoft.java.debug.core.IMethodBreakpoint; import com.microsoft.java.debug.core.IWatchpoint; public interface IBreakpointManager { @@ -70,23 +69,4 @@ public interface IBreakpointManager { * Returns all registered watchpoints. */ IWatchpoint[] getWatchpoints(); - - /** - * Returns all the registered method breakpoints. - */ - IMethodBreakpoint[] getMethodBreakpoints(); - - /** - * Update the method breakpoints list. If the requested method breakpoints - * already registered in the breakpoint - * manager, reuse the cached one. Otherwise register the requested method - * breakpoints as a new method breakpoints. - * Besides, delete those not existed any more. - * - * @param methodBreakpoints - * the method breakpoints requested by client - * @return the full registered method breakpoints list - */ - IMethodBreakpoint[] setMethodBreakpoints(IMethodBreakpoint[] methodBreakpoints); - } diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InitializeRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InitializeRequestHandler.java index ae92f356f..4733170eb 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InitializeRequestHandler.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/InitializeRequestHandler.java @@ -62,7 +62,6 @@ public CompletableFuture handle(Requests.Command command, Req caps.exceptionBreakpointFilters = exceptionFilters; caps.supportsExceptionInfoRequest = true; caps.supportsDataBreakpoints = true; - caps.supportsFunctionBreakpoints = true; caps.supportsClipboardContext = true; response.body = caps; return CompletableFuture.completedFuture(response); diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetFunctionBreakpointsRequestHandler.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetFunctionBreakpointsRequestHandler.java deleted file mode 100644 index fa4d23388..000000000 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/SetFunctionBreakpointsRequestHandler.java +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2022 Microsoft Corporation and others. -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* Gayan Perera - initial API and implementation -*******************************************************************************/ - -package com.microsoft.java.debug.core.adapter.handler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; - -import org.apache.commons.lang3.StringUtils; - -import com.microsoft.java.debug.core.IDebugSession; -import com.microsoft.java.debug.core.IEvaluatableBreakpoint; -import com.microsoft.java.debug.core.IMethodBreakpoint; -import com.microsoft.java.debug.core.MethodBreakpoint; -import com.microsoft.java.debug.core.adapter.AdapterUtils; -import com.microsoft.java.debug.core.adapter.ErrorCode; -import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; -import com.microsoft.java.debug.core.adapter.IDebugRequestHandler; -import com.microsoft.java.debug.core.adapter.IEvaluationProvider; -import com.microsoft.java.debug.core.protocol.Events; -import com.microsoft.java.debug.core.protocol.Events.BreakpointEvent; -import com.microsoft.java.debug.core.protocol.Messages.Response; -import com.microsoft.java.debug.core.protocol.Requests.Arguments; -import com.microsoft.java.debug.core.protocol.Requests.Command; -import com.microsoft.java.debug.core.protocol.Requests.SetFunctionBreakpointsArguments; -import com.microsoft.java.debug.core.protocol.Responses; -import com.microsoft.java.debug.core.protocol.Types.Breakpoint; -import com.microsoft.java.debug.core.protocol.Types.FunctionBreakpoint; -import com.sun.jdi.ThreadReference; -import com.sun.jdi.event.MethodEntryEvent; - -public class SetFunctionBreakpointsRequestHandler implements IDebugRequestHandler { - private boolean registered = false; - - @Override - public List getTargetCommands() { - return Arrays.asList(Command.SETFUNCTIONBREAKPOINTS); - } - - @Override - public CompletableFuture handle(Command command, Arguments arguments, Response response, - IDebugAdapterContext context) { - if (context.getDebugSession() == null) { - return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.EMPTY_DEBUG_SESSION, - "Empty debug session."); - } - - if (!registered) { - registered = true; - registerMethodBreakpointHandler(context); - } - - SetFunctionBreakpointsArguments funcBpArgs = (SetFunctionBreakpointsArguments) arguments; - IMethodBreakpoint[] requestedMethodBreakpoints = (funcBpArgs.breakpoints == null) ? new IMethodBreakpoint[0] - : new MethodBreakpoint[funcBpArgs.breakpoints.length]; - for (int i = 0; i < requestedMethodBreakpoints.length; i++) { - FunctionBreakpoint funcBreakpoint = funcBpArgs.breakpoints[i]; - if (funcBreakpoint.name != null) { - String[] segments = funcBreakpoint.name.split("#"); - if (segments.length == 2 && StringUtils.isNotBlank(segments[0]) - && StringUtils.isNotBlank(segments[1])) { - int hitCount = 0; - try { - hitCount = Integer.parseInt(funcBreakpoint.hitCondition); - } catch (NumberFormatException e) { - hitCount = 0; // If hitCount is an illegal number, ignore hitCount condition. - } - requestedMethodBreakpoints[i] = context.getDebugSession().createFunctionBreakpoint(segments[0], - segments[1], - funcBreakpoint.condition, hitCount); - } - } - } - - IMethodBreakpoint[] currentMethodBreakpoints = context.getBreakpointManager() - .setMethodBreakpoints(requestedMethodBreakpoints); - List breakpoints = new ArrayList<>(); - for (int i = 0; i < currentMethodBreakpoints.length; i++) { - if (currentMethodBreakpoints[i] == null) { - breakpoints.add(new Breakpoint(false)); - continue; - } - - // If the requested method breakpoint exists in the manager, it will reuse - // the cached breakpoint exists object. - // Otherwise add the requested method breakpoint to the cache. - // So if the returned method breakpoint from the manager is same as the - // requested method breakpoint, this means it's a new method breakpoint, need - // install it. - if (currentMethodBreakpoints[i] == requestedMethodBreakpoints[i]) { - currentMethodBreakpoints[i].install().thenAccept(wp -> { - BreakpointEvent bpEvent = new BreakpointEvent("changed", convertDebuggerMethodToClient(wp)); - context.getProtocolServer().sendEvent(bpEvent); - }); - } else { - if (currentMethodBreakpoints[i].getHitCount() != requestedMethodBreakpoints[i].getHitCount()) { - currentMethodBreakpoints[i].setHitCount(requestedMethodBreakpoints[i].getHitCount()); - } - - if (!Objects.equals(currentMethodBreakpoints[i].getCondition(), - requestedMethodBreakpoints[i].getCondition())) { - currentMethodBreakpoints[i].setCondition(requestedMethodBreakpoints[i].getCondition()); - } - } - - breakpoints.add(convertDebuggerMethodToClient(currentMethodBreakpoints[i])); - } - - response.body = new Responses.SetDataBreakpointsResponseBody(breakpoints); - return CompletableFuture.completedFuture(response); - } - - private Breakpoint convertDebuggerMethodToClient(IMethodBreakpoint methodBreakpoint) { - return new Breakpoint((int) methodBreakpoint.getProperty("id"), - methodBreakpoint.getProperty("verified") != null && (boolean) methodBreakpoint.getProperty("verified")); - } - - private void registerMethodBreakpointHandler(IDebugAdapterContext context) { - IDebugSession debugSession = context.getDebugSession(); - if (debugSession != null) { - debugSession.getEventHub().events().filter(debugEvent -> debugEvent.event instanceof MethodEntryEvent) - .subscribe(debugEvent -> { - MethodEntryEvent methodEntryEvent = (MethodEntryEvent) debugEvent.event; - ThreadReference bpThread = methodEntryEvent.thread(); - IEvaluationProvider engine = context.getProvider(IEvaluationProvider.class); - - // Find the method breakpoint related to this method entry event - IMethodBreakpoint methodBreakpoint = Stream - .of(context.getBreakpointManager().getMethodBreakpoints()) - .filter(mp -> { - return mp.requests().contains(methodEntryEvent.request()) - && matches(methodEntryEvent, mp); - }) - .findFirst().orElse(null); - - if (methodBreakpoint != null) { - if (methodBreakpoint instanceof IEvaluatableBreakpoint - && ((IEvaluatableBreakpoint) methodBreakpoint).containsConditionalExpression()) { - if (engine.isInEvaluation(bpThread)) { - return; - } - CompletableFuture.runAsync(() -> { - engine.evaluateForBreakpoint((IEvaluatableBreakpoint) methodBreakpoint, bpThread) - .whenComplete((value, ex) -> { - boolean resume = SetBreakpointsRequestHandler.handleEvaluationResult( - context, bpThread, (IEvaluatableBreakpoint) methodBreakpoint, - value, - ex); - // Clear the evaluation environment caused by above evaluation. - engine.clearState(bpThread); - - if (resume) { - debugEvent.eventSet.resume(); - } else { - context.getProtocolServer().sendEvent(new Events.StoppedEvent( - "function breakpoint", bpThread.uniqueID())); - } - }); - }); - - } else { - context.getProtocolServer() - .sendEvent(new Events.StoppedEvent("function breakpoint", bpThread.uniqueID())); - } - - debugEvent.shouldResume = false; - } - }); - } - } - - private boolean matches(MethodEntryEvent methodEntryEvent, IMethodBreakpoint breakpoint) { - return breakpoint.className().equals(methodEntryEvent.location().declaringType().name()) - && breakpoint.methodName().equals(methodEntryEvent.method().name()); - } - -} diff --git a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Types.java b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Types.java index cd20faf4f..e59f65f74 100644 --- a/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Types.java +++ b/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Types.java @@ -374,6 +374,5 @@ public static class Capabilities { public ExceptionBreakpointFilter[] exceptionBreakpointFilters = new ExceptionBreakpointFilter[0]; public boolean supportsDataBreakpoints; public boolean supportsClipboardContext; - public boolean supportsFunctionBreakpoints; } }