Completed the automatic 'check on file save' function that initiates a code review whenever changes are saved to a code file. Enable it on the main PMD preference page as it is off by default.
git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@7599 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
@ -5,6 +5,7 @@ v4.0.0 - xxx 2011?
|
||||
. New rule creation wizard
|
||||
. New report preferences panel
|
||||
. New file filter panel for exclusion/inclusion entries
|
||||
. New automatic "Check code on file save" function (off by default)
|
||||
. User-definable rule violation markers
|
||||
Highest priority markers also decorate folders & projects (selectable)
|
||||
. Colour syntax highlighting in code viewers/editors
|
||||
|
@ -15,9 +15,6 @@ There's a whole lot of layers, can we simply things a bit?
|
||||
|
||||
Upgrade plugin code to Java 5.
|
||||
|
||||
Allow import of a single rule from a RuleSet.
|
||||
Warn if Import of a Rule results in a duplicate (what is a duplicate exactly?), allow option to Import All, Import Non Duplicates, or Cancel.
|
||||
Warn if newly Added Rule has the name of an existing Rule.
|
||||
Warn if non reference Rule looks like it might be a built-in PMD rule, and ask if replace with reference. On Add? On Import? On Upgrade?
|
||||
Add Upgrade button, which will check current workspace RuleSet against PMD rules showing differences (new PMD rules, rules in
|
||||
Allow checking to see what rules from PMD are missing (useful for upgrade process).
|
||||
|
@ -0,0 +1,22 @@
|
||||
package net.sourceforge.pmd.eclipse.plugin;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Brian Remedios
|
||||
*/
|
||||
public class EclipseUtil {
|
||||
|
||||
public static final IProgressMonitor DUMMY_MONITOR = new IProgressMonitor() {
|
||||
|
||||
public void beginTask(String name, int totalWork) { }
|
||||
public void done() { }
|
||||
public void internalWorked(double work) { }
|
||||
public boolean isCanceled() { return false; }
|
||||
public void setCanceled(boolean value) { }
|
||||
public void setTaskName(String name) { }
|
||||
public void subTask(String name) { }
|
||||
public void worked(int work) { }
|
||||
};
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
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.cmd.ReviewCodeCmd;
|
||||
|
||||
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.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
||||
/**
|
||||
* 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 == 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) {
|
||||
|
||||
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(), EclipseUtil.DUMMY_MONITOR);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -46,8 +46,6 @@ import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IFolder;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IResourceChangeEvent;
|
||||
import org.eclipse.core.resources.IResourceChangeListener;
|
||||
import org.eclipse.core.resources.IWorkspace;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
@ -72,10 +70,12 @@ import org.osgi.framework.BundleContext;
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class PMDPlugin extends AbstractUIPlugin implements IResourceChangeListener {
|
||||
public class PMDPlugin extends AbstractUIPlugin {
|
||||
|
||||
private static File pluginFolder;
|
||||
|
||||
private FileChangeReviewer changeReviewer;
|
||||
|
||||
private Map<RGB, Color> coloursByRGB = new HashMap<RGB, Color>();
|
||||
|
||||
public static final String PLUGIN_ID = "net.sourceforge.pmd.eclipse.plugin";
|
||||
@ -181,17 +181,19 @@ public class PMDPlugin extends AbstractUIPlugin implements IResourceChangeListen
|
||||
registerAdditionalRuleSets();
|
||||
fileChangeListenerEnabled(prefs.isCheckAfterSaveEnabled());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void fileChangeListenerEnabled(boolean flag) {
|
||||
|
||||
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||
|
||||
if (flag) {
|
||||
workspace.addResourceChangeListener(this);
|
||||
if (changeReviewer == null) changeReviewer = new FileChangeReviewer();
|
||||
workspace.addResourceChangeListener(changeReviewer);
|
||||
} else {
|
||||
workspace.removeResourceChangeListener(this);
|
||||
if (changeReviewer != null) {
|
||||
workspace.removeResourceChangeListener(changeReviewer);
|
||||
changeReviewer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,14 +566,5 @@ public class PMDPlugin extends AbstractUIPlugin implements IResourceChangeListen
|
||||
decorator.changed(changes);
|
||||
}
|
||||
|
||||
public void resourceChanged(IResourceChangeEvent event) {
|
||||
|
||||
// switch (event.getType()) {
|
||||
// case PRE_DELETE:
|
||||
// case POST_CHANGE:
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
package net.sourceforge.pmd.eclipse.runtime.cmd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -191,7 +192,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
};
|
||||
|
||||
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||
workspace.run(action, getschedulingRule(), IWorkspace.AVOID_UPDATE, getMonitor());
|
||||
workspace.run(action, getSchedulingRule(), IWorkspace.AVOID_UPDATE, getMonitor());
|
||||
|
||||
// Switch to the PMD perspective if required
|
||||
if (openPmdPerspective) {
|
||||
@ -239,7 +240,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
/**
|
||||
* @param resource The resource to set.
|
||||
*/
|
||||
public void setResources(final List<ISchedulingRule> resources) {
|
||||
public void setResources(Collection<ISchedulingRule> resources) {
|
||||
resources.clear();
|
||||
resources.addAll(resources);
|
||||
}
|
||||
@ -249,7 +250,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
*
|
||||
* @param resource a workbench resource
|
||||
*/
|
||||
public void addResource(final IResource resource) {
|
||||
public void addResource(IResource resource) {
|
||||
if (resource == null) {
|
||||
throw new IllegalArgumentException("Resource parameter can not be null");
|
||||
}
|
||||
@ -260,14 +261,14 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
/**
|
||||
* @param resourceDelta The resourceDelta to set.
|
||||
*/
|
||||
public void setResourceDelta(final IResourceDelta resourceDelta) {
|
||||
public void setResourceDelta(IResourceDelta resourceDelta) {
|
||||
this.resourceDelta = resourceDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param taskMarker The taskMarker to set.
|
||||
*/
|
||||
public void setTaskMarker(final boolean taskMarker) {
|
||||
public void setTaskMarker(boolean taskMarker) {
|
||||
this.taskMarker = taskMarker;
|
||||
}
|
||||
|
||||
@ -302,7 +303,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
/**
|
||||
* @return the scheduling rule needed to apply markers
|
||||
*/
|
||||
private ISchedulingRule getschedulingRule() {
|
||||
private ISchedulingRule getSchedulingRule() {
|
||||
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||
final IResourceRuleFactory ruleFactory = workspace.getRuleFactory();
|
||||
ISchedulingRule rule = null;
|
||||
@ -548,6 +549,11 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
* @return the element count
|
||||
*/
|
||||
private int countResourceElement(IResource resource) {
|
||||
|
||||
if (resource instanceof IFile) {
|
||||
return isSuitable((IFile)resource) ? 1 : 0;
|
||||
}
|
||||
|
||||
final CountVisitor visitor = new CountVisitor();
|
||||
|
||||
try {
|
||||
@ -589,17 +595,21 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
window.getActivePage().setPerspective(reg.findPerspectiveWithId(PMDRuntimeConstants.ID_PERSPECTIVE));
|
||||
}
|
||||
|
||||
private static boolean isSuitable(IFile file) {
|
||||
return isLanguageFile(file, Language.JAVA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private inner class to count the number of resources or delta elements
|
||||
*/
|
||||
private final class CountVisitor implements IResourceVisitor, IResourceDeltaVisitor {
|
||||
public int count = 0;
|
||||
|
||||
public boolean visit(final IResource resource) {
|
||||
public boolean visit(IResource resource) {
|
||||
boolean fVisitChildren = true;
|
||||
count++;
|
||||
|
||||
if (resource instanceof IFile && isLanguageFile((IFile) resource, Language.JAVA)) {
|
||||
if (resource instanceof IFile && isSuitable((IFile) resource)) {
|
||||
|
||||
fVisitChildren = false;
|
||||
}
|
||||
@ -608,7 +618,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand {
|
||||
}
|
||||
|
||||
// @PMD:REVIEWED:UnusedFormalParameter: by Herlin on 10/05/05 23:46
|
||||
public boolean visit(final IResourceDelta delta) {
|
||||
public boolean visit(IResourceDelta delta) {
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ public class PMDCheckAction extends AbstractUIAction {
|
||||
}
|
||||
|
||||
// Run the command
|
||||
setupAndExecute(cmd, countElement(selection));
|
||||
setupAndExecute(cmd, countElements(selection));
|
||||
}
|
||||
|
||||
private void addAdaptable(ReviewCodeCmd cmd, IAdaptable adaptable) {
|
||||
@ -186,7 +186,7 @@ public class PMDCheckAction extends AbstractUIAction {
|
||||
* @param selection a selection
|
||||
* @return the element count
|
||||
*/
|
||||
private int countElement(IStructuredSelection selection) {
|
||||
private int countElements(IStructuredSelection selection) {
|
||||
CountVisitor visitor = new CountVisitor();
|
||||
|
||||
for (Iterator<?> i = selection.iterator(); i.hasNext();) {
|
||||
|
@ -550,7 +550,6 @@ public class GeneralPreferencesPage extends PreferencePage implements IWorkbench
|
||||
Button button = new Button(viewGroup, SWT.CHECK);
|
||||
button.setText("Check code after saving");
|
||||
button.setSelection(preferences.isCheckAfterSaveEnabled());
|
||||
button.setEnabled(false); // FIXME - make it real
|
||||
return button;
|
||||
}
|
||||
|
||||
@ -758,6 +757,8 @@ System.out.println("updating icons");
|
||||
}
|
||||
|
||||
preferences.sync();
|
||||
|
||||
PMDPlugin.getDefault().fileChangeListenerEnabled(checkCodeOnSave.getSelection());
|
||||
PMDPlugin.getDefault().applyLogPreferences(preferences);
|
||||
|
||||
return true;
|
||||
|
@ -27,7 +27,6 @@ new CPD view
|
||||
|
||||
Preferences
|
||||
General Page
|
||||
Enable 'check code after saving' button when working
|
||||
Refresh whole Eclipse UI to obtain updated RulePriority settings
|
||||
Rework Logging Options section - lose the slider!
|
||||
Preferences window jumps around/resizes when changing rule selections
|
||||
|
Reference in New Issue
Block a user