Bug 572002: Make use of IResource.createMarker(type, attribute) added in
Platform 4.19

  - Improve update of breakpoint markers

Change-Id: Ib8ebe549651023df1c39daf5ce64a3158b9a0020
diff --git a/r/org.eclipse.statet.r.core/src/org/eclipse/statet/internal/r/core/builder/RPkgReconciler.java b/r/org.eclipse.statet.r.core/src/org/eclipse/statet/internal/r/core/builder/RPkgReconciler.java
index 6f459f3..a4145ad 100644
--- a/r/org.eclipse.statet.r.core/src/org/eclipse/statet/internal/r/core/builder/RPkgReconciler.java
+++ b/r/org.eclipse.statet.r.core/src/org/eclipse/statet/internal/r/core/builder/RPkgReconciler.java
@@ -16,6 +16,7 @@
 
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.util.Map;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -44,12 +45,6 @@
 	private static final String DESCRIPTION_PACKAGE_FIELD= "Package:"; //$NON-NLS-1$
 	
 	
-	private static final String[] PROBLEM_ARGUMENT_NAMES= new String[] {
-			IMarker.SEVERITY,
-			IMarker.MESSAGE,
-	};
-	
-	
 	public RPkgReconciler() {
 	}
 	
@@ -62,16 +57,11 @@
 			final IProject project= pkgRoot.getProject();
 			
 			if (!pkgRoot.exists()) {
-				final IMarker marker= project.createMarker(RModel.BUILDPATH_PROBLEM_MARKER);
-				marker.setAttributes(new String[] {
-						IMarker.SEVERITY,
-						IMarker.MESSAGE,
-						IMarker.LOCATION,
-				}, new Object[] {
-						IMarker.SEVERITY_ERROR,
-						NLS.bind("R package folder ''{0}'' is missing.", pkgRoot.getProjectRelativePath()),
-						"R Project Configuration",
-				});
+				project.createMarker(RModel.BUILDPATH_PROBLEM_MARKER, Map.of(
+						IMarker.SEVERITY, IMarker.SEVERITY_ERROR,
+						IMarker.MESSAGE, NLS.bind("R package folder ''{0}'' is missing.",
+								pkgRoot.getProjectRelativePath() ),
+						IMarker.LOCATION, "R Project Configuration" ));
 				
 				return result;
 			}
@@ -98,17 +88,15 @@
 				fileOp.doOperation(m);
 				
 				if (result.getPkgName() == null) {
-					final IMarker marker= file.createMarker(RModel.R_MODEL_PROBLEM_MARKER);
-					marker.setAttributes(PROBLEM_ARGUMENT_NAMES, new Object[] {
-							IMarker.SEVERITY_ERROR,
-							"The declaration of 'Package' (R package name) is missing." });
+					file.createMarker(RModel.R_MODEL_PROBLEM_MARKER, Map.of(
+							IMarker.SEVERITY, IMarker.SEVERITY_ERROR,
+							IMarker.MESSAGE, "The declaration of 'Package' (R package name) is missing." ));
 				}
 			}
 			else {
-				final IMarker marker= pkgRoot.createMarker(RModel.R_MODEL_PROBLEM_MARKER);
-				marker.setAttributes(PROBLEM_ARGUMENT_NAMES, new Object[] {
-						IMarker.SEVERITY_ERROR,
-						"'DESCRIPTION' file for R package is missing." });
+				pkgRoot.createMarker(RModel.R_MODEL_PROBLEM_MARKER, Map.of(
+						IMarker.SEVERITY, IMarker.SEVERITY_ERROR,
+						IMarker.MESSAGE, "'DESCRIPTION' file for R package is missing." ));
 				
 				return result;
 			}
diff --git a/r/org.eclipse.statet.r.debug.core/META-INF/MANIFEST.MF b/r/org.eclipse.statet.r.debug.core/META-INF/MANIFEST.MF
index d03c695..45279c5 100644
--- a/r/org.eclipse.statet.r.debug.core/META-INF/MANIFEST.MF
+++ b/r/org.eclipse.statet.r.debug.core/META-INF/MANIFEST.MF
@@ -19,6 +19,7 @@
 Import-Package: org.eclipse.statet.ecommons.io,
  org.eclipse.statet.ecommons.models.core.util,
  org.eclipse.statet.ecommons.preferences,
+ org.eclipse.statet.ecommons.resources.core.util;version="4.4.0",
  org.eclipse.statet.jcommons.collections;version="4.4.0",
  org.eclipse.statet.jcommons.lang;version="4.4.0",
  org.eclipse.statet.jcommons.status;version="4.4.0",
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointImpl.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointImpl.java
index 1447be6..135dd89 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointImpl.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/ExceptionBreakpointImpl.java
@@ -52,11 +52,8 @@
 		final IWorkspaceRunnable wr= new IWorkspaceRunnable() {
 			@Override
 			public void run(final IProgressMonitor monitor) throws CoreException {
-				// create the marker
-				setMarker(resource.createMarker(R_EXCEPTION_BREAKPOINT_MARKER_TYPE));
+				setMarker(resource.createMarker(R_EXCEPTION_BREAKPOINT_MARKER_TYPE, attributes));
 				
-				// update attributes
-				ensureMarker().setAttributes(attributes);
 				register(!temporary);
 				if (temporary) {
 					setPersisted(false);
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/GenericLineBreakpoint.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/GenericLineBreakpoint.java
index d65d009..0376d8d 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/GenericLineBreakpoint.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/GenericLineBreakpoint.java
@@ -15,6 +15,7 @@
 package org.eclipse.statet.internal.r.debug.core.breakpoints;
 
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.eclipse.core.resources.IMarker;
@@ -22,9 +23,12 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.model.IBreakpoint;
 
+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.resources.core.util.MarkerUpdate;
+
 import org.eclipse.statet.r.debug.core.breakpoints.RLineBreakpoint;
 
 
@@ -72,39 +76,33 @@
 	}
 	
 	
-	private static final String[] POSITION_ATTRIBUTES= new String[] {
-			IMarker.LINE_NUMBER, IMarker.CHAR_START, IMarker.CHAR_END };
-	private static final String[] ELEMENT_ATTRIBUTES= new String[] {
-			ELEMENT_TYPE_MARKER_ATTR, ELEMENT_ID_MARKER_ATTR, ELEMENT_LABEL_MARKER_ATTR };
-	
-	public static void updatePosition(final IMarker marker,
+	public static void updatePosition(final MarkerUpdate markerUpdate,
 			final int lineNumber, final int charStart, final int charEnd)
 			throws CoreException {
+		final var marker= markerUpdate.getMarker();
 		if (lineNumber != marker.getAttribute(IMarker.LINE_NUMBER, -1)
 				|| charStart != marker.getAttribute(IMarker.CHAR_START, -1)
 				|| charEnd != marker.getAttribute(IMarker.CHAR_END, -1) ) {
-			marker.setAttributes(POSITION_ATTRIBUTES, new Object[] {
-					lineNumber, charStart, charEnd
-			});
+			markerUpdate.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+			markerUpdate.setAttribute(IMarker.CHAR_START, charStart);
+			markerUpdate.setAttribute(IMarker.CHAR_END, charEnd);
 		}
 	}
 	
-	public static void updateElementInfo(final IMarker marker,
+	public static void updateElementInfo(final MarkerUpdate markerUpdate,
 			final int elementType, final String elementId,
 			final String elementLabel, final String subLabel)
 			throws CoreException {
+		final var marker= markerUpdate.getMarker();
 		if (elementType != marker.getAttribute(ELEMENT_TYPE_MARKER_ATTR, -1)
-				|| ((elementId != null) ? !elementId.equals(marker.getAttribute(ELEMENT_ID_MARKER_ATTR, null)) :
-							null != marker.getAttribute(ELEMENT_ID_MARKER_ATTR, null))
-				|| ((elementLabel != null) ? !elementLabel.equals(marker.getAttribute(ELEMENT_LABEL_MARKER_ATTR, null)) :
-							null != marker.getAttribute(ELEMENT_LABEL_MARKER_ATTR, null)) ) {
-			marker.setAttributes(ELEMENT_ATTRIBUTES, new Object[] {
-					Integer.valueOf(elementType), elementId, elementLabel
-			});
+				|| !Objects.equals(elementId, marker.getAttribute(ELEMENT_ID_MARKER_ATTR, null))
+				|| !Objects.equals(elementLabel, marker.getAttribute(ELEMENT_LABEL_MARKER_ATTR, null)) ) {
+			markerUpdate.setAttribute(ELEMENT_TYPE_MARKER_ATTR, elementType);
+			markerUpdate.setAttribute(ELEMENT_ID_MARKER_ATTR, elementId);
+			markerUpdate.setAttribute(ELEMENT_LABEL_MARKER_ATTR, elementLabel);
 		}
-		if ((subLabel != null) ? !subLabel.equals(marker.getAttribute(SUB_LABEL_MARKER_ATTR, null)) :
-				null != marker.getAttribute(SUB_LABEL_MARKER_ATTR, null) ) {
-			marker.setAttribute(SUB_LABEL_MARKER_ATTR, subLabel);
+		if (!Objects.equals(subLabel, marker.getAttribute(SUB_LABEL_MARKER_ATTR, null)) ) {
+			markerUpdate.setAttribute(SUB_LABEL_MARKER_ATTR, subLabel);
 		}
 //		if (rExpressionIndex != null) {
 //			final String value= encodeIntArray(rExpressionIndex);
@@ -246,11 +244,10 @@
 		if (code != null && code.trim().length() > 0) {
 			marker.setAttribute(CONDITION_EXPR_MARKER_ATTR, code);
 		}
-		else {
-			if (marker.getAttribute(CONDITION_EXPR_MARKER_ATTR, (String) null) != null) {
-				marker.setAttribute(CONDITION_ENABLED_MARKER_ATTR, false);
-			}
-			ensureMarker().setAttribute(CONDITION_EXPR_MARKER_ATTR, (String) null);
+		else if (marker.getAttribute(CONDITION_EXPR_MARKER_ATTR, (String)null) != null) {
+			marker.setAttributes(
+					new @NonNull String[] { CONDITION_ENABLED_MARKER_ATTR, CONDITION_EXPR_MARKER_ATTR },
+					new @Nullable Object[] { false, null } );
 		}
 	}
 	
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/LineBreakpointImpl.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/LineBreakpointImpl.java
index ec137c3..1f45b09 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/LineBreakpointImpl.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/LineBreakpointImpl.java
@@ -47,11 +47,8 @@
 		final IWorkspaceRunnable wr= new IWorkspaceRunnable() {
 			@Override
 			public void run(final IProgressMonitor monitor) throws CoreException {
-				// create the marker
-				setMarker(resource.createMarker(R_LINE_BREAKPOINT_MARKER_TYPE));
+				setMarker(resource.createMarker(R_LINE_BREAKPOINT_MARKER_TYPE, attributes));
 				
-				// update attributes
-				ensureMarker().setAttributes(attributes);
 				register(!temporary);
 				if (temporary) {
 					setPersisted(false);
diff --git a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointImpl.java b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointImpl.java
index 1851f46..ece6d18 100644
--- a/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointImpl.java
+++ b/r/org.eclipse.statet.r.debug.core/src/org/eclipse/statet/internal/r/debug/core/breakpoints/MethodBreakpointImpl.java
@@ -53,11 +53,8 @@
 		final IWorkspaceRunnable wr= new IWorkspaceRunnable() {
 			@Override
 			public void run(final IProgressMonitor monitor) throws CoreException {
-				// create the marker
-				setMarker(resource.createMarker(R_METHOD_BREAKPOINT_MARKER_TYPE));
+				setMarker(resource.createMarker(R_METHOD_BREAKPOINT_MARKER_TYPE, attributes));
 				
-				// update attributes
-				ensureMarker().setAttributes(attributes);
 				register(!temporary);
 				if (temporary) {
 					setPersisted(false);
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 0169a7b..76aae5a 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
@@ -18,7 +18,6 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -30,6 +29,8 @@
 
 import org.eclipse.statet.jcommons.lang.Nullable;
 
+import org.eclipse.statet.ecommons.resources.core.util.MarkerUpdate;
+
 import org.eclipse.statet.internal.r.debug.core.RDebugCorePlugin;
 import org.eclipse.statet.internal.r.debug.core.breakpoints.GenericLineBreakpoint;
 import org.eclipse.statet.internal.r.debug.core.breakpoints.GenericLineBreakpoint.CachedData;
@@ -686,12 +687,13 @@
 		if (!(breakpoint instanceof RLineBreakpoint)) {
 			throw new IllegalArgumentException(breakpoint.getClass().getName());
 		}
-		final IMarker marker= breakpoint.getMarker();
+		final MarkerUpdate markerUpdate= new MarkerUpdate(breakpoint.getMarker(), 3);
 		final String elementId= computeElementId();
-		GenericLineBreakpoint.updatePosition(marker,
+		GenericLineBreakpoint.updatePosition(markerUpdate,
 				getLineNumber(), getCharStart(), getCharEnd() );
-		GenericLineBreakpoint.updateElementInfo(marker,
+		GenericLineBreakpoint.updateElementInfo(markerUpdate,
 				computeElementType(), elementId, computeElementLabel(), computeSubLabel() );
+		markerUpdate.apply();
 		if (breakpoint instanceof GenericLineBreakpoint) {
 			((GenericLineBreakpoint)breakpoint).setCachedData(new CachedData(
 					this.modelInfo.getStamp().getContentStamp(), elementId,
diff --git a/r/org.eclipse.statet.r.debug.ui/META-INF/MANIFEST.MF b/r/org.eclipse.statet.r.debug.ui/META-INF/MANIFEST.MF
index 1eb665c..1020378 100644
--- a/r/org.eclipse.statet.r.debug.ui/META-INF/MANIFEST.MF
+++ b/r/org.eclipse.statet.r.debug.ui/META-INF/MANIFEST.MF
@@ -26,6 +26,7 @@
  org.eclipse.ui.workbench
 Import-Package: org.eclipse.statet.ecommons.debug.core.util,
  org.eclipse.statet.ecommons.io,
+ org.eclipse.statet.ecommons.resources.core.util;version="4.4.0",
  org.eclipse.statet.jcommons.collections;version="4.4.0",
  org.eclipse.statet.jcommons.lang;version="4.4.0",
  org.eclipse.statet.jcommons.status;version="4.4.0",
diff --git a/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/breakpoints/BreakpointMarkerUpdater.java b/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/breakpoints/BreakpointMarkerUpdater.java
index 0a48dc4..d1902cd 100644
--- a/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/breakpoints/BreakpointMarkerUpdater.java
+++ b/r/org.eclipse.statet.r.debug.ui/src/org/eclipse/statet/internal/r/debug/ui/breakpoints/BreakpointMarkerUpdater.java
@@ -14,9 +14,6 @@
 
 package org.eclipse.statet.internal.r.debug.ui.breakpoints;
 
-import java.util.IdentityHashMap;
-import java.util.Map;
-
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -33,6 +30,8 @@
 import org.eclipse.ui.texteditor.IMarkerUpdater;
 import org.eclipse.ui.texteditor.MarkerUtilities;
 
+import org.eclipse.statet.ecommons.resources.core.util.MarkerUpdate;
+
 import org.eclipse.statet.ltk.core.Ltk;
 import org.eclipse.statet.ltk.model.core.LtkModels;
 import org.eclipse.statet.ltk.model.core.SourceUnitManager;
@@ -127,40 +126,42 @@
 	
 	private boolean updateBasic(final IMarker marker,
 			final IDocument document, final Position position) {
+		final var markerUpdate= new MarkerUpdate(marker, 3);
+		
 		boolean offsetsInitialized= false;
-		final int markerStart= MarkerUtilities.getCharStart(marker);
-		final int markerEnd= MarkerUtilities.getCharEnd(marker);
-		
-		final Map<String, Object> attributes= new IdentityHashMap<>(4);
-		if (markerStart != -1 && markerEnd != -1) {
-			offsetsInitialized= true;
-			
-			int offset= position.getOffset();
-			if (markerStart != offset) {
-				attributes.put(IMarker.CHAR_START, Integer.valueOf(offset));
-			}
-			
-			offset+= position.getLength();
-			if (markerEnd != offset) {
-				attributes.put(IMarker.CHAR_END, Integer.valueOf(offset));
+		{	final int markerStart= MarkerUtilities.getCharStart(marker);
+			final int markerEnd= MarkerUtilities.getCharEnd(marker);
+			if (markerStart != -1 && markerEnd != -1) {
+				offsetsInitialized= true;
+				int offset= position.getOffset();
+				if (offset != markerStart) {
+					markerUpdate.setAttribute(IMarker.CHAR_START, offset);
+				}
+				
+				offset+= position.getLength();
+				if (offset != markerEnd) {
+					markerUpdate.setAttribute(IMarker.CHAR_END, offset);
+				}
 			}
 		}
 		
-		if (!offsetsInitialized || (!attributes.isEmpty() && MarkerUtilities.getLineNumber(marker) != -1)) {
-			try {
-				// marker line numbers are 1-based
-				attributes.put(IMarker.LINE_NUMBER, Integer.valueOf(
-						document.getLineOfOffset(position.getOffset()) + 1 ));
-			} catch (final BadLocationException x) {}
+		{	final int markerLineNumber= MarkerUtilities.getLineNumber(marker);
+			if (!offsetsInitialized || markerLineNumber != -1) {
+				try {
+					// marker line numbers are 1-based
+					final int lineNumber= document.getLineOfOffset(position.getOffset()) + 1;
+					if (lineNumber != markerLineNumber) {
+						markerUpdate.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+					}
+				} catch (final BadLocationException x) {}
+			}
 		}
 		
-		if (!attributes.isEmpty()) {
-			try {
-				marker.setAttributes(attributes);
-			}
-			catch (final CoreException e) {
-				StatusManager.getManager().handle(e.getStatus());
-			}
+		try {
+			markerUpdate.apply();
+		}
+		catch (final CoreException e) {
+			StatusManager.getManager().handle(e.getStatus());
 		}
 		
 		return true;
diff --git a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/launching/RCodeLaunching.java b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/launching/RCodeLaunching.java
index 9fa02be..7bb5e36 100644
--- a/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/launching/RCodeLaunching.java
+++ b/r/org.eclipse.statet.r.ui/srcDebug/org/eclipse/statet/r/launching/RCodeLaunching.java
@@ -19,6 +19,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.filesystem.IFileStore;
@@ -250,9 +251,9 @@
 			if (fSourceUnit instanceof RWorkspaceSourceUnit) {
 				final IResource resource = ((RWorkspaceSourceUnit) fSourceUnit).getResource();
 				try {
-					fMarker = resource.createMarker(MARKER_TYPE);
-					fMarker.setAttribute(IMarker.CHAR_START, fBeginOffset);
-					fMarker.setAttribute(IMarker.CHAR_END, fEndOffset);
+					fMarker= resource.createMarker(MARKER_TYPE, Map.of(
+							IMarker.CHAR_START, fBeginOffset,
+							IMarker.CHAR_END, fEndOffset ));
 				}
 				catch (final CoreException e) {
 					StatusManager.getManager().handle(new org.eclipse.core.runtime.Status(IStatus.ERROR, RUI.BUNDLE_ID, 0,