This is an automated email from the ASF dual-hosted git repository.
geertjan pushed a commit to branch delivery
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/delivery by this push:
new af63abb Correct the breakpoint functionality in cpplite debugger.
new ac5046d Merge pull request #2726 from
entlicher/CPPLiteDebugBreakpoints
af63abb is described below
commit af63abbe04d1e02e70807302552ce2ce7375e9bc
Author: Martin Entlicher <[email protected]>
AuthorDate: Tue Feb 2 11:24:52 2021 +0100
Correct the breakpoint functionality in cpplite debugger.
---
.../org.netbeans.spi.viewmodel.NodeModel | 1 -
.../org.netbeans.spi.debugger.ActionsProvider | 2 -
...tbeans.api.debugger.LazyDebuggerManagerListener | 2 -
.../org.netbeans.api.debugger.Properties$Reader | 1 -
.../modules/cpplite/debugger/Bundle.properties | 27 ---
.../cpplite/debugger/CPPLiteActionsProvider.java | 144 +++++++++++
.../modules/cpplite/debugger/CPPLiteDebugger.java | 263 ++++++++++----------
.../modules/cpplite/debugger/CPPThread.java | 3 +
.../cpplite/debugger/DebuggerAnnotation.java | 37 ++-
.../debugger/DebuggerBreakpointAnnotation.java | 115 +++++++--
.../breakpoints/BreakpointAnnotationListener.java | 111 ---------
.../breakpoints/BreakpointAnnotationProvider.java | 269 +++++++++++++++++++++
.../debugger/breakpoints/BreakpointModel.java | 21 +-
.../debugger/breakpoints/BreakpointsReader.java | 40 +--
.../debugger/breakpoints/CPPLiteBreakpoint.java | 74 ++++--
.../CPPLiteBreakpointActionProvider.java | 28 +--
.../debugger/breakpoints/LoadBreakpoints.java | 41 ----
.../debugger/breakpoints/PersistenceManager.java | 2 +
.../debuggingview/DebuggingViewSupportImpl.java | 2 +-
.../cpplite/debugger/AbstractDebugTest.java | 111 +++++++++
.../modules/cpplite/debugger/BreakpointsTest.java | 147 +++++++++++
.../modules/cpplite/debugger/StepTest.java | 69 +-----
.../src/org/netbeans/api/debugger/Breakpoint.java | 2 +-
23 files changed, 1040 insertions(+), 472 deletions(-)
diff --git
a/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel
b/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel
deleted file mode 100644
index b2ec1a2..0000000
---
a/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel
+++ /dev/null
@@ -1 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointModel
\ No newline at end of file
diff --git
a/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider
b/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider
deleted file mode 100644
index 948c17a..0000000
---
a/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider
+++ /dev/null
@@ -1,2 +0,0 @@
-org.netbeans.modules.cpplite.debugger.CPPLiteDebugger
-org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpointActionProvider
\ No newline at end of file
diff --git
a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
b/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
deleted file mode 100644
index b7903e7..0000000
---
a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
+++ /dev/null
@@ -1,2 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointAnnotationListener
-org.netbeans.modules.cpplite.debugger.breakpoints.PersistenceManager
\ No newline at end of file
diff --git
a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader
b/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader
deleted file mode 100644
index 4ce300b..0000000
---
a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader
+++ /dev/null
@@ -1 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointsReader
\ No newline at end of file
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
index fa230e4..5ccc602 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
@@ -18,30 +18,3 @@
OpenIDE-Module-Display-Category=C/C++
OpenIDE-Module-Name=CPPLite Debugger
-# RunTargetsAction
-LBL_run_other_targets=Other Targets
-LBL_run_advanced=Advanced...
-TITLE_run_advanced=Debug Ant Target
-LBL_run_advanced_run=Debug
-LBL_run_advanced_cancel=Cancel
-
-# AdvancedActionsPanel
-AdvancedActionsPanel.targetLabel.text=Select &target(s) to debug\:
-AdvancedActionsPanel.targetDescriptionLabel.text=Target description\:
-AdvancedActionsPanel.propertiesLabel.text=Special Ant &properties\:
-AdvancedActionsPanel.verbosityLabel.text=&Verbosity level\:
-LBL_verbosity_warn=Quiet
-LBL_verbosity_info=Normal
-LBL_verbosity_verbose=Verbose
-LBL_verbosity_debug=Debug
-
-#org.netbeans.modules.debugger.jpda.ui.DebuggerAnnotation
-TOOLTIP_DISABLED_CONDITIONAL_BREAKPOINT=Disabled Conditional Breakpoint
-TOOLTIP_DISABLED_BREAKPOINT=Disabled Breakpoint
-TOOLTIP_CALLSITE=Call Stack Line
-TOOLTIP_BREAKPOINT=Breakpoint
-TOOLTIP_CONDITIONAL_BREAKPOINT=Conditional Breakpoint
-TOOLTIP_CURRENT_PC=Current Program Counter
-TOOLTIP_CURRENT_PC_2=Current Target
-
-CTL_WatchDisabled=>disabled<
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java
new file mode 100644
index 0000000..8ce1378
--- /dev/null
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.cpplite.debugger;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.spi.debugger.ActionsProvider;
+import org.netbeans.spi.debugger.ActionsProviderSupport;
+import org.netbeans.spi.debugger.ContextProvider;
+import org.openide.util.RequestProcessor;
+
+/**
+ * The CPP Lite Debugger's actions provider.
+ */
[email protected](path="CPPLiteSession", actions={"start",
"stepInto", "stepOver", "stepOut",
+ "pause",
"continue", "kill"})
+public final class CPPLiteActionsProvider extends ActionsProviderSupport {
+
+ private static final Logger LOGGER =
Logger.getLogger(CPPLiteActionsProvider.class.getName());
+
+ private static final Set<Object> ACTIONS = new HashSet<>();
+ private static final Set<Object> ACTIONS_TO_DISABLE = new HashSet<>();
+
+ static {
+ ACTIONS.add (ActionsManager.ACTION_KILL);
+ ACTIONS.add (ActionsManager.ACTION_CONTINUE);
+ ACTIONS.add (ActionsManager.ACTION_PAUSE);
+ ACTIONS.add (ActionsManager.ACTION_START);
+ ACTIONS.add (ActionsManager.ACTION_STEP_INTO);
+ ACTIONS.add (ActionsManager.ACTION_STEP_OVER);
+ ACTIONS.add (ActionsManager.ACTION_STEP_OUT);
+ ACTIONS_TO_DISABLE.addAll(ACTIONS);
+ // Ignore the KILL action
+ ACTIONS_TO_DISABLE.remove(ActionsManager.ACTION_KILL);
+ }
+
+ /** The ReqeustProcessor used by action performers. */
+ private static RequestProcessor actionsRequestProcessor;
+ private static RequestProcessor killRequestProcessor;
+
+ private final CPPLiteDebugger debugger;
+
+ public CPPLiteActionsProvider(ContextProvider contextProvider) {
+ debugger = contextProvider.lookupFirst(null, CPPLiteDebugger.class);
+ // init actions
+ for (Object action : ACTIONS) {
+ setEnabled (action, true);
+ }
+ }
+
+ @Override
+ public Set getActions () {
+ return ACTIONS;
+ }
+
+ @Override
+ public void doAction (Object action) {
+ LOGGER.log(Level.FINE, "CPPLiteDebugger.doAction({0}), is kill = {1}",
new Object[]{action, action == ActionsManager.ACTION_KILL});
+ if (action == ActionsManager.ACTION_KILL) {
+ debugger.finish();
+ } else
+ if (action == ActionsManager.ACTION_CONTINUE) {
+ debugger.resume();
+ } else
+ if (action == ActionsManager.ACTION_PAUSE) {
+ debugger.pause();
+ } else
+ if (action == ActionsManager.ACTION_START) {
+ return ;
+ } else
+ if ( action == ActionsManager.ACTION_STEP_INTO ||
+ action == ActionsManager.ACTION_STEP_OUT ||
+ action == ActionsManager.ACTION_STEP_OVER
+ ) {
+ debugger.doStep (action);
+ }
+ }
+
+ @Override
+ public void postAction(final Object action, final Runnable
actionPerformedNotifier) {
+ if (action == ActionsManager.ACTION_KILL) {
+ synchronized (CPPLiteDebugger.class) {
+ if (killRequestProcessor == null) {
+ killRequestProcessor = new RequestProcessor("CPPLite
debugger finish RP", 1);
+ }
+ }
+ killRequestProcessor.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ doAction(action);
+ } finally {
+ actionPerformedNotifier.run();
+ }
+ }
+ });
+ return ;
+ }
+ setDebugActionsEnabled(false);
+ synchronized (CPPLiteDebugger.class) {
+ if (actionsRequestProcessor == null) {
+ actionsRequestProcessor = new RequestProcessor("CPPLite
debugger actions RP", 1);
+ }
+ }
+ actionsRequestProcessor.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ doAction(action);
+ } finally {
+ actionPerformedNotifier.run();
+ setDebugActionsEnabled(true);
+ }
+ }
+ });
+ }
+
+ private void setDebugActionsEnabled(boolean enabled) {
+ for (Object action : ACTIONS_TO_DISABLE) {
+ setEnabled(action, enabled);
+ }
+ }
+
+}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
index 0193378..87d6587 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
@@ -19,6 +19,8 @@
package org.netbeans.modules.cpplite.debugger;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -27,10 +29,9 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.EventListener;
-import java.util.Iterator;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
@@ -43,6 +44,7 @@ import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerInfo;
import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.DebuggerManagerAdapter;
import org.netbeans.modules.cnd.debugger.gdb2.mi.MICommand;
import org.netbeans.modules.cnd.debugger.gdb2.mi.MICommandInjector;
import org.netbeans.modules.cnd.debugger.gdb2.mi.MIConst;
@@ -54,7 +56,6 @@ import
org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
import org.netbeans.modules.nativeexecution.api.ExecutionEnvironmentFactory;
import org.netbeans.modules.nativeexecution.api.pty.Pty;
import org.netbeans.modules.nativeexecution.api.pty.PtySupport;
-import org.netbeans.spi.debugger.ActionsProviderSupport;
import org.netbeans.spi.debugger.ContextProvider;
import org.netbeans.spi.debugger.DebuggerEngineProvider;
import org.netbeans.spi.debugger.SessionProvider;
@@ -62,6 +63,7 @@ import org.netbeans.spi.debugger.ui.DebuggingView;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.text.Annotatable;
import org.openide.text.Line;
import org.openide.util.Exceptions;
import org.openide.util.Pair;
@@ -72,22 +74,19 @@ import org.openide.util.RequestProcessor;
*
* @author Honza
*/
-public class CPPLiteDebugger extends ActionsProviderSupport {
+public final class CPPLiteDebugger {
private static final Logger LOGGER =
Logger.getLogger(CPPLiteDebugger.class.getName());
- /** The ReqeustProcessor used by action performers. */
- private static RequestProcessor actionsRequestProcessor;
- private static RequestProcessor killRequestProcessor;
-
private CPPLiteDebuggerConfig configuration;
private CPPLiteDebuggerEngineProvider engineProvider;
private ContextProvider contextProvider;
private Process debuggee;
private LiteMIProxy proxy;
- private Object currentLine;
+ private volatile Object currentLine;
private volatile boolean suspended = false;
private final List<StateListener> stateListeners = new
CopyOnWriteArrayList<>();
+ private final BreakpointsHandler breakpointsHandler = new
BreakpointsHandler();
private final ThreadsCollector threadsCollector = new
ThreadsCollector(this);
private volatile CPPThread currentThread;
@@ -98,10 +97,6 @@ public class CPPLiteDebugger extends ActionsProviderSupport {
configuration = contextProvider.lookupFirst(null,
CPPLiteDebuggerConfig.class);
// init engineProvider
engineProvider = (CPPLiteDebuggerEngineProvider)
contextProvider.lookupFirst(null, DebuggerEngineProvider.class);
- // init actions
- for (Iterator it = actions.iterator(); it.hasNext(); ) {
- setEnabled (it.next(), true);
- }
}
void setDebuggee(Process debuggee) {
@@ -125,17 +120,7 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
proxy.waitStarted();
- for (Breakpoint b : DebuggerManager.getDebuggerManager
().getBreakpoints ()) {
- if (b instanceof CPPLiteBreakpoint) {
- CPPLiteBreakpoint cpplineBreakpoint = (CPPLiteBreakpoint) b;
- Line l = cpplineBreakpoint.getLine();
- FileObject source = l.getLookup().lookup(FileObject.class);
- File sourceFile = source != null ? FileUtil.toFile(source) :
null;
- if (sourceFile != null) {
- proxy.send(new Command("-break-insert " +
sourceFile.getAbsolutePath() + ":" + (l.getLineNumber() + 1)));
- }
- }
- }
+ breakpointsHandler.init();
proxy.send(new Command("-gdb-set target-async"));
//proxy.send(new Command("-gdb-set scheduler-locking on"));
@@ -143,55 +128,6 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
proxy.send(new Command("-exec-run"));
}
- // ActionsProvider
.........................................................
-
- private static final Set<Object> actions = new HashSet<>();
- private static final Set<Object> actionsToDisable = new HashSet<>();
- static {
- actions.add (ActionsManager.ACTION_KILL);
- actions.add (ActionsManager.ACTION_CONTINUE);
- actions.add (ActionsManager.ACTION_PAUSE);
- actions.add (ActionsManager.ACTION_START);
- actions.add (ActionsManager.ACTION_STEP_INTO);
- actions.add (ActionsManager.ACTION_STEP_OVER);
- actions.add (ActionsManager.ACTION_STEP_OUT);
- actionsToDisable.addAll(actions);
- // Ignore the KILL action
- actionsToDisable.remove(ActionsManager.ACTION_KILL);
- }
-
- @Override
- public Set getActions () {
- return actions;
- }
-
- @Override
- public void doAction (Object action) {
- LOGGER.log(Level.FINE, "CPPLiteDebugger.doAction({0}), is kill = {1}",
new Object[]{action, action == ActionsManager.ACTION_KILL});
- if (action == ActionsManager.ACTION_KILL) {
- finish ();
- } else
- if (action == ActionsManager.ACTION_CONTINUE) {
- CPPThread thread = currentThread;
- if (thread != null) {
- thread.notifyRunning();
- }
- proxy.send(new Command("-exec-continue --all"));
- } else
- if (action == ActionsManager.ACTION_PAUSE) {
- proxy.send(new Command("-exec-interrupt --all"));
- } else
- if (action == ActionsManager.ACTION_START) {
- return ;
- } else
- if ( action == ActionsManager.ACTION_STEP_INTO ||
- action == ActionsManager.ACTION_STEP_OUT ||
- action == ActionsManager.ACTION_STEP_OVER
- ) {
- doStep (action);
- }
- }
-
private static class CPPLiteInjector implements MICommandInjector {
private final OutputStream out;
@@ -218,51 +154,6 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
}
- @Override
- public void postAction(final Object action, final Runnable
actionPerformedNotifier) {
- if (action == ActionsManager.ACTION_KILL) {
- synchronized (CPPLiteDebugger.class) {
- if (killRequestProcessor == null) {
- killRequestProcessor = new RequestProcessor("CPPLite
debugger finish RP", 1);
- }
- }
- killRequestProcessor.post(new Runnable() {
- @Override
- public void run() {
- try {
- doAction(action);
- } finally {
- actionPerformedNotifier.run();
- }
- }
- });
- return ;
- }
- setDebugActionsEnabled(false);
- synchronized (CPPLiteDebugger.class) {
- if (actionsRequestProcessor == null) {
- actionsRequestProcessor = new RequestProcessor("CPPLite
debugger actions RP", 1);
- }
- }
- actionsRequestProcessor.post(new Runnable() {
- @Override
- public void run() {
- try {
- doAction(action);
- } finally {
- actionPerformedNotifier.run();
- setDebugActionsEnabled(true);
- }
- }
- });
- }
-
- private void setDebugActionsEnabled(boolean enabled) {
- for (Object action : actionsToDisable) {
- setEnabled(action, enabled);
- }
- }
-
MIRecord sendAndGet(String command) throws InterruptedException {
return sendAndGet(command, false);
}
@@ -434,7 +325,7 @@ public class CPPLiteDebugger extends ActionsProviderSupport
{
/**
* should define callStack based on callStackInternal & action.
*/
- private void doStep (Object action) {
+ void doStep (Object action) {
CPPThread thread = currentThread;
String threadId = "";
if (thread != null) {
@@ -450,12 +341,22 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
}
}
- private void finish () {
+ void pause() {
+ proxy.send(new Command("-exec-interrupt --all"));
+ }
+
+ void resume() {
+ threadsCollector.running("all");
+ proxy.send(new Command("-exec-continue --all"));
+ }
+
+ void finish () {
LOGGER.fine("CPPLiteDebugger.finish()");
if (finished) {
LOGGER.fine("finish(): already finished.");
return ;
}
+ breakpointsHandler.dispose();
proxy.send(new Command("-gdb-exit"));
Utils.unmarkCurrent ();
engineProvider.getDestructor().killEngine();
@@ -526,8 +427,10 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
if (frame != null) {
Line currentLine = frame.location();
if (currentLine != null) {
- Utils.markCurrent(new Line[]
{currentLine});
- Utils.showLine(new Line[]
{currentLine});
+ Annotatable[] lines = new
Annotatable[] {currentLine};
+ CPPLiteDebugger.this.currentLine =
lines;
+ Utils.markCurrent(lines);
+ Utils.showLine(lines);
}
}
break;
@@ -645,7 +548,7 @@ public class CPPLiteDebugger extends ActionsProviderSupport
{
}
- public static @NonNull Pair<CPPLiteDebugger, Process> startDebugging
(CPPLiteDebuggerConfig configuration) throws IOException {
+ public static @NonNull Pair<DebuggerEngine, Process> startDebugging
(CPPLiteDebuggerConfig configuration) throws IOException {
DebuggerInfo di = DebuggerInfo.create (
"CPPLiteDebuggerInfo",
new Object[] {
@@ -702,7 +605,7 @@ public class CPPLiteDebugger extends ActionsProviderSupport
{
});
debugger.setDebuggee(debuggee);
- return Pair.of(debugger, new Process() {
+ return Pair.of(es[0], new Process() {
@Override
public OutputStream getOutputStream() {
return pty.getOutputStream();
@@ -734,4 +637,114 @@ public class CPPLiteDebugger extends
ActionsProviderSupport {
}
});
}
+
+ private class BreakpointsHandler extends DebuggerManagerAdapter implements
PropertyChangeListener {
+
+ private final Map<String, CPPLiteBreakpoint> breakpointsById = new
ConcurrentHashMap<>();
+ private final Map<CPPLiteBreakpoint, String> breakpointIds = new
ConcurrentHashMap<>();
+
+ BreakpointsHandler() {
+ }
+
+ private void init() {
+
DebuggerManager.getDebuggerManager().addDebuggerListener(DebuggerManager.PROP_BREAKPOINTS,
this);
+ for (Breakpoint b :
DebuggerManager.getDebuggerManager().getBreakpoints()) {
+ if (b instanceof CPPLiteBreakpoint) {
+ CPPLiteBreakpoint cpplineBreakpoint = (CPPLiteBreakpoint)
b;
+ addBreakpoint(cpplineBreakpoint);
+ }
+ }
+ }
+
+ void dispose() {
+
DebuggerManager.getDebuggerManager().removeDebuggerListener(DebuggerManager.PROP_BREAKPOINTS,
this);
+ for (Breakpoint b :
DebuggerManager.getDebuggerManager().getBreakpoints()) {
+ if (b instanceof CPPLiteBreakpoint) {
+ b.removePropertyChangeListener(this);
+ }
+ }
+ }
+
+ @Override
+ public void breakpointAdded(Breakpoint breakpoint) {
+ if (breakpoint instanceof CPPLiteBreakpoint) {
+ addBreakpoint((CPPLiteBreakpoint) breakpoint);
+ }
+ }
+
+ @Override
+ public void breakpointRemoved(Breakpoint breakpoint) {
+ if (breakpoint instanceof CPPLiteBreakpoint) {
+ removeBreakpoint((CPPLiteBreakpoint) breakpoint);
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ Object source = evt.getSource();
+ if (source instanceof CPPLiteBreakpoint) {
+ String id = breakpointIds.get((CPPLiteBreakpoint) source);
+ if (id != null) {
+ String propertyName = evt.getPropertyName();
+ switch (propertyName) {
+ case Breakpoint.PROP_ENABLED:
+ if (Boolean.TRUE.equals(evt.getNewValue())) {
+ proxy.send(new Command("-break-enable " + id));
+ } else {
+ proxy.send(new Command("-break-disable " +
id));
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void addBreakpoint(CPPLiteBreakpoint breakpoint) {
+ Line l = breakpoint.getLine();
+ FileObject source = l.getLookup().lookup(FileObject.class);
+ File sourceFile = source != null ? FileUtil.toFile(source) : null;
+ if (sourceFile != null) {
+ String disabled = breakpoint.isEnabled() ? "" : "-d ";
+ Command command = new Command("-break-insert " + disabled +
sourceFile.getAbsolutePath() + ":" + (l.getLineNumber() + 1)) {
+ @Override
+ protected void onDone(MIRecord record) {
+ MIValue bkpt = record.results().valueOf("bkpt");
+ if (bkpt instanceof MITList) {
+ breakpointResolved(breakpoint, (MITList) bkpt);
+ }
+ super.onDone(record);
+ }
+
+ @Override
+ protected void onError(MIRecord record) {
+ String msg = record.results().getConstValue("msg");
+ breakpointError(breakpoint, msg);
+ super.onError(record);
+ }
+ };
+ proxy.send(command);
+ }
+ breakpoint.addPropertyChangeListener(this);
+ }
+
+ private void removeBreakpoint(CPPLiteBreakpoint breakpoint) {
+ String id = breakpointIds.remove(breakpoint);
+ if (id != null) {
+ breakpoint.removePropertyChangeListener(this);
+ Command command = new Command("-break-delete " + id);
+ proxy.send(command);
+ }
+ }
+
+ private void breakpointResolved(CPPLiteBreakpoint breakpoint, MITList
list) {
+ breakpoint.setCPPValidity(Breakpoint.VALIDITY.VALID, null);
+ String id = list.getConstValue("number");
+ breakpointsById.put(id, breakpoint);
+ breakpointIds.put(breakpoint, id);
+ }
+
+ private void breakpointError(CPPLiteBreakpoint breakpoint, String msg)
{
+ breakpoint.setCPPValidity(Breakpoint.VALIDITY.INVALID, msg);
+ }
+ }
}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
index b3e945c..6158f6e 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
@@ -258,6 +258,9 @@ public final class CPPThread implements DVThread {
void notifyRunning() {
synchronized (this) {
+ if (status == Status.RUNNING) {
+ return ;
+ }
status = Status.RUNNING;
topFrame = null;
stack = null;
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
index c792b0c..3642570 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
@@ -42,34 +42,33 @@ public class DebuggerAnnotation extends Annotation {
/** Annotation type constant. */
public static final String CALL_STACK_FRAME_ANNOTATION_TYPE = "CallSite";
- private Annotatable annotatable;
- private String type;
-
-
+ private final String type;
+
public DebuggerAnnotation (String type, Annotatable annotatable) {
this.type = type;
- this.annotatable = annotatable;
attach (annotatable);
}
-
+
@Override
public String getAnnotationType () {
return type;
}
-
+
@Override
+ @NbBundle.Messages({"TTP_CurrentPC=Current Program Counter",
+ "TTP_CurrentPC2=Current Target",
+ "TTP_Callsite=Call Stack Line"})
public String getShortDescription () {
- if (type == CURRENT_LINE_ANNOTATION_TYPE)
- return NbBundle.getMessage(DebuggerAnnotation.class,
"TOOLTIP_CURRENT_PC");
- else
- if (type == CURRENT_LINE_ANNOTATION_TYPE2)
- return NbBundle.getMessage(DebuggerAnnotation.class,
"TOOLTIP_CURRENT_PC_2");
- else
- if (type == CURRENT_LINE_PART_ANNOTATION_TYPE)
- return NbBundle.getMessage(DebuggerAnnotation.class,
"TOOLTIP_CURRENT_PC");
- else
- if (type == CALL_STACK_FRAME_ANNOTATION_TYPE)
- return NbBundle.getMessage(DebuggerAnnotation.class,
"TOOLTIP_CALLSITE");
- return null;
+ switch (type) {
+ case CURRENT_LINE_ANNOTATION_TYPE:
+ case CURRENT_LINE_PART_ANNOTATION_TYPE:
+ return Bundle.TTP_CurrentPC();
+ case CURRENT_LINE_ANNOTATION_TYPE2:
+ return Bundle.TTP_CurrentPC2();
+ case CALL_STACK_FRAME_ANNOTATION_TYPE:
+ return Bundle.TTP_Callsite();
+ default:
+ throw new IllegalStateException(type);
+ }
}
}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
index bb51639..f5e90b3 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
@@ -19,7 +19,11 @@
package org.netbeans.modules.cpplite.debugger;
+import java.util.LinkedList;
+import java.util.List;
+
import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.Breakpoint.HIT_COUNT_FILTERING_STYLE;
import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
import org.netbeans.spi.debugger.ui.BreakpointAnnotation;
import org.openide.text.Annotatable;
@@ -42,41 +46,104 @@ public class DebuggerBreakpointAnnotation extends
BreakpointAnnotation {
/** Annotation type constant. */
public static final String DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE
= "DisabledCondBreakpoint"; // NOI18N
- private Annotatable annotatable;
- private String type;
- private CPPLiteBreakpoint breakpoint;
-
-
+ private final String type;
+ private final CPPLiteBreakpoint breakpoint;
+
public DebuggerBreakpointAnnotation (String type, CPPLiteBreakpoint b) {
this.type = type;
- this.annotatable = b.getLine ();
this.breakpoint = b;
+ Annotatable annotatable = b.getLine ();
attach (annotatable);
}
-
+
@Override
public String getAnnotationType () {
return type;
}
-
+
@Override
+ @NbBundle.Messages({"TTP_Breakpoint_Hits=Hits when:",
+ "# {0} - hit count",
+ "TTP_Breakpoint_HitsEqual=Hit count \\= {0}",
+ "# {0} - hit count",
+ "TTP_Breakpoint_HitsGreaterThan=Hit count > {0}",
+ "# {0} - hit count",
+ "TTP_Breakpoint_HitsMultipleOf=Hit count is multiple
of {0}"})
public String getShortDescription () {
- if (type == BREAKPOINT_ANNOTATION_TYPE)
- return NbBundle.getMessage
- (DebuggerBreakpointAnnotation.class, "TOOLTIP_BREAKPOINT");
- else
- if (type == DISABLED_BREAKPOINT_ANNOTATION_TYPE)
- return NbBundle.getMessage
- (DebuggerBreakpointAnnotation.class,
"TOOLTIP_DISABLED_BREAKPOINT");
- else
- if (type == CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE)
- return NbBundle.getMessage
- (DebuggerBreakpointAnnotation.class,
"TOOLTIP_CONDITIONAL_BREAKPOINT");
- else
- if (type == DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE)
- return NbBundle.getMessage
- (DebuggerBreakpointAnnotation.class,
"TOOLTIP_DISABLED_CONDITIONAL_BREAKPOINT");
- return null;
+ List<String> list = new LinkedList<>();
+ //add condition if available
+ String condition = breakpoint.getCondition();
+ if (condition != null) {
+ list.add(condition);
+ }
+
+ // add hit count if available
+ HIT_COUNT_FILTERING_STYLE hitCountFilteringStyle =
breakpoint.getHitCountFilteringStyle();
+ if (hitCountFilteringStyle != null) {
+ int hcf = breakpoint.getHitCountFilter();
+ String tooltip;
+ switch (hitCountFilteringStyle) {
+ case EQUAL:
+ tooltip = Bundle.TTP_Breakpoint_HitsEqual(hcf);
+ break;
+ case GREATER:
+ tooltip = Bundle.TTP_Breakpoint_HitsGreaterThan(hcf);
+ break;
+ case MULTIPLE:
+ tooltip = Bundle.TTP_Breakpoint_HitsMultipleOf(hcf);
+ break;
+ default:
+ throw new IllegalStateException("Unknown
HitCountFilteringStyle: "+hitCountFilteringStyle); // NOI18N
+ }
+ list.add(tooltip);
+ }
+
+ String typeDesc = getBPTypeDescription();
+ if (list.isEmpty()) {
+ return typeDesc;
+ }
+ StringBuilder result = new StringBuilder(typeDesc);
+ //append more information
+ result.append("\n"); // NOI18N
+ result.append(Bundle.TTP_Breakpoint_Hits());
+ for (String text : list) {
+ result.append("\n"); // NOI18N
+ result.append(text);
+ }
+ return result.toString();
+ }
+
+ @NbBundle.Messages({"TTP_Breakpoint=Breakpoint",
+ "TTP_BreakpointDisabled=Disabled Breakpoint",
+ "TTP_BreakpointConditional=Conditional Breakpoint",
+ "TTP_BreakpointDisabledConditional=Disabled
Conditional Breakpoint",
+ "TTP_BreakpointBroken=Broken breakpoint - It is not
possible to stop on this line.",
+ "# {0} - Reason for being invalid",
+ "TTP_BreakpointBrokenInvalid=Broken breakpoint: {0}",
+ "TTP_BreakpointStroke=Deactivated breakpoint"})
+ private String getBPTypeDescription () {
+ if (type.endsWith("_broken")) {
// NOI18N
+ if (breakpoint.getValidity() == Breakpoint.VALIDITY.INVALID) {
+ String msg = breakpoint.getValidityMessage();
+ return Bundle.TTP_BreakpointBrokenInvalid(msg);
+ }
+ return Bundle.TTP_BreakpointBroken();
+ }
+ if (type.endsWith("_stroke")) {
// NOI18N
+ return Bundle.TTP_BreakpointStroke();
+ }
+ switch (type) {
+ case BREAKPOINT_ANNOTATION_TYPE:
+ return Bundle.TTP_Breakpoint();
+ case DISABLED_BREAKPOINT_ANNOTATION_TYPE:
+ return Bundle.TTP_BreakpointDisabled();
+ case CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE:
+ return Bundle.TTP_BreakpointConditional();
+ case DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE:
+ return Bundle.TTP_BreakpointDisabledConditional();
+ default:
+ throw new IllegalStateException(type);
+ }
}
@Override
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java
deleted file mode 100644
index 44b20da..0000000
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.netbeans.modules.cpplite.debugger.breakpoints;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashMap;
-import java.util.Map;
-import org.netbeans.api.debugger.Breakpoint;
-import org.netbeans.api.debugger.DebuggerManager;
-
-import org.netbeans.api.debugger.DebuggerManagerAdapter;
-import org.netbeans.modules.cpplite.debugger.DebuggerBreakpointAnnotation;
-
-
-/**
- * Listens on {@org.netbeans.api.debugger.DebuggerManager} on
- * {@link org.netbeans.api.debugger.DebuggerManager#PROP_BREAKPOINTS}
- * property and annotates JPDA Debugger line breakpoints in NetBeans editor.
- *
- * @author Jan Jancura
- */
-public class BreakpointAnnotationListener extends DebuggerManagerAdapter
-implements PropertyChangeListener {
-
- private Map<CPPLiteBreakpoint, DebuggerBreakpointAnnotation>
breakpointToAnnotation = new HashMap<>();
-
- @Override
- public String[] getProperties () {
- return new String[] {DebuggerManager.PROP_BREAKPOINTS};
- }
-
- /**
- * Called when some breakpoint is added.
- *
- * @param b breakpoint
- */
- @Override
- public void breakpointAdded (Breakpoint b) {
- if (! (b instanceof CPPLiteBreakpoint)) return;
- addAnnotation ((CPPLiteBreakpoint) b);
- }
-
- /**
- * Called when some breakpoint is removed.
- *
- * @param breakpoint
- */
- @Override
- public void breakpointRemoved (Breakpoint b) {
- if (! (b instanceof CPPLiteBreakpoint)) return;
- removeAnnotation (b);
- }
-
- /**
- * This method gets called when a bound property is changed.
- * @param evt A PropertyChangeEvent object describing the event source
- * and the property that has changed.
- */
-
- @Override
- public void propertyChange (PropertyChangeEvent evt) {
- if (evt.getPropertyName () != Breakpoint.PROP_ENABLED) return;
- removeAnnotation ((Breakpoint) evt.getSource ());
- addAnnotation ((CPPLiteBreakpoint) evt.getSource ());
- }
-
- private void addAnnotation (CPPLiteBreakpoint b) {
- breakpointToAnnotation.put (
- b,
- new DebuggerBreakpointAnnotation (
- b.isEnabled () ?
- DebuggerBreakpointAnnotation.BREAKPOINT_ANNOTATION_TYPE :
-
DebuggerBreakpointAnnotation.DISABLED_BREAKPOINT_ANNOTATION_TYPE,
- b
- )
- );
- b.addPropertyChangeListener (
- Breakpoint.PROP_ENABLED,
- this
- );
- }
-
- private void removeAnnotation (Breakpoint b) {
- DebuggerBreakpointAnnotation annotation =
(DebuggerBreakpointAnnotation)
- breakpointToAnnotation.remove (b);
- if (annotation == null) return;
- annotation.detach ();
- b.removePropertyChangeListener (
- Breakpoint.PROP_ENABLED,
- this
- );
- }
-}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java
new file mode 100644
index 0000000..aac9137
--- /dev/null
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.cpplite.debugger.breakpoints;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.Breakpoint.VALIDITY;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.DebuggerManagerAdapter;
+import org.netbeans.modules.cpplite.debugger.DebuggerBreakpointAnnotation;
+
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.text.Annotation;
+import org.openide.text.AnnotationProvider;
+import org.openide.text.Line;
+import org.openide.util.Lookup;
+import org.openide.util.RequestProcessor;
+import org.openide.util.WeakListeners;
+import org.openide.util.WeakSet;
+
+
+/**
+ * This class is called when some file in editor is opened. It changes if
+ * some breakpoints are added or removed.
+ *
+ * @author Jan Jancura, Martin Entlicher
+ */
[email protected](service=org.openide.text.AnnotationProvider.class)
+public class BreakpointAnnotationProvider extends DebuggerManagerAdapter
implements AnnotationProvider {
+
+ private final Map<CPPLiteBreakpoint, Set<Annotation>>
breakpointToAnnotations = new IdentityHashMap<>();
+ private final Set<FileObject> annotatedFiles = new WeakSet<>();
+ private Set<PropertyChangeListener> dataObjectListeners;
+ private volatile boolean breakpointsActive = true;
+ private final RequestProcessor annotationProcessor = new
RequestProcessor("CPP BP Annotation Refresh", 1);
+
+ public BreakpointAnnotationProvider() {
+
DebuggerManager.getDebuggerManager().addDebuggerListener(DebuggerManager.PROP_BREAKPOINTS,
this);
+ }
+
+ @Override
+ public void annotate (Line.Set set, Lookup lookup) {
+ final FileObject fo = lookup.lookup(FileObject.class);
+ if (fo != null) {
+ DataObject dobj = lookup.lookup(DataObject.class);
+ if (dobj != null) {
+ PropertyChangeListener pchl = new PropertyChangeListener() {
+ /** annotate renamed files. */
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if
(DataObject.PROP_PRIMARY_FILE.equals(evt.getPropertyName())) {
+ DataObject dobj = (DataObject) evt.getSource();
+ final FileObject newFO = dobj.getPrimaryFile();
+ annotationProcessor.post(new Runnable() {
+ @Override
+ public void run() {
+ annotate(newFO);
+ }
+ });
+ }
+ }
+ };
+
dobj.addPropertyChangeListener(WeakListeners.propertyChange(pchl, dobj));
+ synchronized (this) {
+ if (dataObjectListeners == null) {
+ dataObjectListeners = new HashSet<>();
+ }
+ // Prevent from GC.
+ dataObjectListeners.add(pchl);
+ }
+ }
+ annotate(fo);
+ }
+ }
+
+ private void annotate (final FileObject fo) {
+ synchronized (breakpointToAnnotations) {
+ for (Breakpoint breakpoint :
DebuggerManager.getDebuggerManager().getBreakpoints()) {
+ if (breakpoint instanceof CPPLiteBreakpoint) {
+ CPPLiteBreakpoint b = (CPPLiteBreakpoint) breakpoint;
+ if (isAt(b, fo)) {
+ if (!breakpointToAnnotations.containsKey(b)) {
+ b.addPropertyChangeListener(this);
+ }
+ removeAnnotations(b); // Remove any staled
breakpoint annotations
+ addAnnotationTo(b);
+ }
+ }
+ }
+ annotatedFiles.add(fo);
+ }
+ }
+
+ private static boolean isAt(CPPLiteBreakpoint b, FileObject fo) {
+ FileObject bfo = (FileObject)
b.getLine().getLookup().lookup(FileObject.class);
+ return fo.equals(bfo);
+ }
+
+ @Override
+ public void breakpointAdded(Breakpoint breakpoint) {
+ if (breakpoint instanceof CPPLiteBreakpoint) {
+ postAnnotationRefresh((CPPLiteBreakpoint) breakpoint, false, true);
+ breakpoint.addPropertyChangeListener (this);
+ }
+ }
+
+ @Override
+ public void breakpointRemoved(Breakpoint breakpoint) {
+ if (breakpoint instanceof CPPLiteBreakpoint) {
+ breakpoint.removePropertyChangeListener (this);
+ postAnnotationRefresh((CPPLiteBreakpoint) breakpoint, true, false);
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ Object source = evt.getSource();
+ if (source instanceof CPPLiteBreakpoint) {
+ String propertyName = evt.getPropertyName ();
+ switch (propertyName) {
+ case Breakpoint.PROP_ENABLED:
+ case Breakpoint.PROP_VALIDITY:
+ case CPPLiteBreakpoint.PROP_CONDITION:
+ postAnnotationRefresh((CPPLiteBreakpoint) source, true,
true);
+ }
+ }
+ }
+
+ void setBreakpointsActive(boolean active) {
+ if (breakpointsActive == active) {
+ return ;
+ }
+ breakpointsActive = active;
+ annotationProcessor.post(new AnnotationRefresh(null, true, true));
+ }
+
+ private void postAnnotationRefresh(CPPLiteBreakpoint b, boolean remove,
boolean add) {
+ annotationProcessor.post(new AnnotationRefresh(b, remove, add));
+ }
+
+ private final class AnnotationRefresh implements Runnable {
+
+ private final CPPLiteBreakpoint b;
+ private final boolean remove;
+ private final boolean add;
+
+ public AnnotationRefresh(CPPLiteBreakpoint b, boolean remove, boolean
add) {
+ this.b = b;
+ this.remove = remove;
+ this.add = add;
+ }
+
+ @Override
+ public void run() {
+ synchronized (breakpointToAnnotations) {
+ if (b != null) {
+ refreshAnnotation(b);
+ } else {
+ List<CPPLiteBreakpoint> bpts = new
ArrayList<>(breakpointToAnnotations.keySet());
+ for (CPPLiteBreakpoint bp : bpts) {
+ refreshAnnotation(bp);
+ }
+ }
+ }
+ }
+
+ private void refreshAnnotation(CPPLiteBreakpoint b) {
+ assert Thread.holdsLock(breakpointToAnnotations);
+ removeAnnotations(b);
+ if (remove) {
+ if (!add) {
+ breakpointToAnnotations.remove(b);
+ }
+ }
+ if (add) {
+ breakpointToAnnotations.put(b, new WeakSet<>());
+ for (FileObject fo : annotatedFiles) {
+ if (isAt(b, fo)) {
+ addAnnotationTo(b);
+ }
+ }
+ }
+ }
+
+ }
+
+ private static String getAnnotationType(CPPLiteBreakpoint b, boolean
isConditional,
+ boolean active) {
+ boolean isInvalid = b.getValidity() == VALIDITY.INVALID;
+ String annotationType = b.isEnabled() ?
+ (isConditional ?
DebuggerBreakpointAnnotation.CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE :
+
DebuggerBreakpointAnnotation.BREAKPOINT_ANNOTATION_TYPE) :
+ (isConditional ?
DebuggerBreakpointAnnotation.DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE :
+
DebuggerBreakpointAnnotation.DISABLED_BREAKPOINT_ANNOTATION_TYPE);
+ if (!active) {
+ annotationType += "_stroke"; // NOI18N
+ } else if (isInvalid && b.isEnabled ()) {
+ annotationType += "_broken"; // NOI18N
+ }
+ return annotationType;
+ }
+
+ private void addAnnotationTo(CPPLiteBreakpoint b) {
+ assert Thread.holdsLock(breakpointToAnnotations);
+ String condition = getCondition(b);
+ boolean isConditional = condition.trim().length() > 0 ||
b.getHitCountFilteringStyle() != null;
+ String annotationType = getAnnotationType(b, isConditional,
breakpointsActive);
+ DebuggerBreakpointAnnotation annotation = new
DebuggerBreakpointAnnotation (annotationType, b);
+ Set<Annotation> bpAnnotations = breakpointToAnnotations.get(b);
+ if (bpAnnotations == null) {
+ Set<Annotation> set = new WeakSet<>();
+ set.add(annotation);
+ breakpointToAnnotations.put(b, set);
+ } else {
+ bpAnnotations.add(annotation);
+ breakpointToAnnotations.put(b, bpAnnotations);
+ }
+ }
+
+ private void removeAnnotations(CPPLiteBreakpoint b) {
+ assert Thread.holdsLock(breakpointToAnnotations);
+ Set<Annotation> annotations = breakpointToAnnotations.remove(b);
+ if (annotations == null) {
+ return ;
+ }
+ for (Annotation a : annotations) {
+ a.detach();
+ }
+ }
+
+ /**
+ * Gets the condition of a breakpoint.
+ * @param b The breakpoint
+ * @return The condition or empty {@link String} if no condition is
supported.
+ */
+ static String getCondition(Breakpoint b) {
+ if (b instanceof CPPLiteBreakpoint) {
+ return ""; // TODO
+ } else {
+ throw new IllegalStateException(b.toString());
+ }
+ }
+}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
index 895f4d5..6939797 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
@@ -19,12 +19,14 @@
package org.netbeans.modules.cpplite.debugger.breakpoints;
-import java.util.Vector;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.modules.cpplite.debugger.CPPLiteDebugger;
import org.netbeans.modules.cpplite.debugger.Utils;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
import org.netbeans.spi.viewmodel.ModelEvent;
import org.netbeans.spi.viewmodel.NodeModel;
import org.netbeans.spi.viewmodel.ModelListener;
@@ -35,16 +37,17 @@ import org.openide.filesystems.FileObject;
*
* @author Jan Jancura
*/
+@DebuggerServiceRegistration(path="BreakpointsView", types={NodeModel.class})
public class BreakpointModel implements NodeModel {
public static final String LINE_BREAKPOINT =
- "org/netbeans/modules/debugger/resources/editor/Breakpoint";
+ "org/netbeans/modules/debugger/resources/breakpointsView/Breakpoint";
public static final String LINE_BREAKPOINT_PC =
- "org/netbeans/modules/debugger/resources/editor/Breakpoint+PC";
+
"org/netbeans/modules/debugger/resources/breakpointsView/BreakpointHit";
public static final String DISABLED_LINE_BREAKPOINT =
- "org/netbeans/modules/debugger/resources/editor/DisabledBreakpoint";
+
"org/netbeans/modules/debugger/resources/breakpointsView/DisabledBreakpoint";
- private Vector<ModelListener> listeners = new Vector<>();
+ private List<ModelListener> listeners = new CopyOnWriteArrayList<>();
// NodeModel implementation
................................................
@@ -138,10 +141,10 @@ public class BreakpointModel implements NodeModel {
public void fireChanges () {
- Vector<ModelListener> v = (Vector<ModelListener>)listeners.clone();
- int i, k = v.size ();
- for (i = 0; i < k; i++)
- v.get(i).modelChanged(new ModelEvent.TreeChanged(this));
+ ModelEvent event = new ModelEvent.TreeChanged(this);
+ for (ModelListener l : listeners) {
+ l.modelChanged(event);
+ }
}
private static CPPLiteDebugger getDebugger () {
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
index 79339f4..e0d9020 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
@@ -23,6 +23,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.Properties;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
import org.openide.cookies.LineCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.URLMapper;
@@ -35,6 +36,7 @@ import org.openide.text.Line;
*
* @author Jan Jancura
*/
+@DebuggerServiceRegistration(types={Properties.Reader.class})
public class BreakpointsReader implements Properties.Reader {
@@ -67,6 +69,10 @@ public class BreakpointsReader implements Properties.Reader {
hitCountFilteringStyle = null;
}
b.setHitCountFilter(hitCountFilter, hitCountFilteringStyle);
+ String condition =
properties.getString(CPPLiteBreakpoint.PROP_CONDITION, null);
+ if (condition != null && !condition.isEmpty()) {
+ b.setCondition(condition);
+ }
if (properties.getBoolean (Breakpoint.PROP_ENABLED, true))
b.enable ();
else
@@ -77,21 +83,25 @@ public class BreakpointsReader implements Properties.Reader
{
@Override
public void write (Object object, Properties properties) {
CPPLiteBreakpoint b = (CPPLiteBreakpoint) object;
- FileObject fo = (FileObject) b.getLine ().getLookup ().
- lookup (FileObject.class);
- properties.setString("url", fo.toURL().toString());
- properties.setInt (
- "lineNumber",
- b.getLine ().getLineNumber ()
- );
- properties.setString (
- Breakpoint.PROP_GROUP_NAME,
- b.getGroupName ()
- );
- properties.setBoolean (Breakpoint.PROP_ENABLED, b.isEnabled ());
- properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER,
b.getHitCountFilter());
- Breakpoint.HIT_COUNT_FILTERING_STYLE style =
b.getHitCountFilteringStyle();
- properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER+"_style", style
!= null ? style.ordinal() : 0); // NOI18N
+ FileObject fo = (FileObject)
b.getLine().getLookup().lookup(FileObject.class);
+ properties.setString("url", fo.toURL().toString());
+ properties.setInt (
+ "lineNumber",
+ b.getLine ().getLineNumber ()
+ );
+ properties.setString (
+ Breakpoint.PROP_GROUP_NAME,
+ b.getGroupName ()
+ );
+ properties.setBoolean (Breakpoint.PROP_ENABLED, b.isEnabled ());
+ properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER,
b.getHitCountFilter());
+ Breakpoint.HIT_COUNT_FILTERING_STYLE style =
b.getHitCountFilteringStyle();
+ properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER+"_style", style !=
null ? style.ordinal() : 0); // NOI18N
+ String condition = b.getCondition();
+ if (condition == null) {
+ condition = "";
+ }
+ properties.setString(CPPLiteBreakpoint.PROP_CONDITION, condition);
}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
index e340d84..6f063ce 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
@@ -21,7 +21,10 @@ package org.netbeans.modules.cpplite.debugger.breakpoints;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerManager;
@@ -41,13 +44,16 @@ import org.openide.util.WeakListeners;
*
* @author Honza
*/
-public class CPPLiteBreakpoint extends Breakpoint {
+public final class CPPLiteBreakpoint extends Breakpoint {
- private boolean enabled = true;
- private Line line;
+ public static final String PROP_CONDITION = "condition";
// NOI18N
+ private volatile boolean enabled = true;
+ private final Map<CPPLiteDebugger, String> ids = new HashMap<>();
+ private final Line line;
+ private volatile String condition;
- /*test?*/public CPPLiteBreakpoint (Line line) {
+ public CPPLiteBreakpoint (Line line) {
this.line = line;
}
@@ -64,7 +70,7 @@ public class CPPLiteBreakpoint extends Breakpoint {
public boolean isEnabled () {
return enabled;
}
-
+
/**
* Disables the breakpoint.
*/
@@ -74,7 +80,7 @@ public class CPPLiteBreakpoint extends Breakpoint {
enabled = false;
firePropertyChange (PROP_ENABLED, Boolean.TRUE, Boolean.FALSE);
}
-
+
/**
* Enables the breakpoint.
*/
@@ -85,18 +91,44 @@ public class CPPLiteBreakpoint extends Breakpoint {
firePropertyChange (PROP_ENABLED, Boolean.FALSE, Boolean.TRUE);
}
+ /**
+ * Get the breakpoint condition, or <code>null</code>.
+ */
+ public String getCondition() {
+ return condition;
+ }
+
+ /**
+ * Set the breakpoint condition.
+ */
+ public void setCondition(String condition) {
+ String oldCondition;
+ synchronized (this) {
+ oldCondition = this.condition;
+ if (Objects.equals(oldCondition, condition)) {
+ return ;
+ }
+ this.condition = condition;
+ }
+ firePropertyChange (PROP_CONDITION, oldCondition, condition);
+ }
+
+ public void setCPPValidity(VALIDITY validity, String reason) {
+ setValidity(validity, reason);
+ }
+
@Override
public GroupProperties getGroupProperties() {
- return new AntGroupProperties();
+ return new CPPGroupProperties();
}
- private final class AntGroupProperties extends GroupProperties {
+ private final class CPPGroupProperties extends GroupProperties {
- private AntEngineListener engineListener;
+ private CPPEngineListener engineListener;
@Override
public String getLanguage() {
- return "ANT";
+ return "C/C++";
}
@Override
@@ -140,7 +172,7 @@ public class CPPLiteBreakpoint extends Breakpoint {
@Override
public DebuggerEngine[] getEngines() {
if (engineListener == null) {
- engineListener = new AntEngineListener();
+ engineListener = new CPPEngineListener();
DebuggerManager.getDebuggerManager().addDebuggerListener(
WeakListeners.create(DebuggerManagerListener.class,
engineListener,
@@ -151,7 +183,7 @@ public class CPPLiteBreakpoint extends Breakpoint {
return null;
}
if (engines.length == 1) {
- if (isAntEngine(engines[0])) {
+ if (isCPPEngine(engines[0])) {
return engines;
} else {
return null;
@@ -160,9 +192,9 @@ public class CPPLiteBreakpoint extends Breakpoint {
// Several running sessions
List<DebuggerEngine> antEngines = null;
for (DebuggerEngine e : engines) {
- if (isAntEngine(e)) {
+ if (isCPPEngine(e)) {
if (antEngines == null) {
- antEngines = new ArrayList<DebuggerEngine>();
+ antEngines = new ArrayList<>();
}
antEngines.add(e);
}
@@ -170,11 +202,11 @@ public class CPPLiteBreakpoint extends Breakpoint {
if (antEngines == null) {
return null;
} else {
- return antEngines.toArray(new DebuggerEngine[]{});
+ return antEngines.toArray(new
DebuggerEngine[antEngines.size()]);
}
}
- private boolean isAntEngine(DebuggerEngine e) {
+ private boolean isCPPEngine(DebuggerEngine e) {
return e.lookupFirst(null, CPPLiteDebugger.class) != null;
}
@@ -183,19 +215,19 @@ public class CPPLiteBreakpoint extends Breakpoint {
return false;
}
- private final class AntEngineListener extends DebuggerManagerAdapter {
+ private final class CPPEngineListener extends DebuggerManagerAdapter {
@Override
public void engineAdded(DebuggerEngine engine) {
- if (isAntEngine(engine)) {
- firePropertyChange(PROP_GROUP_PROPERTIES, null,
AntGroupProperties.this);
+ if (isCPPEngine(engine)) {
+ firePropertyChange(PROP_GROUP_PROPERTIES, null,
CPPGroupProperties.this);
}
}
@Override
public void engineRemoved(DebuggerEngine engine) {
- if (isAntEngine(engine)) {
- firePropertyChange(PROP_GROUP_PROPERTIES, null,
AntGroupProperties.this);
+ if (isCPPEngine(engine)) {
+ firePropertyChange(PROP_GROUP_PROPERTIES, null,
CPPGroupProperties.this);
}
}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
index 8ef0cc8..c166e25 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
@@ -25,11 +25,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+
import org.netbeans.api.debugger.ActionsManager;
import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.spi.debugger.ActionsProvider.Registration;
-import org.netbeans.spi.debugger.ActionsProvider.Registrations;
import org.netbeans.spi.debugger.ActionsProviderSupport;
import org.netbeans.spi.debugger.ui.EditorContextDispatcher;
import org.openide.filesystems.FileObject;
@@ -43,16 +43,16 @@ import org.openide.util.WeakListeners;
@Registration(actions={"toggleBreakpoint"}, activateForMIMETypes={"text/X-c",
"text/X-c++", "text/X-h", "text/X-h++"})
public class CPPLiteBreakpointActionProvider extends ActionsProviderSupport
implements PropertyChangeListener {
-
+
private static final String[] C_MIME_TYPES = new String[] {"text/X-c",
"text/X-c++", "text/X-h", "text/X-h++"}; // NOI18N
private static final Set<String> C_MIME_TYPES_SET = new
HashSet<>(Arrays.asList(C_MIME_TYPES));
-
- private static final Set actions = Collections.singleton (
+
+ private static final Set ACTIONS = Collections.singleton (
ActionsManager.ACTION_TOGGLE_BREAKPOINT
);
-
+
EditorContextDispatcher context = EditorContextDispatcher.getDefault();
-
+
public CPPLiteBreakpointActionProvider () {
for (String mimeType : C_MIME_TYPES) {
context.addPropertyChangeListener(mimeType,
@@ -60,7 +60,7 @@ public class CPPLiteBreakpointActionProvider extends
ActionsProviderSupport
}
setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, false);
}
-
+
/**
* Called when the action is called (action button is pressed).
*
@@ -87,7 +87,7 @@ public class CPPLiteBreakpointActionProvider extends
ActionsProviderSupport
);
//S ystem.out.println("toggle");
}
-
+
/**
* Returns set of actions supported by this ActionsProvider.
*
@@ -95,10 +95,9 @@ public class CPPLiteBreakpointActionProvider extends
ActionsProviderSupport
*/
@Override
public Set getActions () {
- return actions;
+ return ACTIONS;
}
-
-
+
private static Line getCurrentLine () {
FileObject fo = EditorContextDispatcher.getDefault().getCurrentFile();
//System.out.println("n = "+n+", FO = "+fo+" => is ANT =
"+isAntFile(fo));
@@ -107,8 +106,7 @@ public class CPPLiteBreakpointActionProvider extends
ActionsProviderSupport
}
return EditorContextDispatcher.getDefault().getCurrentLine();
}
-
-
+
private static boolean isCFile(FileObject fo) {
if (fo == null) {
return false;
@@ -116,12 +114,12 @@ public class CPPLiteBreakpointActionProvider extends
ActionsProviderSupport
return C_MIME_TYPES_SET.contains(fo.getMIMEType());
}
}
-
+
@Override
public void propertyChange(PropertyChangeEvent evt) {
// We need to push the state there :-(( instead of wait for someone to
be interested in...
boolean enabled = getCurrentLine() != null;
setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, enabled);
}
-
+
}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java
deleted file mode 100644
index 78cde77..0000000
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.netbeans.modules.cpplite.debugger.breakpoints;
-
-import org.netbeans.api.debugger.DebuggerManager;
-import org.openide.modules.OnStart;
-import org.openide.windows.WindowManager;
-
-/**
- *
- * @author lahvac
- */
-@OnStart
-public class LoadBreakpoints implements Runnable {
-
- @Override
- public void run() {
- //to load and assign breakpoints
- //XXX: there must be a better/cleaner way, right?
- WindowManager.getDefault().invokeWhenUIReady(() ->
- DebuggerManager.getDebuggerManager ().getBreakpoints ()
- );
- }
-
-}
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
index c296967..d467600 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
@@ -30,6 +30,7 @@ import org.netbeans.api.debugger.LazyDebuggerManagerListener;
import org.netbeans.api.debugger.Properties;
import org.netbeans.api.debugger.Session;
import org.netbeans.api.debugger.Watch;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
/**
* Listens on DebuggerManager and:
@@ -39,6 +40,7 @@ import org.netbeans.api.debugger.Watch;
*
* @author Jan Jancura
*/
+@DebuggerServiceRegistration(types={LazyDebuggerManagerListener.class})
public class PersistenceManager implements LazyDebuggerManagerListener {
@Override
diff --git
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
index d657e09..b0e30d7 100644
---
a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
+++
b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
@@ -85,7 +85,7 @@ public class DebuggingViewSupportImpl extends
DebuggingView.DVSupport implements
@Override
public void resume() {
- debugger.doAction(ActionsManager.ACTION_CONTINUE);
+
session.getCurrentEngine().getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
}
@Override
diff --git
a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java
new file mode 100644
index 0000000..2d9d4bd
--- /dev/null
+++
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.cpplite.debugger;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import junit.framework.Test;
+
+import org.netbeans.api.debugger.DebuggerEngine;
+import org.netbeans.junit.NbModuleSuite;
+import org.netbeans.junit.NbTestCase;
+
+public abstract class AbstractDebugTest extends NbTestCase {
+
+ protected DebuggerEngine engine;
+ protected CPPLiteDebugger debugger;
+
+ private final int[] suspendCount = new int[]{0};
+ private final int[] resumeCount = new int[]{0};
+
+ protected AbstractDebugTest(String s) {
+ super(s);
+ }
+
+ protected final static void compileC(String name, File wd) throws
IOException, InterruptedException {
+ Process compile = new ProcessBuilder("gcc", "-o", name, "-g", name +
".c").directory(wd).start();
+ assertEquals(0, compile.waitFor());
+ }
+
+ protected final static void compileCPP(String name, File wd) throws
IOException, InterruptedException {
+ Process compile = new ProcessBuilder("g++", "-o", name, "-g", name +
".cpp").directory(wd).start();
+ assertEquals(0, compile.waitFor());
+ }
+
+ protected final void startDebugging(String name, File wd) throws
IOException {
+ engine = CPPLiteDebugger.startDebugging(new
CPPLiteDebuggerConfig(Arrays.asList(new File(wd, name).getAbsolutePath()),
wd)).first();
+ debugger = engine.lookupFirst(null, CPPLiteDebugger.class);
+ debugger.addStateListener(new CPPLiteDebugger.StateListener() {
+ @Override
+ public void suspended(boolean suspended) {
+ int[] count;
+ if (suspended) {
+ count = suspendCount;
+ } else {
+ count = resumeCount;
+ }
+ synchronized (count) {
+ count[0]++;
+ count.notifyAll();
+ }
+ }
+
+ @Override
+ public void finished() {
+ }
+
+ @Override
+ public void currentThread(CPPThread thread) {
+ }
+
+ @Override
+ public void currentFrame(CPPFrame frame) {
+ }
+ });
+ }
+
+ protected final void waitSuspended(int count) throws InterruptedException {
+ synchronized (suspendCount) {
+ while (suspendCount[0] < count) {
+ suspendCount.wait();
+ }
+ }
+ }
+
+ protected final void waitResumed(int count) throws InterruptedException {
+ synchronized (resumeCount) {
+ while (resumeCount[0] < count) {
+ resumeCount.wait();
+ }
+ }
+ }
+
+ protected final void assertStoppedAt(URI file, int line) {
+ CPPFrame currentFrame = debugger.getCurrentFrame();
+ assertNotNull(currentFrame);
+ assertEquals(file, currentFrame.getSourceURI());
+ assertEquals(line, currentFrame.getLine());
+ }
+
+ public static Test suite() {
+ return NbModuleSuite.emptyConfiguration().gui(false).suite();
+ }
+}
diff --git
a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java
new file mode 100644
index 0000000..f80bee8
--- /dev/null
+++
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.cpplite.debugger;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import junit.framework.Test;
+
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.junit.NbModuleSuite;
+import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
+import org.openide.cookies.LineCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
+
+/**
+ * Tests C/C++ debugger breakpoints.
+ */
+public class BreakpointsTest extends AbstractDebugTest {
+
+ public BreakpointsTest (String s) {
+ super (s);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ clearWorkDir();
+ }
+
+ public void testBreakpoints() throws Exception {
+ File wd = getWorkDir();
+ FileObject source = FileUtil.createData(FileUtil.toFileObject(wd),
"breakpoints.c");
+ try (OutputStream os = source.getOutputStream();
+ Writer w = new OutputStreamWriter(os)) {
+ w.append("#include<stdio.h>\n" +
+ "\n" +
+ "long double loop(unsigned int N) {\n" +
+ " unsigned int i;\n" +
+ " long double f = 1;\n" +
+ " long double s = 0;\n" +
+ " for (i = 1; i <= N; i++) {\n" +
+ " f *= i;\n" +
+ " s += i;\n" +
+ " f /= s/i;\n" +
+ " }\n" +
+ " return f;\n" +
+ "}\n" +
+ "\n" +
+ "int main(int argc, char** args) {\n" +
+ " int N = 100;\n" +
+ " long double r = loop(N);\n" +
+ " printf(\"Result(%d) = %.40Lg\\n\", N, r);\n" +
+ "}");
+ }
+ compileC("breakpoints", wd);
+ LineCookie lc =
DataObject.find(source).getLookup().lookup(LineCookie.class);
+ assertNotNull(lc);
+ CPPLiteBreakpoint bp8 = new
CPPLiteBreakpoint(lc.getLineSet().getCurrent(7));
+ CPPLiteBreakpoint bp9 = new
CPPLiteBreakpoint(lc.getLineSet().getCurrent(8));
+ bp9.disable();
+ DebuggerManager.getDebuggerManager().addBreakpoint(bp8);
+ DebuggerManager.getDebuggerManager().addBreakpoint(bp9);
+ startDebugging("breakpoints", wd);
+
+ waitSuspended(1);
+ assertStoppedAt(source.toURI(), 8);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(1);
+ waitSuspended(2);
+ assertStoppedAt(source.toURI(), 8);
+
+ bp9.enable();
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(2);
+ waitSuspended(3);
+ assertStoppedAt(source.toURI(), 9);
+
+ CPPLiteBreakpoint bp10 = new
CPPLiteBreakpoint(lc.getLineSet().getCurrent(9));
+ DebuggerManager.getDebuggerManager().addBreakpoint(bp10);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(3);
+ waitSuspended(4);
+ assertStoppedAt(source.toURI(), 10);
+
+ DebuggerManager.getDebuggerManager().removeBreakpoint(bp8);
+ DebuggerManager.getDebuggerManager().removeBreakpoint(bp9);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(4);
+ waitSuspended(5);
+ assertStoppedAt(source.toURI(), 10);
+
+ bp10.disable();
+
+ bp8 = new CPPLiteBreakpoint(lc.getLineSet().getCurrent(7));
+ DebuggerManager.getDebuggerManager().addBreakpoint(bp8);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(5);
+ waitSuspended(6);
+ assertStoppedAt(source.toURI(), 8);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(5);
+ waitSuspended(6);
+ assertStoppedAt(source.toURI(), 8);
+
+ bp8.disable();
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+ waitResumed(6);
+
+ engine.getActionsManager().doAction(ActionsManager.ACTION_KILL);
+ }
+
+ public static Test suite() {
+ return NbModuleSuite.emptyConfiguration()
+ .addTest(BreakpointsTest.class)
+ .enableModules(".*", ".*")
+ .gui(false)
+ .suite();
+ }
+}
diff --git
a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
index 0361a20..a2042dd 100644
---
a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
+++
b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
@@ -23,12 +23,11 @@ import java.io.File;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
-import java.util.Arrays;
import junit.framework.Test;
+
import org.netbeans.api.debugger.ActionsManager;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.junit.NbModuleSuite;
-import org.netbeans.junit.NbTestCase;
import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
import org.openide.cookies.LineCookie;
import org.openide.filesystems.FileObject;
@@ -40,7 +39,7 @@ import org.openide.loaders.DataObject;
*
* @author Jan Jancura
*/
-public class StepTest extends NbTestCase {
+public class StepTest extends AbstractDebugTest {
public StepTest (String s) {
super (s);
@@ -55,7 +54,7 @@ public class StepTest extends NbTestCase {
File wd = getWorkDir();
FileObject source = FileUtil.createData(FileUtil.toFileObject(wd),
"main.cpp");
try (OutputStream os = source.getOutputStream();
- Writer w = new OutputStreamWriter(os)) {
+ Writer w = new OutputStreamWriter(os)) {
w.append("#include <iostream>\n" +
"\n" +
"void test(void) {\n" +
@@ -70,69 +69,25 @@ public class StepTest extends NbTestCase {
" std::cout << \"Hello, second time!\" <<
std::endl;\n" +
"}");
}
- Process compile = new ProcessBuilder("g++", "-o", "main", "-g",
"main.cpp").directory(wd).start();
- assertEquals(0, compile.waitFor());
+ compileCPP("main", wd);
LineCookie lc =
DataObject.find(source).getLookup().lookup(LineCookie.class);
assertNotNull(lc);
DebuggerManager.getDebuggerManager().addBreakpoint(new
CPPLiteBreakpoint(lc.getLineSet().getCurrent(4)));
- CPPLiteDebugger d = CPPLiteDebugger.startDebugging(new
CPPLiteDebuggerConfig(Arrays.asList(new File(wd, "main").getAbsolutePath()),
wd)).first();
- int[] suspendCount = new int[1];
- int[] resumeCount = new int[1];
- d.addStateListener(new CPPLiteDebugger.StateListener() {
- @Override
- public void suspended(boolean suspended) {
- int[] count;
- if (suspended) {
- count = suspendCount;
- } else {
- count = resumeCount;
- }
- synchronized (count) {
- count[0]++;
- count.notifyAll();
- }
- }
-
- @Override
- public void finished() {
- }
-
- @Override
- public void currentThread(CPPThread thread) {
- }
+ startDebugging("main", wd);
- @Override
- public void currentFrame(CPPFrame frame) {
- }
- });
+ waitSuspended(1);
- synchronized (suspendCount) {
- while (suspendCount[0] < 1) {
- suspendCount.wait();
- }
- }
+ assertStoppedAt(source.toURI(), 5);
- //on line 4, there is a breakpoint and the PC
- assertEquals(2, lc.getLineSet().getCurrent(4).getAnnotationCount());
+ engine.getActionsManager().doAction(ActionsManager.ACTION_STEP_OVER);
- d.doAction(ActionsManager.ACTION_STEP_OVER);
+ waitResumed(1);
- synchronized (resumeCount) {
- while (resumeCount[0] < 1) {
- resumeCount.wait();
- }
- }
+ waitSuspended(2);
- synchronized (suspendCount) {
- while (suspendCount[0] < 2) {
- suspendCount.wait();
- }
- }
+ assertStoppedAt(source.toURI(), 6);
- //on line 4, there is a breakpoint
- assertEquals(1, lc.getLineSet().getCurrent(4).getAnnotationCount());
- //PC:
- assertEquals(1, lc.getLineSet().getCurrent(5).getAnnotationCount());
+ engine.getActionsManager().doAction(ActionsManager.ACTION_KILL);
}
public static Test suite() {
diff --git a/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
b/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
index f35418a..3602993 100644
--- a/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
+++ b/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
@@ -195,7 +195,7 @@ public abstract class Breakpoint {
/**
* Get group properties of the breakpoint.
- * These are implementation-defined group properties as oposed to {@link
#getGroupName()},
+ * These are implementation-defined group properties as opposed to {@link
#getGroupName()},
* which returns user-defined group name.
* <p>
* These properties are used by the Breakpoint Window to show a tree
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists