|
1 /******************************************************************************* |
|
2 * Copyright (c) 2009 Nokia and others. |
|
3 * All rights reserved. This program and the accompanying materials |
|
4 * are made available under the terms of the Eclipse Public License v1.0 |
|
5 * which accompanies this distribution, and is available at |
|
6 * http://www.eclipse.org/legal/epl-v10.html |
|
7 * |
|
8 * Contributors: |
|
9 * Nokia - Initial API and implementation. Nov, 2009. |
|
10 *******************************************************************************/ |
|
11 package org.eclipse.cdt.dsf.mi.service; |
|
12 |
|
13 import java.util.ArrayList; |
|
14 import java.util.HashMap; |
|
15 import java.util.HashSet; |
|
16 import java.util.List; |
|
17 import java.util.Map; |
|
18 import java.util.Set; |
|
19 |
|
20 import org.eclipse.cdt.debug.core.model.ICBreakpoint; |
|
21 import org.eclipse.cdt.debug.core.model.ICBreakpointExtension; |
|
22 import org.eclipse.cdt.debug.core.model.ICLineBreakpoint; |
|
23 import org.eclipse.cdt.debug.core.model.ICWatchpoint; |
|
24 import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems; |
|
25 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
|
26 import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
|
27 import org.eclipse.cdt.dsf.datamodel.DMContexts; |
|
28 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator; |
|
29 import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslatorExtension; |
|
30 import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension; |
|
31 import org.eclipse.cdt.dsf.debug.service.ISourceLookup; |
|
32 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.BreakpointEventType; |
|
33 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.ITargetBreakpointInfo; |
|
34 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; |
|
35 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; |
|
36 import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; |
|
37 import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; |
|
38 import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext; |
|
39 import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; |
|
40 import org.eclipse.cdt.dsf.service.DsfServicesTracker; |
|
41 import org.eclipse.cdt.dsf.service.DsfSession; |
|
42 import org.eclipse.core.resources.IMarker; |
|
43 import org.eclipse.core.resources.IResource; |
|
44 import org.eclipse.core.runtime.CoreException; |
|
45 import org.eclipse.core.runtime.IProgressMonitor; |
|
46 import org.eclipse.core.runtime.IStatus; |
|
47 import org.eclipse.core.runtime.Platform; |
|
48 import org.eclipse.core.runtime.Status; |
|
49 import org.eclipse.core.runtime.jobs.Job; |
|
50 import org.eclipse.debug.core.DebugException; |
|
51 import org.eclipse.debug.core.model.IBreakpoint; |
|
52 |
|
53 public class MIBreakpointAttributeTranslator implements IBreakpointAttributeTranslatorExtension { |
|
54 |
|
55 private final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$ |
|
56 |
|
57 // Extra breakpoint attributes |
|
58 private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath"; //$NON-NLS-1$ |
|
59 private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter"; //$NON-NLS-1$ |
|
60 // private static final String ATTR_THREAD_ID = GdbPlugin.PLUGIN_ID + ".threadID"; //$NON-NLS-1$ |
|
61 |
|
62 private DsfServicesTracker dsfServicesTracker; |
|
63 private DsfSession dsfSession; |
|
64 private BreakpointsMediator breakpointsMediator; |
|
65 private String debugModelId; |
|
66 |
|
67 /** |
|
68 * Manage breakpoint problem markers. <br> |
|
69 * It's better be done by MIBreakpoints service so that it's accessible by |
|
70 * the MIBreakpoints service too. But to minimize change to MIBreakpoints in |
|
71 * this iteration, I just put it here..... 11/18/09 |
|
72 */ |
|
73 private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems = |
|
74 new HashMap<ICBreakpoint, IMarker>(); |
|
75 |
|
76 public MIBreakpointAttributeTranslator(DsfSession dsfSession, String debugModelId) { |
|
77 super(); |
|
78 this.dsfSession = dsfSession; |
|
79 this.debugModelId = debugModelId; |
|
80 |
|
81 dsfServicesTracker = new DsfServicesTracker(GdbPlugin.getDefault().getBundle().getBundleContext(), dsfSession.getId()); |
|
82 } |
|
83 |
|
84 public boolean canUpdateAttributes(IBreakpointDMContext bp, Map<String, Object> delta) { |
|
85 /* |
|
86 * This method decides whether we need to re-install the breakpoint |
|
87 * based on the attributes change (refer to caller in |
|
88 * BreakpointsMediator). |
|
89 */ |
|
90 // Check if there is any modified attribute |
|
91 if (delta == null || delta.size() == 0) |
|
92 return true; |
|
93 |
|
94 // Check the "critical" attributes |
|
95 if (delta.containsKey(ATTR_DEBUGGER_PATH) // File name |
|
96 || delta.containsKey(MIBreakpoints.LINE_NUMBER) // Line number |
|
97 || delta.containsKey(MIBreakpoints.FUNCTION) // Function name |
|
98 || delta.containsKey(MIBreakpoints.ADDRESS) // Absolute address |
|
99 || delta.containsKey(ATTR_THREAD_FILTER) // Thread ID |
|
100 || delta.containsKey(MIBreakpoints.EXPRESSION) // Watchpoint expression |
|
101 || delta.containsKey(MIBreakpoints.READ) // Watchpoint type |
|
102 || delta.containsKey(MIBreakpoints.WRITE)) { // Watchpoint type |
|
103 return false; |
|
104 } |
|
105 |
|
106 // for other attrs (ICBreakpoint.INSTALL_COUNT, ICBreakpoint.IGNORE_COUNT, |
|
107 // ICBreakpoint.CONDITION, etc), we can update them. |
|
108 return true; |
|
109 } |
|
110 |
|
111 public void dispose() { |
|
112 if (dsfServicesTracker != null) |
|
113 dsfServicesTracker.dispose(); |
|
114 dsfSession = null; |
|
115 |
|
116 clearBreakpointProblemMarkers(); |
|
117 } |
|
118 |
|
119 public List<Map<String, Object>> getBreakpointAttributes(IBreakpoint bp, boolean bpManagerEnabled) |
|
120 throws CoreException { |
|
121 // deprecated |
|
122 List<Map<String, Object>> retVal = new ArrayList<Map<String, Object>>(); |
|
123 return retVal; |
|
124 } |
|
125 |
|
126 public void initialize(BreakpointsMediator mediator) { |
|
127 breakpointsMediator = mediator; |
|
128 } |
|
129 |
|
130 public boolean supportsBreakpoint(IBreakpoint bp) { |
|
131 if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(debugModelId)) { |
|
132 IMarker marker = bp.getMarker(); |
|
133 if (marker != null) { |
|
134 return true; |
|
135 } |
|
136 } |
|
137 return false; |
|
138 } |
|
139 |
|
140 public void updateBreakpointStatus(IBreakpoint bp) { |
|
141 // obsolet, do nothing. |
|
142 } |
|
143 |
|
144 public void updateBreakpointsStatus(Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo, |
|
145 BreakpointEventType eventType) { |
|
146 for (IBreakpoint bp : bpsInfo.keySet()) { |
|
147 if (! (bp instanceof ICBreakpoint)) // not C breakpoints, bail out. |
|
148 return; |
|
149 |
|
150 final ICBreakpoint icbp = (ICBreakpoint) bp; |
|
151 |
|
152 Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBpPerContext = bpsInfo.get(bp); |
|
153 |
|
154 switch (eventType) { |
|
155 case ADDED: { |
|
156 int installCountTotal = 0; |
|
157 StringBuffer errMsg = new StringBuffer(); |
|
158 for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) { |
|
159 // For each BpTargetDMContext, we increment the installCount for each |
|
160 // target BP that has been successfully installed. |
|
161 int installCountPerContext = 0; |
|
162 for (ITargetBreakpointInfo tbp : tbpInfos) { |
|
163 if (tbp.getTargetBreakpoint() != null) |
|
164 installCountPerContext++; |
|
165 else // failure in installation |
|
166 errMsg.append(tbp.getStatus().getMessage()).append('\n'); |
|
167 } |
|
168 installCountTotal += installCountPerContext; |
|
169 } |
|
170 |
|
171 for (int i=0; i < installCountTotal; i++) |
|
172 try { |
|
173 // this will eventually carried out in a workspace runnable. |
|
174 icbp.incrementInstallCount(); |
|
175 } catch (CoreException e) { |
|
176 GdbPlugin.getDefault().getLog().log(e.getStatus()); |
|
177 } |
|
178 |
|
179 if (errMsg.length() > 0) |
|
180 addBreakpointProblemMarker(icbp, errMsg.toString(), IMarker.SEVERITY_WARNING); |
|
181 else // no error, clean message if any. |
|
182 removeBreakpointProblemMarker(icbp); |
|
183 |
|
184 break; |
|
185 } |
|
186 case MODIFIED: |
|
187 break; |
|
188 |
|
189 case REMOVED: { |
|
190 int removeCountTotal = 0; |
|
191 for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) { |
|
192 // For each BpTargetDMContext, we decrement the installCount for each |
|
193 // target BP that we tried to remove, even if the removal failed. That's |
|
194 // because I've not seen a way to tell platform that removal fails |
|
195 // and the BP should be kept in UI. |
|
196 removeCountTotal += tbpInfos.length; |
|
197 } |
|
198 |
|
199 for (int i=0; i < removeCountTotal; i++) |
|
200 try { |
|
201 if (icbp.isRegistered()) // not deleted in UI |
|
202 icbp.decrementInstallCount(); |
|
203 } catch (CoreException e) { |
|
204 GdbPlugin.getDefault().getLog().log(e.getStatus()); |
|
205 } |
|
206 break; |
|
207 } |
|
208 } |
|
209 } |
|
210 } |
|
211 |
|
212 public Map<String, Object> convertAttributes(Map<String, Object> platformAttrs) { |
|
213 Map<String, Object> targetAttrs = new HashMap<String, Object>(); |
|
214 |
|
215 if (platformAttrs.containsKey(MIBreakpoints.BREAKPOINT_TYPE)) |
|
216 targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, platformAttrs.get(MIBreakpoints.BREAKPOINT_TYPE)); |
|
217 |
|
218 if (platformAttrs.containsKey(ICWatchpoint.EXPRESSION)) |
|
219 targetAttrs.put(MIBreakpoints.EXPRESSION, platformAttrs.get(ICWatchpoint.EXPRESSION)); |
|
220 if (platformAttrs.containsKey(ICWatchpoint.READ)) |
|
221 targetAttrs.put(MIBreakpoints.READ, platformAttrs.get(ICWatchpoint.READ)); |
|
222 if (platformAttrs.containsKey(ICWatchpoint.WRITE)) |
|
223 targetAttrs.put(MIBreakpoints.WRITE, platformAttrs.get(ICWatchpoint.WRITE)); |
|
224 |
|
225 if (platformAttrs.containsKey(ICBreakpoint.SOURCE_HANDLE)) |
|
226 targetAttrs.put(MIBreakpoints.FILE_NAME, platformAttrs.get(ICBreakpoint.SOURCE_HANDLE)); |
|
227 |
|
228 if (platformAttrs.containsKey(IMarker.LINE_NUMBER)) |
|
229 targetAttrs.put(MIBreakpoints.LINE_NUMBER, platformAttrs.get(IMarker.LINE_NUMBER)); |
|
230 if (platformAttrs.containsKey(ICLineBreakpoint.FUNCTION)) |
|
231 targetAttrs.put(MIBreakpoints.FUNCTION, platformAttrs.get(ICLineBreakpoint.FUNCTION)); |
|
232 if (platformAttrs.containsKey(ICLineBreakpoint.ADDRESS)) |
|
233 targetAttrs.put(MIBreakpoints.ADDRESS, platformAttrs.get(ICLineBreakpoint.ADDRESS)); |
|
234 |
|
235 if (platformAttrs.containsKey(ICBreakpoint.CONDITION)) |
|
236 targetAttrs.put(MIBreakpoints.CONDITION, platformAttrs.get(ICBreakpoint.CONDITION)); |
|
237 if (platformAttrs.containsKey(ICBreakpoint.IGNORE_COUNT)) |
|
238 targetAttrs.put(MIBreakpoints.IGNORE_COUNT, platformAttrs.get(ICBreakpoint.IGNORE_COUNT)); |
|
239 if (platformAttrs.containsKey(ICBreakpoint.ENABLED)) |
|
240 targetAttrs.put(MIBreakpoints.IS_ENABLED, platformAttrs.get(ICBreakpoint.ENABLED)); |
|
241 |
|
242 return targetAttrs; |
|
243 } |
|
244 |
|
245 @SuppressWarnings("unchecked") |
|
246 public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint, |
|
247 Map<String, Object> bpAttributes, final DataRequestMonitor<List<Map<String, Object>>> drm) { |
|
248 |
|
249 assert dsfSession.getExecutor().isInExecutorThread(); |
|
250 |
|
251 // Create a copy as we don't want to change "bpAttributes". |
|
252 final Map<String, Object> targetBPAttrBase = new HashMap<String, Object>(bpAttributes); |
|
253 |
|
254 final Set<String> threads = (Set<String>) targetBPAttrBase.get(ATTR_THREAD_FILTER); |
|
255 |
|
256 final List<Map<String, Object>> targetBPList = new ArrayList<Map<String, Object>>(); |
|
257 |
|
258 // get debugger path (compilation-path) for source file, if any. |
|
259 determineDebuggerPath(context, targetBPAttrBase, new RequestMonitor(dsfSession.getExecutor(), drm){ |
|
260 @Override |
|
261 protected void handleSuccess() { |
|
262 // Create attribute list for each thread |
|
263 for (String thread : threads) { |
|
264 Map<String, Object> targetBP = new HashMap<String, Object>(targetBPAttrBase); |
|
265 targetBP.put(MIBreakpointDMData.THREAD_ID, thread); |
|
266 targetBPList.add(targetBP); |
|
267 } |
|
268 |
|
269 drm.setData(targetBPList); |
|
270 drm.done(); |
|
271 }}); |
|
272 } |
|
273 |
|
274 /** |
|
275 * determineDebuggerPath |
|
276 * |
|
277 * Adds the path to the source file to the set of attributes |
|
278 * (for the debugger). |
|
279 * |
|
280 * @param dmc |
|
281 * @param targetAttrs |
|
282 * @param rm |
|
283 */ |
|
284 private void determineDebuggerPath(IBreakpointsTargetDMContext dmc, |
|
285 final Map<String, Object> targetAttrs, final RequestMonitor rm) |
|
286 { |
|
287 String hostPath = (String) targetAttrs.get(MIBreakpoints.FILE_NAME); |
|
288 |
|
289 if (hostPath != null) { |
|
290 ISourceLookup sourceService = dsfServicesTracker.getService(ISourceLookup.class); |
|
291 |
|
292 ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class); |
|
293 if (srcDmc != null) { |
|
294 sourceService.getDebuggerPath(srcDmc, hostPath, |
|
295 new DataRequestMonitor<String>(dsfSession.getExecutor(), rm) { |
|
296 @Override |
|
297 protected void handleSuccess() { |
|
298 targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData())); |
|
299 rm.done(); |
|
300 } |
|
301 }); |
|
302 } else { |
|
303 // Source lookup not available for given context, use the host |
|
304 // path for the debugger path. |
|
305 targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath)); |
|
306 rm.done(); |
|
307 } |
|
308 } else { |
|
309 // Some types of breakpoints do not require a path |
|
310 // (e.g. watchpoints) |
|
311 rm.done(); |
|
312 } |
|
313 } |
|
314 |
|
315 /** |
|
316 * See bug232415 |
|
317 * |
|
318 * @param path the absolute path to the source file |
|
319 * @return |
|
320 */ |
|
321 private String adjustDebuggerPath(String path) { |
|
322 String result = path; |
|
323 // Make it MinGW-specific |
|
324 if (Platform.getOS().startsWith("win")) { //$NON-NLS-1$ |
|
325 if (!path.startsWith("/")) { //$NON-NLS-1$ |
|
326 result = path.substring(path.lastIndexOf('\\') + 1); |
|
327 } |
|
328 } |
|
329 return result; |
|
330 } |
|
331 |
|
332 /** |
|
333 * Get the list of threads from the platform breakpoint attributes |
|
334 * |
|
335 * @param context |
|
336 * if the context is not null, only get threads that are children |
|
337 * of this context. otherwise get all threads. |
|
338 * @param breakpoint |
|
339 * @return |
|
340 */ |
|
341 private Set<String> extractThreads(IBreakpointsTargetDMContext context, ICBreakpoint breakpoint) { |
|
342 Set<String> results = new HashSet<String>(); |
|
343 |
|
344 // Find the ancestor |
|
345 List<IExecutionDMContext[]> threads = new ArrayList<IExecutionDMContext[]>(1); |
|
346 |
|
347 try { |
|
348 // Retrieve the targets |
|
349 IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint); |
|
350 IContainerDMContext[] targets = filterExtension.getTargetFilters(); |
|
351 |
|
352 // If no target is present, breakpoint applies to all. |
|
353 if (targets.length == 0) { |
|
354 results.add("0"); //$NON-NLS-1$ |
|
355 return results; |
|
356 } |
|
357 |
|
358 // Extract the thread IDs (if there is none, we are covered) |
|
359 for (IContainerDMContext ctxt : targets) { |
|
360 if (context == null || |
|
361 DMContexts.isAncestorOf(ctxt, context)) { |
|
362 threads.add(filterExtension.getThreadFilters(ctxt)); |
|
363 } |
|
364 } |
|
365 } catch (CoreException e1) { |
|
366 } |
|
367 |
|
368 if (supportsThreads(breakpoint)) { |
|
369 for (IExecutionDMContext[] targetThreads : threads) { |
|
370 if (targetThreads != null) { |
|
371 for (IExecutionDMContext thread : targetThreads) { |
|
372 if (thread instanceof IMIExecutionDMContext) { |
|
373 IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread; |
|
374 results.add(((Integer) dmc.getThreadId()).toString()); |
|
375 } |
|
376 } |
|
377 } else { |
|
378 results.add("0"); //$NON-NLS-1$ |
|
379 break; |
|
380 } |
|
381 } |
|
382 } else { |
|
383 results.add("0"); //$NON-NLS-1$ |
|
384 } |
|
385 |
|
386 return results; |
|
387 } |
|
388 |
|
389 /** |
|
390 * Indicates if the back-end supports multiple threads for |
|
391 * this type of breakpoint |
|
392 * |
|
393 * @param breakpoint |
|
394 */ |
|
395 protected boolean supportsThreads(ICBreakpoint breakpoint) { |
|
396 |
|
397 return !(breakpoint instanceof ICWatchpoint); |
|
398 } |
|
399 |
|
400 /** |
|
401 * @param bp |
|
402 * @return |
|
403 * @throws CoreException |
|
404 */ |
|
405 private IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException { |
|
406 return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class); |
|
407 } |
|
408 |
|
409 public Map<String, Object> getAllBreakpointAttributes(IBreakpoint breakpoint, boolean bpManagerEnabled) throws CoreException { |
|
410 |
|
411 assert ! dsfSession.getExecutor().isInExecutorThread(); |
|
412 |
|
413 // Check that the marker exists and retrieve its attributes. |
|
414 // Due to accepted race conditions, the breakpoint marker may become |
|
415 // null while this method is being invoked. In this case throw an exception |
|
416 // and let the caller handle it. |
|
417 IMarker marker = breakpoint.getMarker(); |
|
418 if (marker == null || !marker.exists()) { |
|
419 throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, |
|
420 "Breakpoint marker does not exist", null)); |
|
421 } |
|
422 |
|
423 // Suppress cast warning: platform is still on Java 1.3 |
|
424 @SuppressWarnings("unchecked") |
|
425 Map<String, Object> attributes = marker.getAttributes(); |
|
426 |
|
427 Map<String, Object> targetAttrs = convertAttributes(attributes); |
|
428 |
|
429 // Determine breakpoint type. |
|
430 if (breakpoint instanceof ICWatchpoint) |
|
431 targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT); |
|
432 else if (breakpoint instanceof ICLineBreakpoint) |
|
433 targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); |
|
434 else { |
|
435 // catchpoint? |
|
436 } |
|
437 |
|
438 // Adjust for "skip-all" |
|
439 if (!bpManagerEnabled) { |
|
440 targetAttrs.put(MIBreakpoints.IS_ENABLED, false); |
|
441 } |
|
442 |
|
443 Set<String> threads = extractThreads(null, (ICBreakpoint) breakpoint); |
|
444 targetAttrs.put(ATTR_THREAD_FILTER, threads); |
|
445 |
|
446 return targetAttrs; |
|
447 } |
|
448 |
|
449 public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context, Map<String, Object> attrDelta) { |
|
450 boolean yesWeCan; |
|
451 |
|
452 if (attrDelta.containsKey(MIBreakpoints.IS_ENABLED) && bp != null) { |
|
453 // GDB special: |
|
454 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=261082 |
|
455 // |
|
456 Map<String, Object> delta = new HashMap<String, Object>(attrDelta); |
|
457 |
|
458 delta.remove(MIBreakpoints.IS_ENABLED); |
|
459 |
|
460 yesWeCan = canUpdateAttributes(null, delta); |
|
461 |
|
462 if (yesWeCan) { |
|
463 // other attribute change indicates we can. Now check the ENABLE. |
|
464 // if the breakpoint is already installed in the "context" (a process), |
|
465 // we can. Otherwise no. |
|
466 ITargetBreakpointInfo[] targetBPs = breakpointsMediator.getTargetBreakpoints(context, bp); |
|
467 yesWeCan = targetBPs != null && targetBPs.length > 0; |
|
468 } |
|
469 } |
|
470 else |
|
471 yesWeCan = canUpdateAttributes(null, attrDelta); |
|
472 |
|
473 return yesWeCan; |
|
474 } |
|
475 |
|
476 private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description, final int severity) { |
|
477 |
|
478 new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$ |
|
479 {setSystem(true); }; |
|
480 |
|
481 @Override |
|
482 protected IStatus run(IProgressMonitor monitor) { |
|
483 |
|
484 if (breakpoint instanceof ICLineBreakpoint) { |
|
485 // If we have already have a problem marker on this breakpoint |
|
486 // we should remove it first. |
|
487 IMarker marker = fBreakpointMarkerProblems.remove(breakpoint); |
|
488 if (marker != null) { |
|
489 try { |
|
490 marker.delete(); |
|
491 } catch (CoreException e) { |
|
492 } |
|
493 } |
|
494 |
|
495 ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint; |
|
496 try { |
|
497 // Locate the workspace resource via the breakpoint marker |
|
498 IMarker breakpoint_marker = lineBreakpoint.getMarker(); |
|
499 IResource resource = breakpoint_marker.getResource(); |
|
500 |
|
501 // Add a problem marker to the resource |
|
502 IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID); |
|
503 int line_number = lineBreakpoint.getLineNumber(); |
|
504 problem_marker.setAttribute(IMarker.LOCATION, String.valueOf(line_number)); |
|
505 problem_marker.setAttribute(IMarker.MESSAGE, description); |
|
506 problem_marker.setAttribute(IMarker.SEVERITY, severity); |
|
507 problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number); |
|
508 |
|
509 // And save the baby |
|
510 fBreakpointMarkerProblems.put(breakpoint, problem_marker); |
|
511 } catch (CoreException e) { |
|
512 } |
|
513 } |
|
514 return Status.OK_STATUS; |
|
515 } |
|
516 }.schedule(); |
|
517 } |
|
518 |
|
519 private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) { |
|
520 |
|
521 new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$ |
|
522 {setSystem(true); }; |
|
523 @Override |
|
524 protected IStatus run(IProgressMonitor monitor) { |
|
525 |
|
526 IMarker marker = fBreakpointMarkerProblems.remove(breakpoint); |
|
527 if (marker != null) { |
|
528 try { |
|
529 marker.delete(); |
|
530 } catch (CoreException e) { |
|
531 } |
|
532 } |
|
533 |
|
534 return Status.OK_STATUS; |
|
535 } |
|
536 }.schedule(); |
|
537 } |
|
538 |
|
539 /** |
|
540 */ |
|
541 private void clearBreakpointProblemMarkers() |
|
542 { |
|
543 new Job("Clear Breakpoint problem markers") { //$NON-NLS-1$ |
|
544 { setSystem(true); }; |
|
545 @Override |
|
546 protected IStatus run(IProgressMonitor monitor) { |
|
547 for (IMarker marker : fBreakpointMarkerProblems.values()) { |
|
548 if (marker != null) { |
|
549 try { |
|
550 marker.delete(); |
|
551 } catch (CoreException e) { |
|
552 } |
|
553 } |
|
554 } |
|
555 fBreakpointMarkerProblems.clear(); |
|
556 return Status.OK_STATUS; |
|
557 } |
|
558 }.schedule(); |
|
559 } |
|
560 } |
|
561 |