Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: fb3cfeda15caad25236995f90de6caf2bb2cb0f5 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                
                                                       

                                                                        
                                                           
                                            
  


                                                                                 

                                      
                         
                         
                          
                     
                     






                                                   
                                      
                                       
                                                

                                                      




                                              







                                                                                            
                                       

           

                                                


                                                           
                                                                             
           
                                                                                                  
 


                                                                                                        
                                                                                                                                         
 




                                                                                                           
 
           
                                                                                                        

                                            
 
           

                                                   
                                             
         
 
           

                                                                                 





                                                                    
 
           
                                                                                 

                                 
                                                                                                     
 

                                                                                 



                                                                                

         

                                                                                          
                                   
                                
                     

                                                                

                                             
                                    
                                                                             


                                          
                             
                                                                           


                                                                                    


                                                            


                                       



                                                           
 

                                           
                 
 
                                        
 

                                                                                               
                                                                     
 

                                                                                                                                                         
 
                                                         
                                                                                               
                                                
                                                                                      


                                                                       
                         


                                            
 


                                                                                                               
                 
         
 




                                                                                            
                                        
                                                                                         
                                                   
                                                                                      




                                                                                      
                         

                 
 




                                                                                      
                                        
                                                                                         
                                                   
                                                                                      




                                                                                      
                         
                 
         
 
           

                                                                                      
           

                                                           
                                                                                           
                                                
                                                                                                    
                                                           
                                                                                              











                                                                                       
                                                                                            



                                                                   

                         
 
         
 
           
                                                         
           

                                                                                      
                                          
                                                                                                                            
                                                      
                                                                                      

                         
         
 
           
                                                      
                                  
          
                                                     

                     


                                                 
 


                                                                  
          





                                                           
 








                                                                
 














                                                                                                     
                         
                                                                             
                         
                                                                               
                         
                                                                          
                         
                                                                          
                         
                                                                           
                         
                                                                                
 


                                                                                                        
                         




                                                                         
 
                 
 


                                                                                                              
                         






                                                                               
 




                                                                                                            
                         
                                                                 
                         




                                                                                              
                         



                                                                                        
 
         
 
 
/*******************************************************************************
 * Copyright (c) 2000, 2013 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.debug.internal.ui;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

/**
 * This class tracks instruction pointer contexts for all active debug targets and threads
 * in the current workbench.  There should only ever be one instance of this class, obtained
 * via 'getDefault()'.
 */
public class InstructionPointerManager{

	/**
	 * The singleton instance of this class.
	 */
	private static InstructionPointerManager fgDefault;

	/**
	 * Set containing all instruction pointer contexts this class manages
	 */
	private Set<InstructionPointerContext> fIPCSet = new HashSet<InstructionPointerContext>();

	/**
	 * Maps ITextEditors to the set of instruction pointer contexts that are displayed in the editor
	 */
	private Map<ITextEditor, Set<InstructionPointerContext>> fEditorMap = new HashMap<ITextEditor, Set<InstructionPointerContext>>();

	/**
	 * Part listener added to editors that contain annotations.  Allows instruction pointer contexts to
	 * be removed when the editor they are displayed in is removed.
	 */
	private IPartListener2 fPartListener;

	/**
	 * Page listener added to the workbench window to remove part listeners when the page is closed.
	 */
	private IPageListener fPageListener;

	/**
	 * Clients must not instantiate this class.
	 */
	private InstructionPointerManager() {
	}

	/**
	 * Return the singleton instance of this class, creating it if necessary.
	 */
	public static InstructionPointerManager getDefault() {
		if (fgDefault == null) {
			fgDefault = new InstructionPointerManager();
		}
		return fgDefault;
	}

	/**
	 * Adds an instruction pointer annotation in the specified editor for the
	 * specified stack frame.
	 */
	public void addAnnotation(ITextEditor textEditor, IStackFrame frame, Annotation annotation) {

		IDocumentProvider docProvider = textEditor.getDocumentProvider();
		IEditorInput editorInput = textEditor.getEditorInput();
        // If there is no annotation model, there's nothing more to do
        IAnnotationModel annModel = docProvider.getAnnotationModel(editorInput);
        if (annModel == null) {
            return;
        }

		// Create the Position object that specifies a location for the annotation
		Position position = null;
		int charStart = -1;
		int length = -1;
		try {
			charStart = frame.getCharStart();
			length = frame.getCharEnd() - charStart;
		} catch (DebugException de) {
		}
		if (charStart < 0) {
			IDocument doc = docProvider.getDocument(editorInput);
			if (doc == null) {
				return;
			}
			try {
				int lineNumber = frame.getLineNumber() - 1;
				IRegion region = doc.getLineInformation(lineNumber);
				charStart = region.getOffset();
				length = region.getLength();
			} catch (BadLocationException ble) {
				return;
			} catch (DebugException de) {
				return;
			}
		}
		if (charStart < 0) {
			return;
		}
		position = new Position(charStart, length);

		if (frame.isTerminated()) {
			return;
		}

		synchronized (fIPCSet) {

			// Add the annotation at the position to the editor's annotation model.
			annModel.removeAnnotation(annotation);
			annModel.addAnnotation(annotation, position);

			// Create the instruction pointer context
			InstructionPointerContext ipc = new InstructionPointerContext(frame.getDebugTarget(), frame.getThread(), textEditor, annotation);

			// Add the IPC to the set and map
			Set<InstructionPointerContext> editorIPCs = fEditorMap.get(textEditor);
			if (editorIPCs == null){
				editorIPCs = new HashSet<InstructionPointerContext>();
				fEditorMap.put(textEditor, editorIPCs);
			} else {
				editorIPCs.remove(ipc);
			}
			editorIPCs.add(ipc);
			fIPCSet.remove(ipc);
			fIPCSet.add(ipc);

			// Add a listener to the editor so we can remove the IPC when the editor is closed
			textEditor.getSite().getPage().addPartListener(getPartListener());
			textEditor.getSite().getPage().getWorkbenchWindow().addPageListener(getPageListener());
		}
	}

	/**
	 * Remove all annotations associated with the specified debug target that this class
	 * is tracking.
	 */
	public void removeAnnotations(IDebugTarget debugTarget) {
		synchronized (fIPCSet) {
			Iterator<InstructionPointerContext> ipcIter = fIPCSet.iterator();
			while (ipcIter.hasNext()) {
				InstructionPointerContext currentIPC = ipcIter.next();
				if (currentIPC.getDebugTarget().equals(debugTarget)){
					removeAnnotationFromModel(currentIPC);
					ipcIter.remove();
					removeAnnotationFromEditorMapping(currentIPC);
				}
			}
		}
	}

	/**
	 * Remove all annotations associated with the specified thread that this class
	 * is tracking.
	 */
	public void removeAnnotations(IThread thread) {
		synchronized (fIPCSet) {
			Iterator<InstructionPointerContext> ipcIter = fIPCSet.iterator();
			while (ipcIter.hasNext()) {
				InstructionPointerContext currentIPC = ipcIter.next();
				if (currentIPC.getThread().equals(thread)){
					removeAnnotationFromModel(currentIPC);
					ipcIter.remove();
					removeAnnotationFromEditorMapping(currentIPC);
				}
			}
		}
	}

	/**
	 * Remove all annotations associated with the specified editor that this class
	 * is tracking.
	 */
	public void removeAnnotations(ITextEditor editor) {
		synchronized (fIPCSet) {
			Set<InstructionPointerContext> editorIPCs = fEditorMap.get(editor);
			if (editorIPCs != null){
				Iterator<InstructionPointerContext> ipcIter = editorIPCs.iterator();
				while (ipcIter.hasNext()) {
					InstructionPointerContext currentIPC = ipcIter.next();
					removeAnnotationFromModel(currentIPC);
					fIPCSet.remove(currentIPC);
				}
				fEditorMap.remove(editor);
			}
		}
	}

	/**
	 * Remove the given ipc from the mapping of editors.
	 */
	private void removeAnnotationFromEditorMapping(InstructionPointerContext ipc) {
		Set<InstructionPointerContext> editorIPCs = fEditorMap.get(ipc.getEditor());
		if (editorIPCs != null){
			editorIPCs.remove(ipc);
			if (editorIPCs.isEmpty()){
				fEditorMap.remove(ipc.getEditor());
			}
		}

	}

	/**
	 * Remove the annotation from the document model.
	 */
	private void removeAnnotationFromModel(InstructionPointerContext ipc){
		IDocumentProvider docProvider = ipc.getEditor().getDocumentProvider();
		if (docProvider != null) {
			IAnnotationModel annotationModel = docProvider.getAnnotationModel(ipc.getEditor().getEditorInput());
			if (annotationModel != null) {
				annotationModel.removeAnnotation(ipc.getAnnotation());
			}
		}
	}

	/**
	 * Returns the number of instruction pointers.
	 * Used by the test suite.
	 *
	 * @return the number of instruction pointers
	 * @since 3.2
	 */
	public int getInstructionPointerCount() {
		return fIPCSet.size();
	}

	/**
	 * Returns the number of keys in the editor to IPC mapping
	 * Used by the test suite.
	 *
	 * @return the number of keys in the editor mapping
	 * @since 3.3
	 */
	public int getEditorMappingCount() {
		return fEditorMap.size();
	}

	/**
	 * @return the page listener to add to workbench window.
	 */
	private IPageListener getPageListener(){
		if (fPageListener == null){
			fPageListener = new PageListener();
		}
		return fPageListener;
	}

	/**
	 * @return the part listener to add to editors.
	 */
	private IPartListener2 getPartListener(){
		if (fPartListener == null){
			fPartListener = new PartListener();
		}
		return fPartListener;
	}

	/**
	 * Part listener that is added to editors to track when the editor is no longer is displaying
	 * the input containing instruction pointer annotations.
	 */
	class PartListener implements IPartListener2{
		@Override
		public void partActivated(IWorkbenchPartReference partRef) {}
		@Override
		public void partDeactivated(IWorkbenchPartReference partRef) {}
		@Override
		public void partHidden(IWorkbenchPartReference partRef) {}
		@Override
		public void partOpened(IWorkbenchPartReference partRef) {}
		@Override
		public void partVisible(IWorkbenchPartReference partRef) {}
		@Override
		public void partBroughtToTop(IWorkbenchPartReference partRef) {}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
		 */
		@Override
		public void partClosed(IWorkbenchPartReference partRef) {
			IWorkbenchPart part = partRef.getPart(false);
			if (part instanceof ITextEditor){
				removeAnnotations((ITextEditor)part);
			}

		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
		 */
		@Override
		public void partInputChanged(IWorkbenchPartReference partRef) {
			IWorkbenchPart part = partRef.getPart(false);
			if (part instanceof ITextEditor){
				removeAnnotations((ITextEditor)part);
			}
		}
	}

	/**
	 * Page listener that is added to the workbench to remove the part listener when the page is closed.
	 */
	class PageListener implements IPageListener{

		@Override
		public void pageActivated(IWorkbenchPage page) {}
		@Override
		public void pageOpened(IWorkbenchPage page) {}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.IPageListener#pageClosed(org.eclipse.ui.IWorkbenchPage)
		 */
		@Override
		public void pageClosed(IWorkbenchPage page) {
			page.removePartListener(getPartListener());
			page.getWorkbenchWindow().removePageListener(getPageListener());
		}

	}

}

Back to the top