diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt index 8742c90ebc..6cf4f6d71f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt @@ -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 diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/TODO.txt b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/TODO.txt index 8e24a25b61..67b1df9fc8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/TODO.txt +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/TODO.txt @@ -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). diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/EclipseUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/EclipseUtil.java new file mode 100644 index 0000000000..0099485761 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/EclipseUtil.java @@ -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) { } + }; +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/FileChangeReviewer.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/FileChangeReviewer.java new file mode 100644 index 0000000000..860f934ecd --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/FileChangeReviewer.java @@ -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 itemsChanged = new HashSet(); + + 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 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 itemsChanged, IFile rsc, int flags, boolean b) { + + if ((flags & IResourceDelta.CONTENT) > 0) { + itemsChanged.add( new ResourceChange(ChangeType.CHANGED, rsc, flags)); + } + } + + private void added(Set itemsChanged, IFile rsc, int flags, boolean b) { + itemsChanged.add( new ResourceChange(ChangeType.ADDED, rsc, flags)); +// System.out.println("added: " + rsc); + } +// private void changed(Set itemsChanged, IProject rsc, int flags) { +// System.out.println("changed: " + rsc); +// } +// +// +// private void removed(Set itemsChanged, IFile rsc, int flags, boolean b) { +// itemsChanged.add( new ResourceChange(ChangeType.REMOVED, rsc, flags)); +// System.out.println("removed: " + rsc); +// } +// +// private void removed(Set itemsChanged, IProject rsc, int flags) { +// System.out.println("removed: " + rsc); +// } + + +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java index 43e07652c9..0733288998 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java @@ -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 coloursByRGB = new HashMap(); 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: -// } - - } - } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java index e71f70811f..d0473db589 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java @@ -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 resources) { + public void setResources(Collection 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; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java index 7dff6ff5d2..074115e4c8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java @@ -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();) { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/GeneralPreferencesPage.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/GeneralPreferencesPage.java index a34c0f0a02..25fbee40d3 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/GeneralPreferencesPage.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/GeneralPreferencesPage.java @@ -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; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/UI_BUGs.txt b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/UI_BUGs.txt index f71ec9004c..32d673ff02 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/UI_BUGs.txt +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/UI_BUGs.txt @@ -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