package gb.svnfilter.junit; import gb.svnfilter.junit.actions.RunJUnitSelectedTestsAction; import java.util.ArrayList; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageDeclaration; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ui.ISharedImages; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.ViewPart; /** * Viewer for which classes are affected by changes to a particular project */ public class AffectedTestView extends ViewPart implements ISelectionListener { private TreeViewer viewer; private CalledFile treeRoot = null; private final RunJUnitSelectedTestsAction runAction; /** * Tree object hierarchy: * TreeObject * -> TreeParent */ /** * Tree objects */ public class CallingTest { /** * Name of this element */ protected final String name; private CalledFile parent; private IType type; /** * cTor * @param name */ public CallingTest(String name) { this.name = name; } /** * @return name of this node */ public String getName() { return name; } /** * @param parent Parent of this node */ public void setParent(CalledFile parent) { this.parent = parent; } /** * @return Parent of this node */ public CalledFile getParent() { return parent; } @Override public String toString() { return getName(); } /** * @return Resource associated with this node */ protected IResource getResouce() { if (this.type != null) { return type.getResource(); } return null; } /** * @param type Type associated with this node */ protected void setType(IType type) { this.type = type; } /** * @return Type associated with this node */ public IType getType() { return type; } } /** * Tree object used for the top level java element */ public class CalledFile extends CallingTest { private final ArrayList<CallingTest> children = new ArrayList<CallingTest>(); private final IJavaElement thisJavaElement; /** * cTor * @param xiEditJavaElement */ public CalledFile(IJavaElement xiEditJavaElement) { super(xiEditJavaElement.getElementName()); thisJavaElement = xiEditJavaElement; Map<String, Set<String>> coverageData = JCallDBLoader.loadJCallDB(thisJavaElement.getJavaProject().getProject()); if (coverageData != null) { if (thisJavaElement.getElementType() == IJavaElement.COMPILATION_UNIT) { ICompilationUnit compUnit = (ICompilationUnit)thisJavaElement; String fullPath = getFullPath(compUnit); Set<String> fileCallers = coverageData.get(fullPath); if (fileCallers != null) { IJavaProject jproj = compUnit.getJavaProject(); Set<String> sortedFileCallers = new TreeSet<String>(fileCallers); for (String caller : sortedFileCallers) { CallingTest child = new CallingTest(caller); try { IType childType = jproj.findType(caller); child.setType(childType); } catch (JavaModelException e) { // Throw away } children.add(child); } } } } else { CallingTest child = new CallingTest("No coverage db: test.jcalldb"); children.add(child); } } // TODO : This probably breaks for file not in a package! private String getFullPath(ICompilationUnit xiCompUnit) { String path = null; try { IPackageDeclaration[] packDecls = xiCompUnit.getPackageDeclarations(); String packageDecl = packDecls[0].getElementName(); String packagePath = packageDecl.replace(".", "/"); String fileName = thisJavaElement.getElementName(); path = packagePath + "/" + fileName; } catch (JavaModelException e) { // Throw away } return path; } /** * Special cTor for blank top level elements * @param xiName */ public CalledFile(String xiName) { super(xiName); thisJavaElement = null; CallingTest child = new CallingTest("Not a java file in a java project"); children.add(child); } /** * @return Children of this object */ public CallingTest[] getChildren() { return children.toArray(new CallingTest[children.size()]); } /** * @return Whether this node has children */ public boolean hasChildren() { return children.size() > 0; } } /** * Content provider for this view */ class ViewContentProvider implements ITreeContentProvider { @SuppressWarnings("unused") public void inputChanged(Viewer v, Object oldInput, Object newInput) { // Do nothing } public void dispose() { // Do nothing } public Object[] getElements(Object parent) { if (parent.equals(getViewSite())) { if (treeRoot != null) { return new Object[] {treeRoot}; } return new Object[0]; } return getChildren(parent); } public Object getParent(Object child) { if (child instanceof CallingTest) { return ((CallingTest) child).getParent(); } return null; } public Object[] getChildren(Object parent) { if (parent instanceof CalledFile) { return ((CalledFile) parent).getChildren(); } return new Object[0]; } public boolean hasChildren(Object parent) { if (parent instanceof CalledFile) return ((CalledFile) parent).hasChildren(); return false; } } /** * Label provider */ class ViewLabelProvider extends LabelProvider { @Override public Image getImage(Object obj) { String imageKey = ISharedImages.IMG_OBJS_CUNIT; if (obj instanceof CalledFile) imageKey = ISharedImages.IMG_OBJS_CLASS; return JavaUI.getSharedImages().getImage(imageKey); } } /** * cTor */ public AffectedTestView() { runAction = new RunJUnitSelectedTestsAction(); } @Override public void createPartControl(Composite parent) { getSite().getPage().addSelectionListener(this); viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); viewer.setInput(getViewSite()); hookDoubleClickAction(); // Setup Context Menu MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ viewer.getControl().setMenu(menuMgr.createContextMenu(viewer.getControl())); menuMgr.add(runAction); viewer.addSelectionChangedListener(runAction); } private void hookDoubleClickAction() { viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { ISelection selection = event.getSelection(); Object obj = ((IStructuredSelection) selection).getFirstElement(); if (!(obj instanceof CallingTest)) { return; } CallingTest tempObj = (CallingTest) obj; IResource tempObjRes = tempObj.getResouce(); if (tempObjRes != null) { IFile ifile = ResourcesPlugin.getWorkspace().getRoot().getFile( tempObjRes.getFullPath()); IWorkbenchPage dpage = AffectedTestView.this.getViewSite() .getWorkbenchWindow().getActivePage(); if (dpage != null) { try { IDE.openEditor(dpage, ifile, true); } catch (Exception e) { // Do nothing } } } } }); } @Override public void setFocus() { viewer.getControl().setFocus(); } @Override public void selectionChanged(IWorkbenchPart xiPart, @SuppressWarnings("unused") ISelection xiSelection) { if (xiPart instanceof IEditorPart) { IEditorPart editPart = (IEditorPart)xiPart; IEditorInput editInput = editPart.getEditorInput(); IJavaElement editJavaElement = JavaUI.getEditorInputJavaElement(editInput); if (editJavaElement != null) { treeRoot = new CalledFile(editJavaElement); IJavaProject project = editJavaElement.getJavaProject(); runAction.projectChanged(project); } else { treeRoot = new CalledFile(editInput.getName()); } // Refresh once to pickup the new root viewer.refresh(); // Expand the new root then refresh again viewer.setExpandedState(treeRoot, true); viewer.refresh(treeRoot); } } }