package net.sourceforge.pmd.eclipse.plugin; import java.util.HashSet; import java.util.Set; import name.herlin.command.CommandException; import net.sourceforge.pmd.eclipse.runtime.builder.MarkerUtil; import net.sourceforge.pmd.eclipse.runtime.cmd.ReviewCodeCmd; import org.apache.log4j.Logger; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IWorkspaceDescription; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; /** * Monitors for changes in the workspace and initiates the ReviewCodeCmd when * suitable file changes in some meaningful way. * * @author Brian Remedios */ public class FileChangeReviewer implements IResourceChangeListener { public FileChangeReviewer() { } private enum ChangeType { ADDED, REMOVED, CHANGED } private class ResourceChange { public final ChangeType resourceDeltaType; public final int flags; public final IFile file; private ResourceChange(ChangeType type, IFile theFile, int theFlags) { resourceDeltaType = type; file = theFile; flags = theFlags; } public int hashCode() { return resourceDeltaType.hashCode() + 13 + file.hashCode() + flags; } public boolean equals(Object other) { if (other == null) return false; if (other == this) return true; if (other.getClass() == getClass()) { ResourceChange chg = (ResourceChange) other; return chg.file.equals(file) && resourceDeltaType == chg.resourceDeltaType && flags == chg.flags; } return false; } } /** * @param event */ public void resourceChanged(IResourceChangeEvent event) { IWorkspaceDescription workspaceSettings = ResourcesPlugin.getWorkspace().getDescription(); if (workspaceSettings.isAutoBuilding()) { PMDPlugin.getDefault().logInformation("Not running PMD via FileChangeReviewer, as autoBuilding is enabled for this workspace"); return; } Set<ResourceChange> itemsChanged = new HashSet<ResourceChange>(); switch (event.getType()) { // case IResourceChangeEvent.PRE_DELETE: // case IResourceChangeEvent.PRE_CLOSE: // case IResourceChangeEvent.PRE_BUILD: // case IResourceChangeEvent.POST_BUILD: // case IResourceChangeEvent.PRE_REFRESH: case IResourceChangeEvent.POST_CHANGE: changed(itemsChanged, event.getDelta(), new NullProgressMonitor()); } if (itemsChanged.isEmpty()) return; ReviewCodeCmd cmd = new ReviewCodeCmd(); // separate one for each thread cmd.reset(); for (ResourceChange chg : itemsChanged) cmd.addResource(chg.file); try { cmd.performExecute(); } catch (CommandException e) { PMDPlugin.getDefault().log(IStatus.ERROR, "Error processing code review upon file changes", e); } } private void changed(Set<ResourceChange> itemsChanged, IResourceDelta delta, IProgressMonitor monitor) { IResource rsc = delta.getResource(); int flags = delta.getFlags(); switch (delta.getKind()) { case IResourceDelta.NO_CHANGE: return; case IResourceDelta.REMOVED: // if (rsc instanceof IProject) { // removed(itemsChanged, (IProject)rsc, delta.getFlags()); // } // if (rsc instanceof IFile) { // removed(itemsChanged, (IFile)rsc, flags, true); // } for (IResourceDelta grandkidDelta : delta.getAffectedChildren()) { if (monitor.isCanceled()) return; changed(itemsChanged, grandkidDelta, monitor); } break; case IResourceDelta.ADDED: // if (rsc instanceof IProject) { // removed(itemsChanged, (IProject)rsc, delta.getFlags()); // } if (rsc instanceof IFile) { added(itemsChanged, (IFile) rsc, flags, true); } for (IResourceDelta grandkidDelta : delta.getAffectedChildren()) { if (monitor.isCanceled()) return; changed(itemsChanged, grandkidDelta, monitor); } break; case IResourceDelta.CHANGED: // if (rsc instanceof IProject) { // changed(itemsChanged, (IProject)rsc, delta.getFlags()); // } if (rsc instanceof IFile) { changed(itemsChanged, (IFile) rsc, flags, true); } for (IResourceDelta grandkidDelta : delta.getAffectedChildren()) { if (monitor.isCanceled()) return; changed(itemsChanged, grandkidDelta, monitor); } break; default: for (IResourceDelta grandkidDelta : delta.getAffectedChildren()) { if (monitor.isCanceled()) return; changed(itemsChanged, grandkidDelta, monitor); } } } private void changed(Set<ResourceChange> itemsChanged, IFile rsc, int flags, boolean b) { if ((flags & IResourceDelta.CONTENT) > 0) { itemsChanged.add(new ResourceChange(ChangeType.CHANGED, rsc, flags)); } } private void added(Set<ResourceChange> itemsChanged, IFile rsc, int flags, boolean b) { itemsChanged.add(new ResourceChange(ChangeType.ADDED, rsc, flags)); // System.out.println("added: " + rsc); } // private void changed(Set<ResourceChange> itemsChanged, IProject rsc, int // flags) { // System.out.println("changed: " + rsc); // } // // // private void removed(Set<ResourceChange> itemsChanged, IFile rsc, int // flags, boolean b) { // itemsChanged.add( new ResourceChange(ChangeType.REMOVED, rsc, flags)); // System.out.println("removed: " + rsc); // } // // private void removed(Set<ResourceChange> itemsChanged, IProject rsc, int // flags) { // System.out.println("removed: " + rsc); // } }