CDT源代碼框架分析改造(四) 添加斷點流程分析,添加獲取跟蹤點編號。

入口類 ToggleMethodTracepointAction框架

建立一個FunctionBreakpointeclipse

CDIDebugModel.createFunctionBreakpoint(location, getResource(), function, -1, -1, -1, true, 0, "", true, true, false); 

CDIDebugModle中建立。該類時一個debugmodel類,其中大部分是建立方法,在CDT中類型前面以CDI開頭的。都屬於ide

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建立斷點。ui

 

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層建立this

 

通知spa

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的類debug

    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層的斷點管理器就收到通知了code

 

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