入口类 ToggleMethodTracepointAction
创建一个FunctionBreakpoint
CDIDebugModel.createFunctionBreakpoint(location, getResource(), function, -1, -1, -1, true, 0, "", true, true, false);
CDIDebugModle中创建。该类时一个debugmodel类,其中大部分是创建方法,在CDT中类型前面以CDI开头的。都属于
Debug。跟CDT的桥梁类。
/** * @param sourceHandle * @param resource * @param function * @param charStart * @param charEnd * @param lineNumber * @param enabled * @param ignoreCount * @param condition * @param register * @param type * @param temporary * @return * @throws CoreException */ public static ICFunctionBreakpoint createFunctionBreakpoint( String sourceHandle, IResource resource, String function, int charStart, int charEnd, int lineNumber, boolean enabled, int ignoreCount, String condition, boolean register, boolean isGlobal, boolean temporary ) throws CoreException { HashMap attributes = new HashMap(10); // attributes.put(IBreakpoint.ID, getPluginIdentifier()); attributes.put(IBreakpoint.ID, getPluginIdentifier()); attributes.put(IMarker.CHAR_START, new Integer(charStart)); attributes.put(IMarker.CHAR_END, new Integer(charEnd)); attributes.put(IMarker.LINE_NUMBER, new Integer(lineNumber)); attributes.put(ICLineBreakpoint.FUNCTION, function); attributes.put(IBreakpoint.ENABLED, Boolean.valueOf(enabled)); attributes.put(ICBreakpoint.IGNORE_COUNT, new Integer(ignoreCount)); attributes.put(ICBreakpoint.CONDITION, condition); attributes.put(ICBreakpoint.SOURCE_HANDLE, sourceHandle); attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary)); attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary)); attributes.put(ICBreakpoint.TEMPORARY, new Boolean(temporary)); attributes.put(ICFunctionBreakpoint.FUNCTION_BREAKPOINT_ID, getFunctionBreakpointId()); attributes.put(ICBreakpoint.TYPE, isGlobal?ICBreakpoint.GLOBAL_BREAKPOINT:ICBreakpoint.LOCAL_BREAKPOINT); attributes.put(ICBreakpoint.BREAKPOINT_ID, getBreakpointID()); return new CFunctionBreakpoint(resource, attributes, register); }
FunctionBreakpoint就是debug层的断点对象。其父类为CBreakpoint对象,在父类的构造函数中中,通知BreakpointManager创建断点。
Class CBreakpoint{ ... public CBreakpoint( final IResource resource, final String markerType, final Map attributes, final boolean add ) throws CoreException { this(); IWorkspaceRunnable wr = new IWorkspaceRunnable() { public void run( IProgressMonitor monitor ) throws CoreException { // create the marker setMarker( resource.createMarker( markerType ) ); // set attributes ensureMarker().setAttributes( attributes ); //set the marker message setAttribute( IMarker.MESSAGE, getMarkerMessage() ); // add to breakpoint manager if requested register( add ); } }; run( wr ); } ** * Add this breakpoint to the breakpoint manager, or sets it as * unregistered. */ public void register( boolean register ) throws CoreException { if ( register ) { DebugPlugin.getDefault().getBreakpointManager().addBreakpoint( this ); } /* * else { setRegistered( false ); } */ } }
通知CDT层创建
通知
private void fireUpdate(List breakpoints, List deltas, int update) { if (breakpoints.isEmpty()) { return; } IBreakpoint[] bpArray = (IBreakpoint[])breakpoints.toArray(new IBreakpoint[breakpoints.size()]); IMarkerDelta[] deltaArray = new IMarkerDelta[bpArray.length]; if (deltas != null) { deltaArray = (IMarkerDelta[])deltas.toArray(deltaArray); } // single listeners getBreakpointNotifier().notify(bpArray, deltaArray, update); // plural listeners getBreakpointsNotifier().notify(bpArray, deltaArray, update); }
所有实现了IBreakpointsListner的类
public void notify(IBreakpoint[] breakpoints, IMarkerDelta[] deltas, int update) { fType = update; fNotifierBreakpoints = breakpoints; fDeltas = deltas; Object[] copiedListeners = fBreakpointsListeners.getListeners(); for (int i= 0; i < copiedListeners.length; i++) { fListener = (IBreakpointsListener)copiedListeners[i]; SafeRunner.run(this); } fDeltas = null; fNotifierBreakpoints = null; fListener = null; }
这时候CBreakpointManager这个C层的断点管理器就收到通知了
breakpointsAdded 方法最后调用了setBreakpointsOnTarget0。而这个方法就关联到ICDIFunctionLocation
总结一下,其实整个断点的模型就是一个通知监听模式,当视图上创建了一个断点后,就通知管理器下发创建命令。而实现了断点监听的就负责创建。这时候cdt层CBreakpointManager首先了该监听。开始创建。当然还可以有其它的模型。这个可以看下debug的源码。 管理器中 setBreakpointsOnTarget0 。调用了ICDIBreakpointManagement2。创建断点。这里就调用了cdt层的Target目标机。然后继续向cdt下发。最后发送命令。
整个eclipse 源码都大量采用了这种模型框架。因此搞清楚这个原理。看源代码就好理解的多了
现在看下让断点视图上显示跟踪点的id。开始改造
CBreakpointManager类中的 setBreakpointsOnTarget0 这个方法差不多就是ui 跟cdt的创建断点的纽带。
我们现在需要的是cdt层的断点下发创建断点命令后,返回的跟踪点id。在ui层展示。因此在ui层我们需要CFunctionBreakpoint类来给我跟踪点的id
因此ICFunctionBreakpoint接口中我们创建跟踪点的参数跟方法
public interface ICFunctionBreakpoint extends ICLineBreakpoint { /** * 断点返回的跟踪点的信息 * wangmin */ public static final String FUNCTION_TRACEPOINT_ID="org.eclipse.cdt.debug.core.funcTracepointId";
/***
*
* 跟踪点的id
* @param symbolFile
* @throws CoreException
*/
public void setNumber( String number ) throws CoreException;
public String getNumber( String number ) throws CoreException;
}
CFunctionBreakpoint中实现接口。采用IMarker的形式保存参数
@Override public void setNumber(int number) throws CoreException { // TODO 自动生成的方法存根 setAttribute(ICFunctionBreakpoint.FUNCTION_TRACEPOINT_ID, number); } @Override public int getNumber(int number) throws CoreException { // TODO 自动生成的方法存根 return getMarker().getAttribute(ICFunctionBreakpoint.FUNCTION_TRACEPOINT_ID, 0); }
好了。。现在就需要让cdt层的断电来告诉最后的跟踪点id。
继续看CBreakpointManager 找到 doHandleLocationBreakpointCreatedEvent 这是一个 事件通知 。。嗯。cdt源码还有很重要的一种事件通知框架模型。这个以后说
这里只需要知道cdt创建完成之后这个方法就会被触发。这里我们就获取到了cdt创建完成后的 ICDILocationBreakpoint接口 so。就可以将ui层之前定义的跟踪点。设置进来了。
哦。cdt层也要改造。让它携带跟踪点id。首先时 ICDIBreakpoint接口 定义
/*** * * * @return */ public int getNumber() ;
然后是其子类。:AddressBreakpoint,FunctionBreakpoint,LineBreakpoint
在其抽象父类实现LocationBreakpoint MIBreakpoint miBreakpoints 这个就是命令下发后返回的解析后的信息类
public int getNumber() { if (miBreakpoints != null && miBreakpoints.length > 0) { return miBreakpoints[0].getNumber(); } return 0; }
最后在doHandleLocationBreakpointCreatedEvent 方法中对接
synchronized private void doHandleLocationBreakpointCreatedEvent( ICDILocationBreakpoint cdiBreakpoint ) { ... if (breakpoint instanceof ICFunctionBreakpoint && ((ICFunctionBreakpoint) breakpoint).getCharStart() == -1 && ((ICFunctionBreakpoint) breakpoint).getCharEnd() == -1) { ICFunctionBreakpoint bp = (ICFunctionBreakpoint)cTopMap.get(breakpoint); bp.setNumber(cdiBreakpoint.getNumber()); ... } }
ok..这样就可以获取了number了
org.eclipse.cdt.debug.internal.ui 包下
CBreakpointActionsPage类
//显示number