Bug 540324: [R-Debug] Add support of server side tracepoint/breakpoint
manager

Change-Id: Ia3d8d6fcd7af534f998ec6dcaae2dc1d8e7b8dce
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RDbg.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RDbg.java
index dfa32a9..80a69a9 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RDbg.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/console/core/RDbg.java
@@ -20,6 +20,9 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.debug.core.DebugEvent;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.ecommons.io.FileUtil;
 
 import org.eclipse.statet.ltk.model.core.elements.ISourceStructElement;
@@ -36,35 +39,36 @@
 /**
  * Helper for rj.server.dbg in Eclipse/StatET
  */
+@NonNullByDefault
 public class RDbg {
 	
 	
 	public static String getElementId(IRLangSourceElement element) {
-		ISourceStructElement parent = element.getSourceParent();
+		ISourceStructElement parent= element.getSourceParent();
 		if (!(parent instanceof IRLangSourceElement)
 				|| (parent.getElementType() & IRElement.MASK_C1) == IRElement.C1_SOURCE ) {
 			return element.getId();
 		}
-		final StringBuilder sb = new StringBuilder(element.getId());
-		element = (IRLangSourceElement) parent;
+		final StringBuilder sb= new StringBuilder(element.getId());
+		element= (IRLangSourceElement) parent;
 		while (true) {
 			sb.insert(0, '/');
 			sb.insert(0, element.getId());
-			parent = element.getSourceParent();
+			parent= element.getSourceParent();
 			if (!(parent instanceof IRLangSourceElement)
 					|| (parent.getElementType() & IRElement.MASK_C1) == IRElement.C1_SOURCE ) {
 				return sb.toString();
 			}
-			element = (IRLangSourceElement) parent;
+			element= (IRLangSourceElement) parent;
 		}
 	}
 	
 	public static long getTimestamp(final ISourceUnit su, final IProgressMonitor monitor) {
 		if (su.isSynchronized() && su.getResource() != null) {
-			final FileUtil fileUtil = FileUtil.getFileUtil(su.getResource());
+			final FileUtil fileUtil= FileUtil.getFileUtil(su.getResource());
 			if (fileUtil != null) {
 				try {
-					return fileUtil.getTimeStamp(monitor)/1000;
+					return fileUtil.getTimeStamp(monitor);
 				}
 				catch (final CoreException e) {
 				}
@@ -74,49 +78,47 @@
 	}
 	
 	public static SrcfileData createRJSrcfileData(final IResource resource) {
-		final IPath location = resource.getLocation();
+		final IPath location= resource.getLocation();
 		return new SrcfileData(resource.getFullPath().toPortableString(),
 				(location != null) ? location.toString() : null,
-				resource.getLocalTimeStamp()/1000 );
+				resource.getLocalTimeStamp() );
 	}
 	
 	public static int[] createRJSrcref(final IRSrcref srcref) {
-		if (srcref == null || srcref.getFirstLine() < 0) {
-			return null;
-		}
-		final int[] array = new int[6];
+		final int[] array= new int[6];
+		
 		if (srcref.getFirstLine() >= 0) {
-			array[Srcref.BEGIN_LINE] = srcref.getFirstLine() + 1;
+			array[Srcref.BEGIN_LINE]= srcref.getFirstLine() + 1;
 		}
 		else {
-			array[Srcref.BEGIN_LINE] = Srcref.NA;
+			array[Srcref.BEGIN_LINE]= Srcref.NA;
 		}
 		if (srcref.getFirstColumn() >= 0) {
-			array[Srcref.BEGIN_COLUMN] = srcref.getFirstColumn() + 1;
+			array[Srcref.BEGIN_COLUMN]= srcref.getFirstColumn() + 1;
 		}
 		else {
-			array[Srcref.BEGIN_COLUMN] = Srcref.NA;
+			array[Srcref.BEGIN_COLUMN]= Srcref.NA;
 		}
-		array[Srcref.BEGIN_BYTE] = Srcref.NA;
+		array[Srcref.BEGIN_BYTE]= Srcref.NA;
 		
 		if (srcref.getLastLine() >= 0) {
-			array[Srcref.END_LINE] = srcref.getLastLine() + 1;
+			array[Srcref.END_LINE]= srcref.getLastLine() + 1;
 		}
 		else {
-			array[Srcref.END_LINE] = Srcref.NA;
+			array[Srcref.END_LINE]= Srcref.NA;
 		}
 		if (srcref.getLastColumn() >= 0) {
-			array[Srcref.END_COLUMN] = srcref.getLastColumn() + 1;
+			array[Srcref.END_COLUMN]= srcref.getLastColumn() + 1;
 		}
 		else {
-			array[Srcref.END_COLUMN] = Srcref.NA;
+			array[Srcref.END_COLUMN]= Srcref.NA;
 		}
-		array[Srcref.END_BYTE] = Srcref.NA;
+		array[Srcref.END_BYTE]= Srcref.NA;
 		
 		return array;
 	}
 	
-	public static IRSrcref createStatetSrcref(final int[] data) {
+	public static @Nullable IRSrcref createStatetSrcref(final int @Nullable [] data) {
 		if (data == null || data.length < 6) {
 			return null;
 		}
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
index 110a59f..354540b 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/AbstractRDbgController.java
@@ -32,6 +32,9 @@
 import org.eclipse.debug.core.DebugEvent;
 import org.eclipse.osgi.util.NLS;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.ecommons.io.FileUtil;
 import org.eclipse.statet.ecommons.ts.core.SystemRunnable;
 import org.eclipse.statet.ecommons.ts.core.Tool;
@@ -73,7 +76,6 @@
 import org.eclipse.statet.rj.server.dbg.SetDebugRequest;
 import org.eclipse.statet.rj.server.dbg.SrcfileData;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
-import org.eclipse.statet.rj.server.dbg.TracepointInstallationReport;
 import org.eclipse.statet.rj.server.dbg.TracepointInstallationRequest;
 import org.eclipse.statet.rj.server.dbg.TracepointStatesUpdate;
 
@@ -85,16 +87,19 @@
 		implements IRDataAdapter, ICombinedRDataAdapter {
 	
 	
+	@NonNullByDefault
 	public interface IRControllerTracepointAdapter {
 		
 		
+		void handle(final TracepointEvent event);
+		
 		boolean matchScriptBreakpoint(IRModelSrcref srcref, IProgressMonitor monitor);
 		
-		ElementTracepointInstallationRequest getElementTracepoints(SrcfileData srcfile,
-				IRModelSrcref su, IProgressMonitor monitor );
+		@Nullable ElementTracepointInstallationRequest getElementTracepoints(
+				SrcfileData srcfile, IRModelSrcref su, IProgressMonitor monitor );
 		
-		ElementTracepointInstallationRequest prepareFileElementTracepoints(SrcfileData srcfile,
-				IRSourceUnit su, IProgressMonitor monitor );
+		@Nullable ElementTracepointInstallationRequest prepareFileElementTracepoints(
+				SrcfileData srcfile, IRSourceUnit su, IProgressMonitor monitor );
 		
 		void finishFileElementTracepoints(SrcfileData srcfileData, IRSourceUnit su,
 				ElementTracepointInstallationRequest request, IProgressMonitor monitor );
@@ -102,7 +107,7 @@
 		void installElementTracepoints(ElementTracepointInstallationRequest request,
 				IProgressMonitor monitor );
 		
-		Object toEclipseData(TracepointEvent hit);
+		@Nullable Object toEclipseData(TracepointEvent hit);
 		
 		
 	}
@@ -631,8 +636,7 @@
 	public abstract void exec(TracepointStatesUpdate request,
 			IProgressMonitor monitor) throws CoreException;
 	
-	public abstract TracepointInstallationReport exec(
-			TracepointInstallationRequest request,
+	public abstract void exec(TracepointInstallationRequest request,
 			IProgressMonitor monitor) throws CoreException;
 	
 	@Override
@@ -736,9 +740,19 @@
 	protected void doRequestSuspend(final IProgressMonitor monitor) throws CoreException {
 	}
 	
-	protected void handle(final TracepointEvent event) {
-		if (event.getKind() == TracepointEvent.KIND_ABOUT_TO_HIT) {
-			this.breakpointHit= event;
+	protected void handleTracepointEvents(final List<? extends TracepointEvent> events) {
+		for (final TracepointEvent event : events) {
+			try {
+				if (event.getKind() == TracepointEvent.KIND_ABOUT_TO_HIT) {
+					this.breakpointHit= event;
+				}
+				else {
+					this.breakpointAdapter.handle(event);
+				}
+			}
+			catch (final Exception e) {
+				
+			}
 		}
 	}
 	
@@ -826,7 +840,7 @@
 		}
 		finally {
 			if (breakpointsRequest != null) {
-				if (srcfile.getTimestamp() != getRTimestamp((IRWorkspaceSourceUnit) su, monitor)) {
+				if (srcfile.getTimestamp() != getTimestamp((IRWorkspaceSourceUnit) su, monitor)) {
 					srcfile= null;
 				}
 				this.breakpointAdapter.finishFileElementTracepoints(srcfile, (IRSourceUnit) su,
@@ -849,9 +863,9 @@
 		return null;
 	}
 	
-	private long getRTimestamp(final IWorkspaceSourceUnit su, final IProgressMonitor monitor) {
+	private long getTimestamp(final IWorkspaceSourceUnit su, final IProgressMonitor monitor) {
 		return (su.getWorkingContext() == LTK.PERSISTENCE_CONTEXT) ?
-				su.getResource().getLocalTimeStamp()/1000 :
+				su.getResource().getLocalTimeStamp() :
 				RDbg.getTimestamp(su, monitor);
 	}
 	
@@ -886,7 +900,7 @@
 				
 				return new SrcfileData(
 						(this.lastSrcfile == fileName) ? this.lastSrcfilePath : path.toPortableString(),
-						fileName, getRTimestamp(wsu, monitor) );
+						fileName, getTimestamp(wsu, monitor) );
 			}
 			else {
 				return new SrcfileData(null, fileName, RDbg.getTimestamp(su, monitor));
diff --git a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
index 1bb06eb..6e8e5e3 100644
--- a/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
+++ b/r/org.eclipse.statet.r.console.core/src/org/eclipse/statet/r/nico/impl/RjsController.java
@@ -133,7 +133,6 @@
 import org.eclipse.statet.rj.server.dbg.SetDebugRequest;
 import org.eclipse.statet.rj.server.dbg.SrcfileData;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
-import org.eclipse.statet.rj.server.dbg.TracepointInstallationReport;
 import org.eclipse.statet.rj.server.dbg.TracepointInstallationRequest;
 import org.eclipse.statet.rj.server.dbg.TracepointStatesUpdate;
 import org.eclipse.statet.rj.services.FQRObject;
@@ -353,11 +352,11 @@
 		}
 		
 		@Override
-		protected void handleDbgEvent(final byte dbgOp, final Object event) {
-			if (dbgOp == DbgCmdItem.OP_NOTIFY_TP_EVENT) {
-				handle((TracepointEvent) event);
+		protected void handleDbgEvents(final byte dbgOp, final Object events) {
+			if (dbgOp == DbgCmdItem.OP_NOTIFY_TP_EVENTS) {
+				handleTracepointEvents((List<TracepointEvent>) events);
 			}
-			super.handleDbgEvent(dbgOp, event);
+			super.handleDbgEvents(dbgOp, events);
 		}
 		
 		@Override
@@ -933,15 +932,13 @@
 	}
 	
 	@Override
-	public TracepointInstallationReport exec(final TracepointInstallationRequest request,
+	public void exec(final TracepointInstallationRequest request,
 			final IProgressMonitor monitor) throws CoreException {
 		if (request instanceof FlagTracepointInstallationRequest) {
-			return (TracepointInstallationReport) this.fRjs.execSyncDbgOp(
-					DbgCmdItem.OP_INSTALL_TP_FLAGS, request, monitor );
+			this.fRjs.execSyncDbgOp(DbgCmdItem.OP_INSTALL_TP_FLAGS, request, monitor);
 		}
 		else if (request instanceof ElementTracepointInstallationRequest) {
-			return (TracepointInstallationReport) this.fRjs.execSyncDbgOp(
-					DbgCmdItem.OP_INSTALL_TP_POSITIONS, request, monitor );
+			this.fRjs.execSyncDbgOp(DbgCmdItem.OP_INSTALL_TP_POSITIONS, request, monitor);
 		}
 		else {
 			throw new IllegalArgumentException("request type not supported");
@@ -982,7 +979,7 @@
 		final FunctionCall prepare= createFunctionCall("rj:::.statet.prepareCommand");
 		prepare.add("lines", this.fRObjectFactory.createVector(this.fRObjectFactory.createCharData(lines)));
 		
-		if (srcfile != null && srcref != null) {
+		if (srcfile != null && srcref != null && srcref.getFirstLine() >= 0) {
 			final List<String> attributeNames= new ArrayList<>();
 			final List<RObject> attributeValues= new ArrayList<>();
 			
@@ -999,12 +996,9 @@
 				attributeValues.add(this.fRObjectFactory.createVector(this.fRObjectFactory.createNumData(
 						new double[] { srcfile.getTimestamp() } )));
 			}
-			final int[] rjSrcref= RDbg.createRJSrcref(srcref);
-			if (rjSrcref != null) {
-				attributeNames.add("linesSrcref");
-				attributeValues.add(this.fRObjectFactory.createVector(this.fRObjectFactory.createIntData(
-						rjSrcref )));
-			}
+			attributeNames.add("linesSrcref");
+			attributeValues.add(this.fRObjectFactory.createVector(this.fRObjectFactory.createIntData(
+					RDbg.createRJSrcref(srcref) )));
 			
 			if (attributeNames.size() > 0) {
 				prepare.add("srcfileAttributes", this.fRObjectFactory.createList(
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
index 7d3d98b..1479d7e 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RConsoleRJLaunchDelegate.java
@@ -31,6 +31,7 @@
 import org.eclipse.core.runtime.SubMonitor;
 import org.eclipse.debug.core.ILaunch;
 import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
 import org.eclipse.debug.core.model.IProcess;
 import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
 import org.eclipse.debug.ui.IDebugUIConstants;
@@ -72,6 +73,7 @@
 import org.eclipse.statet.r.nico.impl.RjsController;
 import org.eclipse.statet.r.nico.impl.RjsController.RjsConnection;
 import org.eclipse.statet.rj.server.RjsComConfig;
+import org.eclipse.statet.rj.services.FunctionCall;
 
 
 /**
@@ -91,13 +93,16 @@
 		private final boolean enableRHelp;
 		private final boolean enableRGraphics;
 		private final boolean enableRDbgExt;
+		private final boolean enableRDbg;
 		
 		public ConfigRunnable(final Tool tool, final boolean enableRHelp,
-				final boolean enableRGraphics, final boolean enableRDbgExt) {
+				final boolean enableRGraphics,
+				final boolean enableRDbgExt, final boolean enableRDbg) {
 			this.tool= tool;
 			this.enableRHelp= enableRHelp;
 			this.enableRGraphics= enableRGraphics;
 			this.enableRDbgExt= enableRDbgExt;
+			this.enableRDbg= enableRDbg;
 		}
 		
 		
@@ -138,7 +143,8 @@
 					r.evalVoid("library('rj', quietly= TRUE)", monitor); //$NON-NLS-1$
 				}
 				if (this.enableRHelp) {
-					r.evalVoid(".statet.initHelp()", monitor); //$NON-NLS-1$
+					final FunctionCall fcall= r.createFunctionCall(".statet.initHelp"); //$NON-NLS-1$
+					fcall.evalVoid(monitor);
 				}
 				if (this.enableRGraphics) {
 					try {
@@ -152,8 +158,10 @@
 								monitor );
 					}
 				}
-				if (this.enableRDbgExt) {
-					r.evalVoid(".statet.initDebug()", monitor); //$NON-NLS-1$
+				{	final FunctionCall fcall= r.createFunctionCall(".statet.initDebug"); //$NON-NLS-1$
+					fcall.addLogi("mode", this.enableRDbg); //$NON-NLS-1$
+					fcall.addLogi("ext", this.enableRDbgExt); //$NON-NLS-1$
+					fcall.evalVoid(monitor);
 				}
 			}
 			finally {
@@ -171,7 +179,7 @@
 	}
 	
 	static void initConsoleOptions(final RjsController controller, final IREnvConfiguration rEnv,
-			final ILaunchConfiguration configuration,
+			final ILaunchConfiguration configuration, final String mode,
 			final boolean isStartup) throws CoreException {
 		if (rEnv != null) {
 			final IRPkgManager manager= RCore.getRPkgManager(rEnv.getReference());
@@ -182,7 +190,8 @@
 				controller.getTool(),
 				(rEnv != null && configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RHELP_ENABLED, true)),
 				configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT, true),
-				configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RDBGEXT_ENABLED, true) ));
+				configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RDBGEXT_ENABLED, true),
+				mode.equals(ILaunchManager.DEBUG_MODE) ));
 		if (isStartup) {
 			RConsoleLaunching.scheduleStartupSnippet(controller, configuration);
 		}
@@ -384,7 +393,7 @@
 			
 			m.worked(5);
 			
-			initConsoleOptions(controller, rEnv, configuration, true);
+			initConsoleOptions(controller, rEnv, configuration, mode, true);
 			
 			if (this.addon != null) {
 				this.addon.init(configuration, mode, controller, m);
diff --git a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
index 2f61483..8572854 100644
--- a/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
+++ b/r/org.eclipse.statet.r.console.ui/src/org/eclipse/statet/internal/r/console/ui/launching/RRemoteConsoleLaunchDelegate.java
@@ -592,7 +592,8 @@
 			
 			m.worked(5);
 			
-			RConsoleRJLaunchDelegate.initConsoleOptions(controller, rEnv, configuration, startup);
+			RConsoleRJLaunchDelegate.initConsoleOptions(controller, rEnv, configuration, mode,
+					startup );
 			
 			if (this.addon != null) {
 				this.addon.init(configuration, mode, controller, monitor);
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/RControllerBreakpointAdapter.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/RControllerBreakpointAdapter.java
index 3f87351..eca23cb 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/RControllerBreakpointAdapter.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/RControllerBreakpointAdapter.java
@@ -23,6 +23,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.eclipse.core.resources.IFile;
@@ -51,6 +52,9 @@
 
 import org.eclipse.statet.jcommons.collections.ImCollections;
 import org.eclipse.statet.jcommons.collections.ImList;
+import org.eclipse.statet.jcommons.lang.Immutable;
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 import org.eclipse.statet.jcommons.lang.Nullable;
 
 import org.eclipse.statet.ecommons.text.IMarkerPositionResolver;
@@ -90,18 +94,18 @@
 import org.eclipse.statet.rj.data.REnvironment;
 import org.eclipse.statet.rj.server.dbg.DbgEnablement;
 import org.eclipse.statet.rj.server.dbg.ElementTracepointInstallationRequest;
-import org.eclipse.statet.rj.server.dbg.ElementTracepointPositions;
+import org.eclipse.statet.rj.server.dbg.ElementTracepoints;
 import org.eclipse.statet.rj.server.dbg.FlagTracepointInstallationRequest;
 import org.eclipse.statet.rj.server.dbg.SrcfileData;
 import org.eclipse.statet.rj.server.dbg.Srcref;
 import org.eclipse.statet.rj.server.dbg.Tracepoint;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
-import org.eclipse.statet.rj.server.dbg.TracepointInstallationReport;
 import org.eclipse.statet.rj.server.dbg.TracepointPosition;
 import org.eclipse.statet.rj.server.dbg.TracepointState;
 import org.eclipse.statet.rj.server.dbg.TracepointStatesUpdate;
 
 
+@NonNullByDefault
 public class RControllerBreakpointAdapter implements IRControllerTracepointAdapter,
 		IBreakpointManagerListener, IBreakpointsListener {
 	
@@ -109,7 +113,7 @@
 		
 		private final IRLineBreakpoint breakpoint;
 		
-		private String label;
+		private @Nullable String label;
 		
 		public Position(final int type, final long id, final int[] exprIndex,
 				final IRLineBreakpoint breakpoint) {
@@ -117,7 +121,7 @@
 			this.breakpoint= breakpoint;
 		}
 		
-		void setExprSrcref(final int[] srcref) {
+		void setExprSrcref(final int @Nullable [] srcref) {
 			this.exprSrcref= srcref;
 		}
 		
@@ -125,22 +129,22 @@
 			return this.breakpoint;
 		}
 		
-		void setLabel(final String label) {
+		void setLabel(final @Nullable String label) {
 			this.label= label;
 		}
 		
-		public String getElementLabel() {
+		public @Nullable String getElementLabel() {
 			return this.label;
 		}
 		
 	}
 	
-	private static class Element extends ElementTracepointPositions {
+	private static class Element extends ElementTracepoints {
 		
 		private final IResource resource;
 		
 		public Element(final SrcfileData fileInfo, final IResource resource,
-				final String elementId, final int[] elementSrcref) {
+				final String elementId, final int @Nullable [] elementSrcref) {
 			super(fileInfo, elementId, elementSrcref);
 			this.resource= resource;
 		}
@@ -157,7 +161,6 @@
 	}
 	
 	
-	
 	private static class UpdateData {
 		
 		private final IResource resource;
@@ -170,21 +173,73 @@
 		
 	}
 	
-	private static class ElementData implements IRBreakpoint.ITargetData {
+	private static class ElementInstallData {
 		
-		final Element installed;
 		
-		public ElementData(final Element installed) {
+		private final IResource resource;
+		private final String elementId;
+		private final @Nullable String elementLabel;
+		
+		
+		public ElementInstallData(final IResource resource, final String elementId,
+				final @Nullable String elementLabel) {
+			this.resource= resource;
+			this.elementId= elementId;
+			this.elementLabel= elementLabel;
+		}
+		
+		public ElementInstallData(final IResource resource, final String elementId,
+				final Position position) {
+			this.resource= resource;
+			this.elementId= elementId;
+			this.elementLabel= position.getElementLabel();
+		}
+		
+		
+		@Override
+		public int hashCode() {
+			return this.resource.hashCode() ^ Objects.hashCode(this.elementId);
+		}
+		
+		@Override
+		public boolean equals(final @Nullable Object obj) {
+			if (this == obj) {
+				return true;
+			}
+			if (obj instanceof ElementInstallData) {
+				final ElementInstallData other= (ElementInstallData) obj;
+				return (this.resource.equals(other.resource)
+						&& Objects.equals(this.elementId, other.elementId)
+						&& Objects.equals(this.elementLabel, other.elementLabel) );
+			}
+			return false;
+		}
+		
+		
+	}
+	
+	private static class BreakpointTargetData implements IRBreakpoint.ITargetData, Immutable {
+		
+		
+		private final @Nullable ElementInstallData latest;
+		
+		private final @Nullable ElementInstallData installed;
+		
+		
+		public BreakpointTargetData(final @Nullable ElementInstallData latest,
+				final @Nullable ElementInstallData installed) {
+			this.latest= latest;
 			this.installed= installed;
 		}
 		
+		
 		@Override
 		public boolean isInstalled() {
 			return (this.installed != null);
 		}
 		
 		@Override
-		public <T> T getAdapter(final Class<T> adapterType) {
+		public <T> @Nullable T getAdapter(final Class<T> adapterType) {
 			return null;
 		}
 		
@@ -198,7 +253,7 @@
 		}
 		
 		@Override
-		public <T> T getAdapter(final Class<T> adapter) {
+		public <T> @Nullable T getAdapter(final Class<T> adapter) {
 			return null;
 		}
 		
@@ -212,7 +267,7 @@
 		}
 		
 		@Override
-		public <T> T getAdapter(final Class<T> adapter) {
+		public <T> @Nullable T getAdapter(final Class<T> adapter) {
 			return null;
 		}
 		
@@ -231,9 +286,11 @@
 	private final AtomicInteger positionModCounter= new AtomicInteger();
 	private final Object positionUpdatesLock= this.positionUpdatesBreakpoints;
 	
+	private final Object targetUpdateLock= new Object();
+	
 	private final Object flagUpdateLock= new Object();
 	private boolean flagUpdateCheck;
-	private ITargetData exceptionBreakpointData;
+	private @Nullable ITargetData exceptionBreakpointData;
 	
 	private final List<IRBreakpoint> stateUpdatesBreakpoints= new ArrayList<>();
 	private final Object stateUpdatesLock= this.stateUpdatesBreakpoints;
@@ -305,7 +362,7 @@
 						{	final FlagTracepointInstallationRequest request= createFlagRequest(
 									(exceptionAvailable) ? Boolean.TRUE : null );
 							if (request != null) {
-								installFlagTracepoints(request, breakpoints, monitor);
+								installFlagTracepoints(request, monitor);
 							}
 						}
 						synchronized (RControllerBreakpointAdapter.this.positionUpdatesLock) {
@@ -317,13 +374,7 @@
 						}
 						{	final List<Element> positions= getPendingElementPositions(monitor);
 							installElementTracepoints(
-									new ElementTracepointInstallationRequest(positions),
-									monitor );
-						}
-						synchronized (RControllerBreakpointAdapter.this.stateUpdatesMap) {
-							final List<TracepointState> states= getPendingTracepointStates();
-							RControllerBreakpointAdapter.this.controller.exec(
-									new TracepointStatesUpdate(states, true),
+									new ElementTracepointInstallationRequest(positions, true),
 									monitor );
 						}
 					}
@@ -423,7 +474,7 @@
 												!= exceptionAvailable ) ?
 										Boolean.valueOf(exceptionAvailable) : null );
 						if (request != null) {
-							installFlagTracepoints(request, breakpoints, monitor);
+							installFlagTracepoints(request, monitor);
 						}
 					}
 				}
@@ -432,7 +483,7 @@
 					final List<Element> positions= getPendingElementPositions(monitor);
 					if (!positions.isEmpty()) {
 						installElementTracepoints(
-								new ElementTracepointInstallationRequest(positions),
+								new ElementTracepointInstallationRequest(positions, false),
 								monitor );
 					}
 					else {
@@ -478,6 +529,44 @@
 		}
 	}
 	
+	private @Nullable IRBreakpoint getRBreakpoint(final TracepointEvent event) {
+		if (event.getFilePath() == null) {
+			return null;
+		}
+		try {
+			final IWorkspace workspace= ResourcesPlugin.getWorkspace();
+			final IMarker marker;
+			if (event.getType() == Tracepoint.TYPE_EB) {
+				final IResource resource= workspace.getRoot();
+				final IMarker[] markers= resource.findMarkers(RExceptionBreakpoint.R_EXCEPTION_BREAKPOINT_MARKER_TYPE, false, IResource.DEPTH_ZERO);
+				marker= (markers.length > 0) ? markers[0] : null;
+			}
+			else {
+				final IResource resource= workspace.getRoot().getFile(new Path(event.getFilePath()));
+				marker= resource.getMarker(event.getId());
+			}
+			final IBreakpoint b= this.breakpointManager.getBreakpoint(marker);
+			return (b instanceof IRBreakpoint) ? (IRBreakpoint) b : null;
+		}
+		catch (final CoreException e) {
+			return null;
+		}
+	}
+	
+	@Override
+	public void handle(final TracepointEvent event) {
+		switch (event.getKind()) {
+		case TracepointEvent.KIND_INSTALLED:
+		case TracepointEvent.KIND_UNINSTALLED:
+			if (event.getType() == Tracepoint.TYPE_EB) {
+				updateFlagInstallData(event);
+			}
+			else {
+				updateElementInstallData(event);
+			}
+		}
+	}
+	
 	/** Call in R thread */
 	@Override
 	public boolean matchScriptBreakpoint(final IRModelSrcref srcref,
@@ -534,7 +623,7 @@
 	}
 	
 	
-	private FlagTracepointInstallationRequest createFlagRequest(final Boolean exception) {
+	private @Nullable FlagTracepointInstallationRequest createFlagRequest(final @Nullable Boolean exception) {
 		int count= 0;
 		if (exception != null) {
 			count++;
@@ -556,63 +645,22 @@
 	
 	/** Call in R thread */
 	private void installFlagTracepoints(final FlagTracepointInstallationRequest request,
-			final IBreakpoint[] breakpoints,
 			final IProgressMonitor monitor) {
-		TracepointInstallationReport report= null;
 		try {
-			report= this.controller.exec(request, monitor);
+			this.controller.exec(request, monitor);
 		}
 		catch (final Exception e) {
 			RDebugCorePlugin.log(new Status(IStatus.ERROR, RDebugCorePlugin.BUNDLE_ID, 0,
 					"An error occurred when updating breakpoints in R." , e ));
 		}
 		finally {
-			report(request, breakpoints, report);
 			checkUpdates();
 		}
 	}
 	
-	private void report(final FlagTracepointInstallationRequest request,
-			final IBreakpoint[] breakpoints, final TracepointInstallationReport report) {
-		IRBreakpoint.ITargetData exceptionData= null;
-		final byte[] types= request.getTypes();
-		final int[] results= report.getInstallationResults();
-		for (int i= 0; i < types.length; i++) {
-			if (types[i] == Tracepoint.TYPE_EB) {
-				switch (results[i]) {
-				case TracepointInstallationReport.FOUND_SET:
-					exceptionData= INSTALLED_DATA;
-					break;
-				case TracepointInstallationReport.FOUND_UNSET:
-					exceptionData= NOT_INSTALLED_DATA;
-					break;
-				}
-			}
-		}
-		if (exceptionData == null) {
-			return;
-		}
-		synchronized (this.flagUpdateLock) {
-			if (exceptionData != null) {
-				this.exceptionBreakpointData= exceptionData;
-			}
-		}
-		
-		for (int i= 0; i < breakpoints.length; i++) {
-			if (breakpoints[i] instanceof IRBreakpoint) {
-				final IRBreakpoint breakpoint= (IRBreakpoint) breakpoints[i];
-				if (breakpoint.getBreakpointType() == RDebugModel.R_EXCEPTION_BREAKPOINT_TYPE_ID) {
-					if (exceptionData != null) {
-						breakpoint.registerTarget(this.debugTarget, exceptionData);
-					}
-				}
-			}
-		}
-	}
-	
 	/** Call in R thread */
 	@Override
-	public ElementTracepointInstallationRequest getElementTracepoints(final SrcfileData srcfile,
+	public @Nullable ElementTracepointInstallationRequest getElementTracepoints(final SrcfileData srcfile,
 			final IRModelSrcref srcref,
 			final IProgressMonitor monitor) {
 		try {
@@ -631,7 +679,7 @@
 		}
 	}
 	
-	private ElementTracepointInstallationRequest doGetElementTracepoints(final SrcfileData srcfile,
+	private @Nullable ElementTracepointInstallationRequest doGetElementTracepoints(final SrcfileData srcfile,
 			final IRModelSrcref srcref,
 			final IRWorkspaceSourceUnit rSourceUnit,
 			final IProgressMonitor monitor) throws CoreException, BadLocationException {
@@ -677,7 +725,7 @@
 					lines[j]= document.getLineOfOffset(region.getOffset()) + 1;
 					lines[j+1]= document.getLineOfOffset(region.getOffset()+region.getLength()) + 1;
 				}
-				HashMap<String, Element> map= null;
+				HashMap<String, @Nullable Element> map= null;
 				List<String> cleanup= null;
 				for (final IRLineBreakpoint breakpoint : breakpoints) {
 					try {
@@ -702,14 +750,14 @@
 										if (map == null) {
 											map= new HashMap<>(elements.size());
 										}
-										final ElementData breakpointData= (ElementData) breakpoint.getTargetData(this.debugTarget);
-										if (breakpointData != null && breakpointData.installed != null
-												&& !elementId.equals(breakpointData.installed.getElementId()) ) {
+										final BreakpointTargetData breakpointData= (BreakpointTargetData) breakpoint.getTargetData(this.debugTarget);
+										if (breakpointData != null && breakpointData.latest != null
+												&& !elementId.equals(breakpointData.latest.elementId) ) {
 											if (cleanup == null) {
 												cleanup= new ArrayList<>();
 											}
-											if (!cleanup.contains(breakpointData.installed.getElementId())) {
-												cleanup.add(breakpointData.installed.getElementId());
+											if (!cleanup.contains(breakpointData.latest.elementId)) {
+												cleanup.add(breakpointData.latest.elementId);
 											}
 										}
 										addBreakpoint(map, srcfile, rSourceUnit.getResource(),
@@ -740,7 +788,7 @@
 					final ArrayList<Element> list= new ArrayList<>(map.size());
 					addElements(list, map, false);
 					if (!list.isEmpty()) {
-						return new ElementTracepointInstallationRequest(list);
+						return new ElementTracepointInstallationRequest(list, false);
 					}
 				}
 			}
@@ -752,7 +800,7 @@
 	}
 	
 	@Override
-	public ElementTracepointInstallationRequest prepareFileElementTracepoints(final SrcfileData srcfile,
+	public @Nullable ElementTracepointInstallationRequest prepareFileElementTracepoints(final SrcfileData srcfile,
 			final IRSourceUnit su,
 			final IProgressMonitor monitor) {
 		try {
@@ -762,7 +810,7 @@
 				if (request != null) {
 					installElementTracepoints(request, monitor);
 					
-					for (final ElementTracepointPositions positions : request.getRequests()) {
+					for (final ElementTracepoints positions : request.getRequests()) {
 						if (positions instanceof Element) {
 							this.currentRequests.add(((Element) positions).getResource());
 						}
@@ -782,27 +830,28 @@
 	
 	@Override
 	public void finishFileElementTracepoints(final SrcfileData srcfile, final IRSourceUnit su,
-			ElementTracepointInstallationRequest request, final IProgressMonitor monitor) {
-		if (request != null) {
-			for (final ElementTracepointPositions positions : request.getRequests()) {
-				if (positions instanceof Element) {
-					this.currentRequests.remove(((Element) positions).getResource());
-				}
+			final ElementTracepointInstallationRequest request, final IProgressMonitor monitor) {
+		for (final ElementTracepoints positions : request.getRequests()) {
+			if (positions instanceof Element) {
+				this.currentRequests.remove(((Element) positions).getResource());
 			}
-			
-			if (srcfile != null) {
-				try {
-					request= doPrepareFileElementTracepoints(srcfile, (IRWorkspaceSourceUnit) su,
-							monitor );
-				}
-				catch (final CoreException e) {}
+		}
+		
+		ElementTracepointInstallationRequest installRequest= request;
+		if (srcfile != null) {
+			try {
+				installRequest= doPrepareFileElementTracepoints(srcfile, (IRWorkspaceSourceUnit) su,
+						monitor );
 			}
+			catch (final CoreException e) {}
+		}
+		if (installRequest != null) {
 			installElementTracepoints(request, monitor);
 		}
 	}
 	
-	private ElementTracepointInstallationRequest doPrepareFileElementTracepoints(final SrcfileData srcfile,
-			final IRWorkspaceSourceUnit rSourceUnit,
+	private @Nullable ElementTracepointInstallationRequest doPrepareFileElementTracepoints(
+			final SrcfileData srcfile, final IRWorkspaceSourceUnit rSourceUnit,
 			final IProgressMonitor monitor) throws CoreException {
 		if (rSourceUnit.getResource().getType() != IResource.FILE
 				|| !rSourceUnit.getResource().exists()) {
@@ -815,7 +864,7 @@
 		if (breakpoints.isEmpty()) {
 			return null;
 		}
-		Map<String, Element> map= null;
+		Map<String, @Nullable Element> map= null;
 		for (final IRLineBreakpoint breakpoint : breakpoints) {
 			try {
 				final String breakpointType= breakpoint.getBreakpointType();
@@ -847,7 +896,7 @@
 			final ArrayList<Element> list= new ArrayList<>(map.size());
 			addElements(list, map, false);
 			if (!list.isEmpty()) {
-				return new ElementTracepointInstallationRequest(list);
+				return new ElementTracepointInstallationRequest(list, false);
 			}
 		}
 		return null;
@@ -856,16 +905,21 @@
 	@Override
 	public void installElementTracepoints(final ElementTracepointInstallationRequest request,
 			final IProgressMonitor monitor) {
-		TracepointInstallationReport report= null;
 		try {
-			report= this.controller.exec(request, monitor);
+			synchronized (RControllerBreakpointAdapter.this.stateUpdatesMap) {
+				final List<TracepointState> states= getPendingTracepointStates();
+				RControllerBreakpointAdapter.this.controller.exec(
+						new TracepointStatesUpdate(states, request.getReset()),
+						monitor );
+			}
+			
+			this.controller.exec(request, monitor);
 		}
 		catch (final Exception e) {
 			RDebugCorePlugin.log(new Status(IStatus.ERROR, RDebugCorePlugin.BUNDLE_ID, 0,
 					"An error occurred when updating breakpoints in R." , e ));
 		}
 		finally {
-			report(request, report);
 			checkUpdates();
 		}
 	}
@@ -878,12 +932,12 @@
 			if (this.positionUpdatesBreakpoints.isEmpty() && this.positionUpdatesElements.isEmpty()) {
 				return ImCollections.emptyList();
 			}
-			breakpointsToUpdate= this.positionUpdatesBreakpoints.toArray(new IRBreakpoint[this.positionUpdatesBreakpoints.size()]);
+			breakpointsToUpdate= this.positionUpdatesBreakpoints.toArray(new @NonNull IRBreakpoint[this.positionUpdatesBreakpoints.size()]);
 			this.positionUpdatesBreakpoints.clear();
-			elementsToUpdate= this.positionUpdatesElements.toArray(new UpdateData[this.positionUpdatesElements.size()]);
+			elementsToUpdate= this.positionUpdatesElements.toArray(new @NonNull UpdateData[this.positionUpdatesElements.size()]);
 			this.positionUpdatesElements.clear();
 		}
-		final Map<IResource, @Nullable Map<String, Element>> resourceMap= new HashMap<>();
+		final Map<IResource, Map<String, @Nullable Element>> resourceMap= new HashMap<>();
 		// by resources
 		for (int i= 0; i < breakpointsToUpdate.length; i++) {
 			final IRBreakpoint rBreakpoint= breakpointsToUpdate[i];
@@ -891,20 +945,20 @@
 			if (breakpointType == RDebugModel.R_LINE_BREAKPOINT_TYPE_ID
 					|| breakpointType == RDebugModel.R_METHOD_BREAKPOINT_TYPE_ID) {
 				try {
-					final ElementData breakpointData= (ElementData) rBreakpoint.getTargetData(this.debugTarget);
-					if (breakpointData != null && breakpointData.installed != null) {
-						Map<String, Element> map= resourceMap.get(breakpointData.installed.getResource());
+					final BreakpointTargetData breakpointData= (BreakpointTargetData) rBreakpoint.getTargetData(this.debugTarget);
+					if (breakpointData != null && breakpointData.latest != null) {
+						Map<String, @Nullable Element> map= resourceMap.get(breakpointData.latest.resource);
 						if (map == null) {
 							map= new HashMap<>();
-							resourceMap.put(breakpointData.installed.getResource(), map);
+							resourceMap.put(breakpointData.latest.resource, map);
 						}
-						map.put(breakpointData.installed.getElementId(), null);
+						map.put(breakpointData.latest.elementId, null);
 					}
 					
 					if (rBreakpoint.isRegistered()) {
 						final IResource resource= rBreakpoint.getMarker().getResource();
 						if (!resourceMap.containsKey(resource)) {
-							resourceMap.put(resource, new HashMap<String, Element>());
+							resourceMap.put(resource, new HashMap<String, @Nullable Element>());
 						}
 					}
 					else if (breakpointData != null) {
@@ -918,7 +972,7 @@
 		}
 		for (int i= 0; i < elementsToUpdate.length; i++) {
 			final UpdateData updateData= elementsToUpdate[i];
-			Map<String, Element> map= resourceMap.get(updateData.resource);
+			Map<String, @Nullable Element> map= resourceMap.get(updateData.resource);
 			if (map == null) {
 				map= new HashMap<>();
 				resourceMap.put(updateData.resource, map);
@@ -927,9 +981,9 @@
 		}
 		
 		int n= 0;
-		for (final Entry<IResource, Map<String, Element>> resourceEntry : resourceMap.entrySet()) {
+		for (final Entry<IResource, Map<String, @Nullable Element>> resourceEntry : resourceMap.entrySet()) {
 			final IResource resource= resourceEntry.getKey();
-			final Map<String, Element> map= resourceEntry.getValue();
+			final Map<String, @Nullable Element> map= resourceEntry.getValue();
 			try {
 				final SrcfileData srcfile= RDbg.createRJSrcfileData(resource);
 				if (resource.exists() && resource.getType() == IResource.FILE) {
@@ -962,14 +1016,14 @@
 		}
 		
 		final List<Element> list= new ArrayList<>(n);
-		for (final Entry<IResource, Map<String, Element>> resourceEntry : resourceMap.entrySet()) {
+		for (final Entry<IResource, Map<String, @Nullable Element>> resourceEntry : resourceMap.entrySet()) {
 			addElements(list, resourceEntry.getValue(), true);
 		}
 		return list;
 	}
 	
 	private void doGetPendingElementPositions(final SrcfileData srcfile, final IRWorkspaceSourceUnit rSourceUnit,
-			final IRBreakpoint[] breakpointsToUpdate, final Map<String, Element> map,
+			final IRBreakpoint[] breakpointsToUpdate, final Map<String, @Nullable Element> map,
 			final IProgressMonitor monitor) throws CoreException {
 		final int modCounter= this.positionModCounter.get();
 		final List<IRLineBreakpoint> breakpoints= RDebugModel.getLineBreakpoints(
@@ -1017,7 +1071,7 @@
 				}
 			}
 		}
-		for (final Entry<String, Element> elementEntry : map.entrySet()) {
+		for (final Entry<String, @Nullable Element> elementEntry : map.entrySet()) {
 			if (elementEntry.getValue() == null) {
 				addClear(map, srcfile, rSourceUnit.getResource(), elementEntry.getKey());
 			}
@@ -1050,98 +1104,155 @@
 		}
 	}
 	
-	/** Call in R thread */
-	private void report(final ElementTracepointInstallationRequest request,
-			final TracepointInstallationReport report) {
-		if (request == null) {
-			throw new NullPointerException();
-		}
-		final List<? extends ElementTracepointPositions> elements= request.getRequests();
-		final int l= elements.size();
-		int[] results= null;
-		if (report != null && report.getInstallationResults().length == l) {
-			results= report.getInstallationResults();
+//	/** Call in R thread */
+//	private void report(final ElementTracepointInstallationRequest request,
+//			final TracepointInstallationReport report) {
+//		if (request == null) {
+//			throw new NullPointerException();
+//		}
+//		final List<? extends ElementTracepoints> elements= request.getRequests();
+//		final int l= elements.size();
+//		int[] results= null;
+//		if (report != null && report.getInstallationResults().length == l) {
+//			results= report.getInstallationResults();
+//		}
+//		
+//		if (results == null) {
+//			return; // ?
+//		}
+//		
+//		ArrayList<Element> cleanup= null;
+//		List<IRLineBreakpoint> updated= null;
+//		
+//		for (int i= 0; i < l; i++) {
+//			if (results[i] == TracepointInstallationReport.FOUND_UNCHANGED
+//					|| !(elements.get(i) instanceof Element)) {
+//				continue;
+//			}
+//			
+//			final Element current= (Element) elements.get(i);
+//			final boolean installed= (results[i] == TracepointInstallationReport.FOUND_SET);
+//			for (final TracepointPosition position : current.getPositions()) {
+//				if (!(position instanceof Position)) {
+//					continue;
+//				}
+//				final IRLineBreakpoint breakpoint= ((Position) position).getBreakpoint();
+//				try {
+//					if (breakpoint == null || !breakpoint.isRegistered()) {
+//						continue;
+//					}
+//					final IMarker marker= breakpoint.getMarker();
+//					if (marker == null || marker.getId() != position.getId()) {
+//						continue;
+//					}
+//					final ElementTargetData newData= new ElementTargetData((installed) ? current : null);
+//					final ElementTargetData oldData= (ElementTargetData) breakpoint.registerTarget(this.debugTarget, newData);
+////					if (oldData != null && oldData.isInstalled()
+////							&& oldData.getElementId().equals(current.getElementId())) {
+////						if (cleanup == null) {
+////							cleanup= new ArrayList<>(l-i);
+////						}
+////						if (!contains(cleanup, oldData.installed)) {
+////							cleanup.add(oldData.installed);
+////						}
+////					}
+//					if (updated == null) {
+//						updated= new ArrayList<>(l - i);
+//					}
+//					updated.add(breakpoint);
+//				}
+//				catch (final CoreException e) {} // only isRegistered
+//			}
+//		}
+//		
+//		if (cleanup != null) {
+//			for (int i= 0; i < cleanup.size(); i++) {
+//				final Element current= cleanup.get(i);
+//				for (final TracepointPosition position : current.getPositions()) {
+//					if (!(position instanceof Position)) {
+//						continue;
+//					}
+//					final IRBreakpoint breakpoint= ((Position) position).getBreakpoint();
+//					try {
+//						if (breakpoint == null || !breakpoint.isRegistered()) {
+//							continue;
+//						}
+//						final ElementTargetData data= (ElementTargetData) breakpoint.getTargetData(this.debugTarget);
+//						if (data != null && data.isInstalled()) {
+//							breakpoint.registerTarget(this.debugTarget, new ElementTargetData(null));
+//						}
+//					}
+//					catch (final CoreException e) {} // only isRegistered
+//				}
+//			}
+//		}
+//		
+//		if (updated != null) {
+//			synchronized (this.stateUpdatesLock) {
+//				for (int i= 0; i < updated.size(); i++) {
+//					scheduleStateUpdate(updated.get(i));
+//				}
+//			}
+//		}
+//	}
+	
+	private void updateFlagInstallData(final TracepointEvent event) {
+		final IRBreakpoint.ITargetData newData;
+		switch (event.getKind()) {
+		case TracepointEvent.KIND_INSTALLED:
+			newData= INSTALLED_DATA;
+			break;
+		case TracepointEvent.KIND_UNINSTALLED:
+			newData= NOT_INSTALLED_DATA;
+			break;
+		default:
+			return;
 		}
 		
-		if (results == null) {
-			return; // ?
+		synchronized (this.flagUpdateLock) {
+			this.exceptionBreakpointData= newData;
 		}
 		
-		ArrayList<Element> cleanup= null;
-		List<IRLineBreakpoint> updated= null;
-		
-		for (int i= 0; i < l; i++) {
-			if (results[i] == TracepointInstallationReport.FOUND_UNCHANGED
-					|| !(elements.get(i) instanceof Element)) {
-				continue;
-			}
-			
-			final Element current= (Element) elements.get(i);
-			final boolean installed= (results[i] == TracepointInstallationReport.FOUND_SET);
-			for (final TracepointPosition position : current.getPositions()) {
-				if (!(position instanceof Position)) {
-					continue;
-				}
-				final IRLineBreakpoint breakpoint= ((Position) position).getBreakpoint();
-				try {
-					if (breakpoint == null || !breakpoint.isRegistered()) {
-						continue;
-					}
-					final IMarker marker= breakpoint.getMarker();
-					if (marker == null || marker.getId() != position.getId()) {
-						continue;
-					}
-					final ElementData newData= new ElementData((installed) ? current : null);
-					final ElementData oldData= (ElementData) breakpoint.registerTarget(this.debugTarget, newData);
-					if (oldData != null && oldData.installed != null
-							&& oldData.installed.getElementId().equals(current.getElementId())) {
-						if (cleanup == null) {
-							cleanup= new ArrayList<>(l-i);
-						}
-						if (!contains(cleanup, oldData.installed)) {
-							cleanup.add(oldData.installed);
-						}
-					}
-					if (updated == null) {
-						updated= new ArrayList<>(l - i);
-					}
-					updated.add(breakpoint);
-				}
-				catch (final CoreException e) {} // only isRegistered
-			}
+		final IRBreakpoint breakpoint= getRBreakpoint(event);
+		if (breakpoint == null) {
+			return;
 		}
 		
-		if (cleanup != null) {
-			for (int i= 0; i < cleanup.size(); i++) {
-				final Element current= cleanup.get(i);
-				for (final TracepointPosition position : current.getPositions()) {
-					if (!(position instanceof Position)) {
-						continue;
-					}
-					final IRBreakpoint breakpoint= ((Position) position).getBreakpoint();
-					try {
-						if (breakpoint == null || !breakpoint.isRegistered()) {
-							continue;
-						}
-						final ElementData data= (ElementData) breakpoint.getTargetData(this.debugTarget);
-						if (data != null && data.installed == current) {
-							breakpoint.registerTarget(this.debugTarget, new ElementData(null));
-						}
-					}
-					catch (final CoreException e) {} // only isRegistered
-				}
-			}
+		breakpoint.registerTarget(this.debugTarget, newData);
+	}
+	
+	private void updateElementInstallData(final TracepointEvent event) {
+		final IRBreakpoint breakpoint= getRBreakpoint(event);
+		if (breakpoint == null) {
+			return;
+		}
+		final IMarker marker= breakpoint.getMarker();
+		if (marker == null) {
+			return;
 		}
 		
-		if (updated != null) {
-			synchronized (this.stateUpdatesLock) {
-				for (int i= 0; i < updated.size(); i++) {
-					scheduleStateUpdate(updated.get(i));
-				}
-			}
+		final ElementInstallData installData;
+		switch (event.getKind()) {
+		case TracepointEvent.KIND_INSTALLED:
+			installData= new ElementInstallData(marker.getResource(),
+					event.getElementId(), event.getLabel() );
+			break;
+		case TracepointEvent.KIND_UNINSTALLED:
+			installData= null;
+			break;
+		default:
+			return;
+		}
+		synchronized (this.targetUpdateLock) {
+			final BreakpointTargetData oldData= (BreakpointTargetData) breakpoint.getTargetData(this.debugTarget);
+			breakpoint.registerTarget(this.debugTarget,
+					new BreakpointTargetData(
+							(oldData != null) ? oldData.latest : null,
+							installData ));
 		}
 	}
 	
+	
 	private void addBreakpoint(final Map<String, Element> map,
 			final SrcfileData srcfile, final IResource resource, final String elementId,
 			final IRLineBreakpoint breakpoint, final RLineBreakpointValidator validator,
@@ -1154,8 +1265,9 @@
 		
 		Element elementPositions= map.get(elementId);
 		if (elementPositions == null) {
+			final IRSrcref elementSrcref= validator.computeElementSrcref();
 			elementPositions= new Element(srcfile, resource, elementId,
-					RDbg.createRJSrcref(validator.computeElementSrcref()) );
+					(elementSrcref != null) ? RDbg.createRJSrcref(elementSrcref) : null );
 			map.put(elementId, elementPositions);
 		}
 		final IMarker marker= breakpoint.getMarker();
@@ -1184,11 +1296,13 @@
 		final Position position= new Position(type, marker.getId(), rExpressionIndex,
 				breakpoint );
 		if (!elementPositions.getPositions().contains(position)) {
-			if (elementPositions.getElementSrcref() != null) {
-				final IRSrcref rExpressionSrcref= validator.computeRExpressionSrcref();
-				if (rExpressionSrcref != null) {
-					position.setExprSrcref(Srcref.diff(elementPositions.getElementSrcref(),
-							RDbg.createRJSrcref(rExpressionSrcref) ));
+			{	final int[] elementSrcref= elementPositions.getElementSrcref();
+				if (elementSrcref != null) {
+					final IRSrcref rExpressionSrcref= validator.computeRExpressionSrcref();
+					if (rExpressionSrcref != null) {
+						position.setExprSrcref(Srcref.diff(elementSrcref,
+								RDbg.createRJSrcref(rExpressionSrcref) ));
+					}
 				}
 			}
 			{	String label= validator.computeSubLabel();
@@ -1199,6 +1313,22 @@
 			}
 			elementPositions.getPositions().add(position);
 		}
+		
+		final ElementInstallData latestData= new ElementInstallData(marker.getResource(),
+				elementId, position );
+		synchronized (this.targetUpdateLock) {
+			final BreakpointTargetData oldData= (BreakpointTargetData) breakpoint.getTargetData(this.debugTarget);
+			if (oldData != null && Objects.equals(latestData, oldData.latest)) {
+				return;
+			}
+			breakpoint.registerTarget(this.debugTarget,
+					new BreakpointTargetData(
+							latestData,
+							(oldData != null) ? oldData.installed : null ));
+		}
+		synchronized (this.stateUpdatesLock) {
+			scheduleStateUpdate(breakpoint);
+		}
 	}
 	
 	private void addClear(final Map<String, Element> map,
@@ -1212,8 +1342,9 @@
 		map.put(elementId, elementPositions);
 	}
 	
-	private void addElements(final List<Element> list, final Map<String, Element> map, final boolean delete) {
-		final Collection<Element> values= map.values();
+	private void addElements(final List<Element> list, final Map<String, @Nullable Element> map,
+			final boolean delete) {
+		final Collection<@Nullable Element> values= map.values();
 		for (final Element elementPositions : values) {
 			if (elementPositions == null) {
 				continue;
@@ -1285,7 +1416,7 @@
 	}
 	
 	@Override
-	public void breakpointsRemoved(final IBreakpoint[] breakpoints, final IMarkerDelta[] deltas) {
+	public void breakpointsRemoved(final IBreakpoint[] breakpoints, final @Nullable IMarkerDelta[] deltas) {
 		boolean check= false;
 		try {
 			for (int i= 0; i < breakpoints.length; i++) {
@@ -1353,7 +1484,7 @@
 	}
 	
 	@Override
-	public void breakpointsChanged(final IBreakpoint[] breakpoints, final IMarkerDelta[] deltas) {
+	public void breakpointsChanged(final IBreakpoint[] breakpoints, final @Nullable IMarkerDelta[] deltas) {
 		boolean check= false;
 		try {
 			for (int i= 0; i < breakpoints.length; i++) {
@@ -1395,7 +1526,7 @@
 	}
 	
 	
-	protected void deactivateBreakpoint(final IResource resource, final long id) {
+	protected void deactivateBreakpoint(final @Nullable IResource resource, final long id) {
 		if (resource == null) {
 			return;
 		}
@@ -1481,7 +1612,7 @@
 				iter.hasNext(); ) {
 			final TracepointState[] states;
 			final List<TracepointState> statesList= iter.next();
-			states= statesList.toArray(new TracepointState[statesList.size()]);
+			states= statesList.toArray(new @NonNull TracepointState[statesList.size()]);
 			Arrays.sort(states);
 			
 			boolean delete= true;
@@ -1555,7 +1686,7 @@
 	}
 	
 	
-	private boolean contains(final List<? extends Object> list, final Object object) {
+	private boolean contains(final List<?> list, final Object object) {
 		for (int i= 0; i < list.size(); i++) {
 			if (list.get(i) == object) {
 				return true;
@@ -1573,7 +1704,7 @@
 		return false;
 	}
 	
-	private int getLineNumber(final IMarker marker, final IMarkerPositionResolver resolver) {
+	private int getLineNumber(final IMarker marker, final @Nullable IMarkerPositionResolver resolver) {
 		return (resolver != null) ?
 				resolver.getLine(marker) :
 				marker.getAttribute(IMarker.LINE_NUMBER, -1);
@@ -1592,7 +1723,7 @@
 					|| elementType == IRLineBreakpoint.R_S4_METHOD_ELEMENT_TYPE ));
 	}
 	
-	private TracepointState createState(final IRLineBreakpoint breakpoint,
+	private @Nullable TracepointState createState(final IRLineBreakpoint breakpoint,
 			final IMarker marker) throws CoreException {
 		final int type;
 		int flags= breakpoint.isEnabled() ? TracepointState.FLAG_ENABLED : 0;
@@ -1620,20 +1751,21 @@
 		final String expr= (breakpoint.isConditionEnabled()) ?
 				breakpoint.getConditionExpr() : null;
 		
-		final ElementData breakpointData= (ElementData) breakpoint.getTargetData(this.debugTarget);
-		final Element installed= (breakpointData != null) ? breakpointData.installed : null;
+		final BreakpointTargetData breakpointData= (BreakpointTargetData) breakpoint.getTargetData(this.debugTarget);
 		final ModelPosition modelPosition= RLineBreakpointValidator.getModelPosition(breakpoint);
 		
 		String elementId= null;
 		String elementLabel= null;
 		int[] index= null;
-		if (installed != null) {
-			elementId= installed.getElementId();
-			for (final Position position : installed.getPositions()) {
-				if (position.getBreakpoint() == breakpoint) {
-					elementLabel= position.getElementLabel();
-					break;
-				}
+		if (breakpointData != null) {
+			if (breakpointData.installed != null) {
+				elementId= breakpointData.installed.elementId;
+				elementLabel= breakpointData.installed.elementLabel;
+			}
+			if (breakpointData.latest != null
+					&& elementId == null) {
+				elementId= breakpointData.latest.elementId;
+				elementLabel= breakpointData.latest.elementLabel;
 			}
 		}
 		if (modelPosition != null) {
@@ -1666,7 +1798,7 @@
 				elementId, index, elementLabel, flags, expr);
 	}
 	
-	private TracepointState createState(final IRExceptionBreakpoint breakpoint,
+	private @Nullable TracepointState createState(final IRExceptionBreakpoint breakpoint,
 			final IMarker marker) throws CoreException {
 		final int type;
 		final int flags= breakpoint.isEnabled() ? TracepointState.FLAG_ENABLED : 0;
@@ -1687,23 +1819,9 @@
 	
 	
 	@Override
-	public Object toEclipseData(final TracepointEvent event) {
+	public @Nullable Object toEclipseData(final TracepointEvent event) {
 		try {
-			if (event == null) {
-				return null;
-			}
-			IRBreakpoint breakpoint= null;
-			if (event.getFilePath() != null) {
-				final IWorkspace workspace= ResourcesPlugin.getWorkspace();
-				final IResource resource= (event.getType() == Tracepoint.TYPE_EB) ?
-						workspace.getRoot() :
-						workspace.getRoot().getFile(new Path(event.getFilePath()));
-				final IMarker marker= resource.getMarker(event.getId());
-				final IBreakpoint b= this.breakpointManager.getBreakpoint(marker);
-				if (b instanceof IRBreakpoint) {
-					breakpoint= (IRBreakpoint) b;
-				}
-			}
+			final IRBreakpoint breakpoint= getRBreakpoint(event);
 			String label= event.getLabel();
 			if (event.getType() == Tracepoint.TYPE_EB) {
 				if (label == null || label.equals("*")) {
@@ -1712,14 +1830,9 @@
 			}
 			else if (label == null && breakpoint instanceof IRLineBreakpoint) {
 				final IRLineBreakpoint lineBreakpoint= (IRLineBreakpoint) breakpoint;
-				final ElementData breakpointData= (ElementData) breakpoint.getTargetData(this.debugTarget);
+				final BreakpointTargetData breakpointData= (BreakpointTargetData) breakpoint.getTargetData(this.debugTarget);
 				if (breakpointData != null && breakpointData.installed != null) {
-					for (final Position position : breakpointData.installed.getPositions()) {
-						if (position.getBreakpoint() == breakpoint) {
-							label= position.getElementLabel();
-							break;
-						}
-					}
+					label= breakpointData.installed.elementLabel;
 				}
 				if (label == null) {
 					try {
@@ -1733,11 +1846,11 @@
 			}
 			switch (event.getType()) {
 			case Tracepoint.TYPE_FB:
-				return new MethodBreakpointStatus(event, label, breakpoint);
+				return new TracepointEventMethodBreakpointStatus(event, label, breakpoint);
 			case Tracepoint.TYPE_EB:
-				return new ExceptionBreakpointStatus(event, label, breakpoint);
+				return new TracepointEventExceptionBreakpointStatus(event, label, breakpoint);
 			default:
-				return new BreakpointStatus(event, label, breakpoint);
+				return new TracepointEventBreakpointStatus(event, label, breakpoint);
 			}
 		}
 		catch (final Exception e) {
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/BreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventBreakpointStatus.java
similarity index 67%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/BreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventBreakpointStatus.java
index 4f50975..1301ed7 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/BreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventBreakpointStatus.java
@@ -14,22 +14,26 @@
 
 package org.eclipse.statet.internal.r.debug.core.breakpoints;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RBreakpointStatus;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
 
 
-public class BreakpointStatus implements IRBreakpointStatus {
+@NonNullByDefault
+public class TracepointEventBreakpointStatus implements RBreakpointStatus {
 	
 	
 	protected final TracepointEvent event;
 	
-	protected final String label;
-	protected final IRBreakpoint breakpoint;
+	protected final @Nullable String label;
+	protected final @Nullable IRBreakpoint breakpoint;
 	
 	
-	public BreakpointStatus(final TracepointEvent event, final String label,
-			final IRBreakpoint breakpoint) {
+	public TracepointEventBreakpointStatus(final TracepointEvent event,
+			final @Nullable String label, final @Nullable IRBreakpoint breakpoint) {
 		this.event= event;
 		this.label= label;
 		this.breakpoint= breakpoint;
@@ -46,12 +50,12 @@
 	}
 	
 	@Override
-	public String getLabel() {
+	public @Nullable String getLabel() {
 		return this.label;
 	}
 	
 	@Override
-	public IRBreakpoint getBreakpoint() {
+	public @Nullable IRBreakpoint getBreakpoint() {
 		return this.breakpoint;
 	}
 	
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventExceptionBreakpointStatus.java
similarity index 64%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventExceptionBreakpointStatus.java
index f0d343c..86e3add 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventExceptionBreakpointStatus.java
@@ -14,16 +14,21 @@
 
 package org.eclipse.statet.internal.r.debug.core.breakpoints;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRExceptionBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RExceptionBreakpointStatus;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
 
 
-public class ExceptionBreakpointStatus extends BreakpointStatus implements IRExceptionBreakpointStatus {
+@NonNullByDefault
+public class TracepointEventExceptionBreakpointStatus extends TracepointEventBreakpointStatus
+		implements RExceptionBreakpointStatus {
 	
 	
-	public ExceptionBreakpointStatus(final TracepointEvent event, final String label,
-			final IRBreakpoint breakpoint) {
+	public TracepointEventExceptionBreakpointStatus(final TracepointEvent event,
+			final @Nullable String label, final @Nullable IRBreakpoint breakpoint) {
 		super(event, label, breakpoint);
 	}
 	
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventMethodBreakpointStatus.java
similarity index 73%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventMethodBreakpointStatus.java
index 37234d9..c871f0a 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/TracepointEventMethodBreakpointStatus.java
@@ -14,18 +14,23 @@
 
 package org.eclipse.statet.internal.r.debug.core.breakpoints;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRMethodBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RMethodBreakpointStatus;
 import org.eclipse.statet.rj.server.dbg.Tracepoint;
 import org.eclipse.statet.rj.server.dbg.TracepointEvent;
 import org.eclipse.statet.rj.server.dbg.TracepointState;
 
 
-public class MethodBreakpointStatus extends BreakpointStatus implements IRMethodBreakpointStatus {
+@NonNullByDefault
+public class TracepointEventMethodBreakpointStatus extends TracepointEventBreakpointStatus
+		implements RMethodBreakpointStatus {
 	
 	
-	public MethodBreakpointStatus(final TracepointEvent event, final String label,
-			final IRBreakpoint breakpoint) {
+	public TracepointEventMethodBreakpointStatus(final TracepointEvent event,
+			final @Nullable String label, final @Nullable IRBreakpoint breakpoint) {
 		super(event, label, breakpoint);
 	}
 	
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RMainThread.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RMainThread.java
index 8382fd0..917b4fd 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RMainThread.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RMainThread.java
@@ -59,7 +59,7 @@
 import org.eclipse.statet.r.debug.core.IRStackFrame;
 import org.eclipse.statet.r.debug.core.IRThread;
 import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RBreakpointStatus;
 import org.eclipse.statet.r.nico.AbstractRDbgController;
 import org.eclipse.statet.rj.data.RDataUtils;
 import org.eclipse.statet.rj.data.RLanguage;
@@ -431,9 +431,9 @@
 								fileName= fileName.substring(idx + 1);
 							}
 						}
-						final IRBreakpointStatus breakpoint= (dbgFrame.isTopFrame()
-								&& suspendData instanceof IRBreakpointStatus) ?
-										(IRBreakpointStatus) suspendData : null;
+						final RBreakpointStatus breakpoint= (dbgFrame.isTopFrame()
+								&& suspendData instanceof RBreakpointStatus) ?
+										(RBreakpointStatus) suspendData : null;
 						
 						final EnvItem envItem= new EnvItem(handle);
 						newEnvItems.put(envItem.handle, envItem);
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RStackFrame.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RStackFrame.java
index e69c467..8c676d7 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RStackFrame.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RStackFrame.java
@@ -43,7 +43,7 @@
 import org.eclipse.statet.r.core.model.RElementName;
 import org.eclipse.statet.r.core.model.RModel;
 import org.eclipse.statet.r.debug.core.IRStackFrame;
-import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RBreakpointStatus;
 import org.eclipse.statet.r.nico.AbstractRDbgController;
 import org.eclipse.statet.r.nico.ICombinedRDataAdapter;
 import org.eclipse.statet.rj.data.RObject;
@@ -149,12 +149,12 @@
 	private RElementVariable frameVariable;
 	private IValue variables;
 	
-	private IRBreakpointStatus breakpointStatus;
+	private RBreakpointStatus breakpointStatus;
 	
 	
 	public RStackFrame(final RDebugTarget target, final RMainThread thread, final int stamp,
 			final Frame dbgFrame, final Long handle, final String call, final String fileName,
-			final IRBreakpointStatus breakpointStatus) {
+			final RBreakpointStatus breakpointStatus) {
 		super(target);
 		this.thread= thread;
 		
@@ -182,7 +182,7 @@
 	
 	public boolean update(final int stamp,
 			final Frame dbgFrame, final Long handle, final String call, final String fileName,
-			final IRBreakpointStatus breakpointStatus) {
+			final RBreakpointStatus breakpointStatus) {
 		if (call.equals(this.call)
 				&& Objects.equals(dbgFrame.getFileName(), this.dbgFrame.getFileName())
 				&& dbgFrame.getFileTimestamp() == this.dbgFrame.getFileTimestamp() ) {
@@ -537,11 +537,11 @@
 		if (type == IRStackFrame.class) {
 			return (T) this;
 		}
-		if (type == IRBreakpointStatus.class) {
+		if (type == RBreakpointStatus.class) {
 			return (T) this.breakpointStatus;
 		}
 		if (type == IBreakpoint.class) {
-			final IRBreakpointStatus breakpointStatus= this.breakpointStatus;
+			final RBreakpointStatus breakpointStatus= this.breakpointStatus;
 			return (breakpointStatus != null) ? (T) breakpointStatus.getBreakpoint() : null;
 		}
 		if (type == IModelElement.class) {
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RVariableProxy.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RVariableProxy.java
index 608a9a7..b06dfff 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RVariableProxy.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/model/RVariableProxy.java
@@ -51,10 +51,7 @@
 	protected final IRVariable parent;
 	
 	
-	public RVariableProxy(final IRVariable variable, final IRVariable parent) {
-		if (variable instanceof RVariableProxy) {
-			System.out.println("XXX Variable");
-		}
+	protected RVariableProxy(final IRVariable variable, final IRVariable parent) {
 		this.variable= variable;
 		this.parent= parent;
 	}
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/sourcelookup/RSourceLookupParticipant.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/sourcelookup/RSourceLookupParticipant.java
index c427565..e578bf0 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/sourcelookup/RSourceLookupParticipant.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/sourcelookup/RSourceLookupParticipant.java
@@ -69,6 +69,7 @@
 import org.eclipse.statet.r.debug.core.sourcelookup.RRuntimeSourceFragment;
 import org.eclipse.statet.r.nico.IRSrcref;
 import org.eclipse.statet.rj.server.dbg.FrameContext;
+import org.eclipse.statet.rj.server.dbg.Srcfiles;
 import org.eclipse.statet.rj.server.dbg.Srcref;
 
 
@@ -129,12 +130,6 @@
 		
 	}
 	
-	protected static boolean equalTimestamp(final long suTimestamp, final long rTimestamp) {
-		return (suTimestamp == rTimestamp
-				|| Math.abs(suTimestamp - rTimestamp) == 3600 // R returns wrong timestamp under some conditions (daylight saving)
-		);
-	}
-	
 	protected class RSourceLookupMatch implements RStackFrame.PositionResolver, IRSourceLookupMatch {
 		
 		
@@ -641,7 +636,7 @@
 						final IRSrcref exprSrcref= (data.context.getExprSrcref() != null) ?
 								RDbg.createStatetSrcref(data.context.getExprSrcref()) : null;
 						
-						if (data.context.getFileTimestamp() != 0 && equalTimestamp(
+						if (data.context.getFileTimestamp() != 0 && Srcfiles.equalsTimestamp(
 								RDbg.getTimestamp(su, monitor), data.context.getFileTimestamp() )) {
 							match.quality= QUALITY_EXACT_FILE_TIMESTAMP;
 							bDocument= suDocument;
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpoint.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpoint.java
index 7ddf11b..9f7a917 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpoint.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpoint.java
@@ -18,9 +18,13 @@
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.debug.core.model.IBreakpoint;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.r.debug.core.IRDebugTarget;
 
 
+@NonNullByDefault
 public interface IRBreakpoint extends IBreakpoint {
 	
 	
@@ -31,8 +35,6 @@
 	}
 	
 	
-	
-	
 	/**
 	 * Returns the type of this breakpoint
 	 * 
@@ -58,9 +60,9 @@
 //	 */
 //	void setHitCount(int count) throws CoreException;
 	
-	ITargetData registerTarget(IRDebugTarget target, ITargetData data);
-	ITargetData unregisterTarget(IRDebugTarget target);
-	ITargetData getTargetData(IRDebugTarget target);
+	@Nullable ITargetData registerTarget(IRDebugTarget target, ITargetData data);
+	@Nullable ITargetData unregisterTarget(IRDebugTarget target);
+	@Nullable ITargetData getTargetData(IRDebugTarget target);
 	
 	
 	/**
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RBreakpointStatus.java
similarity index 77%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RBreakpointStatus.java
index 3da9a89..5876165 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRBreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RBreakpointStatus.java
@@ -14,15 +14,20 @@
 
 package org.eclipse.statet.r.debug.core.breakpoints;
 
-public interface IRBreakpointStatus {
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public interface RBreakpointStatus {
 	
 	
 	int HIT =                                               0x00000001;
 	
 	
 	int getKind();
-	String getLabel();
+	@Nullable String getLabel();
 	
-	IRBreakpoint getBreakpoint();
+	@Nullable IRBreakpoint getBreakpoint();
 	
 }
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRExceptionBreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RExceptionBreakpointStatus.java
similarity index 83%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRExceptionBreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RExceptionBreakpointStatus.java
index 5126ab9..353c24b 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRExceptionBreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RExceptionBreakpointStatus.java
@@ -14,8 +14,11 @@
 
 package org.eclipse.statet.r.debug.core.breakpoints;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 
-public interface IRExceptionBreakpointStatus extends IRBreakpointStatus {
+
+@NonNullByDefault
+public interface RExceptionBreakpointStatus extends RBreakpointStatus {
 	
 	
 }
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RLineBreakpointValidator.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RLineBreakpointValidator.java
index fb3a3cf..6005882 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RLineBreakpointValidator.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RLineBreakpointValidator.java
@@ -27,6 +27,8 @@
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IRegion;
 
+import org.eclipse.statet.jcommons.lang.Nullable;
+
 import org.eclipse.statet.internal.r.debug.core.RDebugCorePlugin;
 import org.eclipse.statet.internal.r.debug.core.breakpoints.RGenericLineBreakpoint;
 import org.eclipse.statet.internal.r.debug.core.breakpoints.RGenericLineBreakpoint.CachedData;
@@ -560,7 +562,7 @@
 		return element.getElementName().toString();
 	}
 	
-	public IRSrcref computeElementSrcref() throws CoreException {
+	public @Nullable IRSrcref computeElementSrcref() throws CoreException {
 		if (this.type == null) {
 			throw invalid();
 		}
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRMethodBreakpointStatus.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RMethodBreakpointStatus.java
similarity index 84%
rename from r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRMethodBreakpointStatus.java
rename to r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RMethodBreakpointStatus.java
index 8cfef5a..c76ded1 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/IRMethodBreakpointStatus.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/r/debug/core/breakpoints/RMethodBreakpointStatus.java
@@ -14,8 +14,11 @@
 
 package org.eclipse.statet.r.debug.core.breakpoints;
 
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
 
-public interface IRMethodBreakpointStatus extends IRBreakpointStatus {
+
+@NonNullByDefault
+public interface RMethodBreakpointStatus extends RBreakpointStatus {
 	
 	
 	boolean isEntry();
diff --git a/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/RDebugModelPresentation.java b/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/RDebugModelPresentation.java
index ba67028..d3ef336 100644
--- a/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/RDebugModelPresentation.java
+++ b/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/RDebugModelPresentation.java
@@ -64,11 +64,11 @@
 import org.eclipse.statet.r.debug.core.IRVariable;
 import org.eclipse.statet.r.debug.core.RDebugModel;
 import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRBreakpointStatus;
-import org.eclipse.statet.r.debug.core.breakpoints.IRExceptionBreakpointStatus;
 import org.eclipse.statet.r.debug.core.breakpoints.IRLineBreakpoint;
 import org.eclipse.statet.r.debug.core.breakpoints.IRMethodBreakpoint;
-import org.eclipse.statet.r.debug.core.breakpoints.IRMethodBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RExceptionBreakpointStatus;
+import org.eclipse.statet.r.debug.core.breakpoints.RMethodBreakpointStatus;
 import org.eclipse.statet.r.debug.core.sourcelookup.IRSourceLookupMatch;
 import org.eclipse.statet.r.debug.core.sourcelookup.RRuntimeSourceFragment;
 import org.eclipse.statet.r.ui.RLabelProvider;
@@ -239,11 +239,11 @@
 	protected String getText(final IRThread thread) throws CoreException {
 		final StringBuilder sb = new StringBuilder(thread.getName());
 		if (thread.isSuspended()) {
-			final IRBreakpointStatus status= getBreakpointStatus(thread);
+			final RBreakpointStatus status= getBreakpointStatus(thread);
 			if (status != null) {
 				int a = 0;
-				if (status instanceof IRMethodBreakpointStatus) {
-					final IRMethodBreakpointStatus mbStatus= (IRMethodBreakpointStatus) status;
+				if (status instanceof RMethodBreakpointStatus) {
+					final RMethodBreakpointStatus mbStatus= (RMethodBreakpointStatus) status;
 					if (mbStatus.isEntry()) {
 						sb.append(" (Suspended at entry of ");
 						a= 1;
@@ -253,7 +253,7 @@
 						a= 1;
 					}
 				}
-				if (status instanceof IRExceptionBreakpointStatus) {
+				if (status instanceof RExceptionBreakpointStatus) {
 					sb.append(" (Suspended on ");
 					a= 1;
 				}
@@ -283,10 +283,10 @@
 		return sb.toString();
 	}
 	
-	private IRBreakpointStatus getBreakpointStatus(final IRThread thread) {
+	private RBreakpointStatus getBreakpointStatus(final IRThread thread) {
 		final IStackFrame frame = thread.getTopStackFrame();
 		if (frame != null) {
-			return frame.getAdapter(IRBreakpointStatus.class);
+			return frame.getAdapter(RBreakpointStatus.class);
 		}
 		return null;
 	}