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 <martin.entlic...@oracle.com>
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.
+ */
+@ActionsProvider.Registration(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
+ */
+@org.openide.util.lookup.ServiceProvider(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: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to